From 57914c2a61cf891fa7a748d4d7f6fb64b1587888 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 22 Jul 2020 08:40:16 +0200 Subject: [PATCH] Add Secp256k1Wallet.generate --- packages/sdk38/src/wallet.spec.ts | 15 +++++++++++++++ packages/sdk38/src/wallet.ts | 18 ++++++++++++++++++ packages/sdk38/types/wallet.d.ts | 12 ++++++++++++ 3 files changed, 45 insertions(+) diff --git a/packages/sdk38/src/wallet.spec.ts b/packages/sdk38/src/wallet.spec.ts index d9992ad2..3e5322ae 100644 --- a/packages/sdk38/src/wallet.spec.ts +++ b/packages/sdk38/src/wallet.spec.ts @@ -18,6 +18,21 @@ describe("Secp256k1Wallet", () => { }); }); + describe("generate", () => { + it("defaults to 12 words", async () => { + const wallet = await Secp256k1Wallet.generate(); + expect(wallet.mnemonic.split(" ").length).toEqual(12); + }); + + it("can use different mnemonic lengths", async () => { + expect((await Secp256k1Wallet.generate(12)).mnemonic.split(" ").length).toEqual(12); + expect((await Secp256k1Wallet.generate(15)).mnemonic.split(" ").length).toEqual(15); + expect((await Secp256k1Wallet.generate(18)).mnemonic.split(" ").length).toEqual(18); + expect((await Secp256k1Wallet.generate(21)).mnemonic.split(" ").length).toEqual(21); + expect((await Secp256k1Wallet.generate(24)).mnemonic.split(" ").length).toEqual(24); + }); + }); + describe("getAccounts", () => { it("resolves to a list of accounts if enabled", async () => { const wallet = await Secp256k1Wallet.fromMnemonic(defaultMnemonic); diff --git a/packages/sdk38/src/wallet.ts b/packages/sdk38/src/wallet.ts index 1efb4075..eb3059a3 100644 --- a/packages/sdk38/src/wallet.ts +++ b/packages/sdk38/src/wallet.ts @@ -1,6 +1,7 @@ import { Bip39, EnglishMnemonic, + Random, Secp256k1, Sha256, Sha512, @@ -76,6 +77,23 @@ export class Secp256k1Wallet implements OfflineSigner { return new Secp256k1Wallet(mnemonic, privkey, Secp256k1.compressPubkey(uncompressed), prefix); } + /** + * Generates a new wallet with a BIP39 mnemonic of the given length. + * + * @param length The number of words in the mnemonic (12, 15, 18, 21 or 24). + * @param hdPath The BIP-32/SLIP-10 derivation path. Defaults to the Cosmos Hub/ATOM path `m/44'/118'/0'/0/0`. + * @param prefix The bech32 address prefix (human readable part). Defaults to "cosmos". + */ + public static async generate( + length: 12 | 15 | 18 | 21 | 24 = 12, + hdPath: readonly Slip10RawIndex[] = makeCosmoshubPath(0), + prefix = "cosmos", + ): Promise { + const entropyLength = 4 * Math.floor((11 * length) / 33); + const entropy = Random.getBytes(entropyLength); + const mnemonic = Bip39.encode(entropy); + return Secp256k1Wallet.fromMnemonic(mnemonic.toString(), hdPath, prefix); + } private readonly mnemonicData: EnglishMnemonic; private readonly pubkey: Uint8Array; diff --git a/packages/sdk38/types/wallet.d.ts b/packages/sdk38/types/wallet.d.ts index 0c29481d..0f295b04 100644 --- a/packages/sdk38/types/wallet.d.ts +++ b/packages/sdk38/types/wallet.d.ts @@ -28,6 +28,18 @@ export declare class Secp256k1Wallet implements OfflineSigner { hdPath?: readonly Slip10RawIndex[], prefix?: string, ): Promise; + /** + * Generates a new wallet with a BIP39 mnemonic of the given length. + * + * @param length The number of words in the mnemonic (12, 15, 18, 21 or 24). + * @param hdPath The BIP-32/SLIP-10 derivation path. Defaults to the Cosmos Hub/ATOM path `m/44'/118'/0'/0/0`. + * @param prefix The bech32 address prefix (human readable part). Defaults to "cosmos". + */ + static generate( + length?: 12 | 15 | 18 | 21 | 24, + hdPath?: readonly Slip10RawIndex[], + prefix?: string, + ): Promise; private readonly mnemonicData; private readonly pubkey; private readonly privkey;