diff --git a/packages/harmony-account/src/hdnode.ts b/packages/harmony-account/src/hdnode.ts new file mode 100644 index 0000000..3b2dddb --- /dev/null +++ b/packages/harmony-account/src/hdnode.ts @@ -0,0 +1,48 @@ +import { bip39, hdkey } from '@harmony-js/crypto'; +import { HDPath } from '@harmony-js/utils'; + +export class HDNode extends hdkey { + static new() { + return new HDNode(bip39.generateMnemonic(), 0); + } + static add(phrase: string, index: number) { + return new HDNode(phrase, index); + } + static isValidMnemonic(phrase: string): boolean { + if (phrase.trim().split(/\s+/g).length < 12) { + return false; + } + return bip39.validateMnemonic(phrase); + } + static generateMnemonic(): string { + return bip39.generateMnemonic(); + } + private path: string; + private mnemonic?: string; + private entropy?: string; + private childKey?: hdkey; + + constructor(menmonic?: string, index: number = 0) { + super(); + this.path = HDPath; + this.mnemonic = menmonic; + this.entropy = this.mnemonic ? this.getEntropy(this.mnemonic) : undefined; + this.childKey = this.entropy + ? this.getChildKey(this.entropy, index) + : undefined; + } + + getEntropy(mnemonic: string) { + return bip39.mnemonicToEntropy(mnemonic); + } + getChildKey(entropy: string, index: number) { + const master = HDNode.fromMasterSeed(Buffer.from(entropy, 'hex')); + return master.derive(`${this.path}${index}`); + } + get _privateKey() { + return this.childKey ? this.childKey.privateKey.toString('hex') : ''; + } + get _publicKey() { + return this.childKey ? this.childKey.publicKey.toString('hex') : ''; + } +} diff --git a/packages/harmony-account/src/index.ts b/packages/harmony-account/src/index.ts index 88db089..181fc3e 100644 --- a/packages/harmony-account/src/index.ts +++ b/packages/harmony-account/src/index.ts @@ -2,3 +2,4 @@ export * from './account'; export * from './wallet'; export * from './types'; export * from './utils'; +export * from './hdnode'; diff --git a/packages/harmony-account/src/wallet.ts b/packages/harmony-account/src/wallet.ts index 852c4b1..22022cd 100644 --- a/packages/harmony-account/src/wallet.ts +++ b/packages/harmony-account/src/wallet.ts @@ -1,8 +1,8 @@ import { bip39, hdkey, EncryptOptions, getAddress } from '@harmony-js/crypto'; import { Messenger } from '@harmony-js/network'; import { isPrivateKey, isAddress } from '@harmony-js/utils'; -import { Account } from './account'; import { Transaction } from '@harmony-js/transaction'; +import { Account } from './account'; import { defaultMessenger } from './utils'; class Wallet { diff --git a/packages/harmony-contract/src/abi/abiCoder.ts b/packages/harmony-contract/src/abi/abiCoder.ts index 3adccd9..4aea770 100644 --- a/packages/harmony-contract/src/abi/abiCoder.ts +++ b/packages/harmony-contract/src/abi/abiCoder.ts @@ -19,7 +19,7 @@ import { checkNew, bytesPadRight, } from '@harmony-js/crypto'; -import { hexToBN } from '@harmony-js/utils'; +import { hexToBN, defineReadOnly } from '@harmony-js/utils'; const NegativeOne: BN = new BN(-1); const One: BN = new BN(1); @@ -1130,14 +1130,6 @@ function splitNesting(value: string): any[] { return result; } -export function defineReadOnly(object: any, name: string, value: any): void { - Object.defineProperty(object, name, { - enumerable: true, - value, - writable: false, - }); -} - // @TODO: Is there a way to return "class"? const paramTypeSimple: { [key: string]: any } = { address: CoderAddress, diff --git a/packages/harmony-crypto/src/keystore.ts b/packages/harmony-crypto/src/keystore.ts index c51449b..9179792 100644 --- a/packages/harmony-crypto/src/keystore.ts +++ b/packages/harmony-crypto/src/keystore.ts @@ -5,13 +5,7 @@ import uuid from 'uuid'; import { isPrivateKey } from '@harmony-js/utils'; import { randomBytes } from './random'; import { getAddressFromPrivateKey } from './keyTool'; -import { - concat, - // arrayify, - // hexDataLength, - // hexToByteArray, - hexToIntArray, -} from './bytes'; +import { concat, hexToIntArray } from './bytes'; import { keccak256 } from './keccak256'; import { KDF, diff --git a/packages/harmony-utils/src/chain.ts b/packages/harmony-utils/src/chain.ts index 4397d2e..94d93eb 100644 --- a/packages/harmony-utils/src/chain.ts +++ b/packages/harmony-utils/src/chain.ts @@ -41,3 +41,5 @@ export abstract class HarmonyCore { return this.chainId; } } + +export const HDPath = `m/44'/60'/0'/0/`; diff --git a/packages/harmony-utils/src/index.ts b/packages/harmony-utils/src/index.ts index d23298a..f444916 100644 --- a/packages/harmony-utils/src/index.ts +++ b/packages/harmony-utils/src/index.ts @@ -2,3 +2,4 @@ export * from './validators'; export * from './transformers'; export * from './utils'; export * from './chain'; +export * from './tools'; diff --git a/packages/harmony-utils/src/tools.ts b/packages/harmony-utils/src/tools.ts new file mode 100644 index 0000000..6f8905e --- /dev/null +++ b/packages/harmony-utils/src/tools.ts @@ -0,0 +1,7 @@ +export function defineReadOnly(object: any, name: string, value: any): void { + Object.defineProperty(object, name, { + enumerable: true, + value, + writable: false, + }); +}