Search code examples
ethereum

nodejs bip39 seed with hdkey.fromMasterSeed


edit: solved

I am running into a weird error while trying to implement bip39/bip32. I've tried both the hdkey library and hdkey from ethereumjs-wallet and both fail with the same error when I try to do hdkey.fromMasterSeed where the master seed is a buffer returned from bip39 lib's mnemonicToSeedSync function. For some reason, I am getting this error:

Expected private key to be an Uint8Array

28 | 29 | const seed = mnemonicToSeedSync(mnemonic); 30 | const hdWallet = hdkey.fromMasterSeed(seed); | ^ 31 | const wallet = hdWallet 32 | .derivePath(EthereumECIES.primaryKeyDerivationPath) 33 | .getWallet();

at assert (../../node_modules/secp256k1/lib/index.js:18:20) at isUint8Array (../../node_modules/secp256k1/lib/index.js:22:3) at Object.privateKeyVerify (../../node_modules/secp256k1/lib/index.js:66:7) at Object.privateKeyVerify (../../node_modules/ethereum-cryptography/src/shims/hdkey-secp256k1v3.ts:4:20) at HDKey.set (../../node_modules/ethereum-cryptography/vendor/hdkey-without-crypto.js:46:26) at Function.Object..HDKey.fromMasterSeed (../../node_modules/ethereum-cryptography/vendor/hdkey-without-crypto.js:194:20) at Function.fromMasterSeed (../../node_modules/ethereumjs-wallet/src/hdkey.ts:13:36) at Function.generateKeyPairFromMnemonic (src/lib/cryptoWallet.ts:30:28) at Object. (src/lib/cryptoWallet.spec.ts:8:29)

Any ideas why this is happening? It is a typescript project in an nx monorepo with node 20

I've tried the hdkey library and the hdkey from ethereumjs-wallet and both run into exactly the same problem. I'm confident I've got a Buffer coming out of the mnemonicToSeedSync function via step-debugging.

It seems like there is an incompatibility somewhere in the child dependencies. I'm not sure how to resolve it.


Solution

  • I ended up solving it with ethereumjs-wallet. Code is here: https://github.com/Digital-Defiance/BrightChain/blob/main/brightchain-lib/src/lib/staticHelpers.ECIES.ts

    Gist is as follows- excerpt from a class:

    public static readonly primaryKeyDerivationPath = "m/44'/60'/0'/0/0";
    
    public static walletFromSeed(seed: Buffer): Wallet {
      const hdWallet = hdkey.fromMasterSeed(seed);
      return hdWallet
        .derivePath(StaticHelpersECIES.primaryKeyDerivationPath)
        .getWallet();
    }
    
      public static walletAndSeedFromMnemonic(mnemonic: string): {
        seed: SecureBuffer;
        wallet: Wallet;
      } {
        if (!validateMnemonic(mnemonic)) {
          throw new Error('Invalid mnemonic');
        }
    
        const seed = mnemonicToSeedSync(mnemonic);
        const wallet = StaticHelpersECIES.walletFromSeed(seed);
    
        return {
          seed: new SecureBuffer(seed),
          wallet,
        };
      }