diff --git a/src/mnemonic.ts b/src/mnemonic.ts index b9dba56..e9ab1e3 100644 --- a/src/mnemonic.ts +++ b/src/mnemonic.ts @@ -20,7 +20,7 @@ export class Mnemonic { static fromString(text: string) { text = text.trim(); - + Mnemonic.assertTextIsValid(text); return new Mnemonic(text); } @@ -34,13 +34,42 @@ export class Mnemonic { } deriveKey(addressIndex: number = 0, password: string = ""): UserSecretKey { - let seed = mnemonicToSeedSync(this.text, password); - let derivationPath = `${BIP44_DERIVATION_PREFIX}/${addressIndex}'`; - let derivationResult = derivePath(derivationPath, seed.toString("hex")); - let key = derivationResult.key; + const seed = mnemonicToSeedSync(this.text, password); + return this.deriveKeyWithIndex(seed, addressIndex); + } + + private deriveKeyWithIndex(seed: Buffer, addressIndex: number): UserSecretKey { + const derivationPath = `${BIP44_DERIVATION_PREFIX}/${addressIndex}'`; + const derivationResult = derivePath(derivationPath, seed.toString("hex")); + const key = derivationResult.key; return new UserSecretKey(key); } + deriveKeysWithPredicate(options: { + startAddressIndex: number, + stopAddressIndex: number, + numStop: number; + password?: string, + predicate: (index: number, userKey: UserSecretKey) => boolean + }): { index: number, userKey: UserSecretKey }[] { + const userKeys: { index: number, userKey: UserSecretKey }[] = []; + const seed = mnemonicToSeedSync(this.text, options.password || ""); + + for (let index = options.startAddressIndex; index < options.stopAddressIndex; index++) { + const userKey = this.deriveKeyWithIndex(seed, index); + + if (options.predicate(index, userKey)) { + userKeys.push({ index: index, userKey: userKey }); + } + + if (userKeys.length == options.numStop) { + break; + } + } + + return userKeys; + } + getWords(): string[] { return this.text.split(" "); } diff --git a/src/users.spec.ts b/src/users.spec.ts index ee71c03..aecdece 100644 --- a/src/users.spec.ts +++ b/src/users.spec.ts @@ -35,6 +35,23 @@ describe("test user wallets", () => { assert.equal(mnemonic.deriveKey(2).hex(), carol.secretKeyHex); }); + it("should derive keys with predicate", async function() { + this.timeout(20000); + + const mnemonic = Mnemonic.fromString(DummyMnemonic); + const keys = mnemonic.deriveKeysWithPredicate({ + startAddressIndex: 0, + stopAddressIndex: 10000, + numStop: 4, + predicate: (_index: number, userKey: UserSecretKey) => { + const pk = userKey.generatePublicKey().hex(); + return pk.endsWith("2a"); + } + }); + + assert.lengthOf(keys, 4); + }); + it("should create secret key", () => { let keyHex = alice.secretKeyHex; let fromBuffer = new UserSecretKey(Buffer.from(keyHex, "hex"));