Search code examples
metamaskthundercore

How do I generate private keys for ThunderCore from a 12-word mnemonic seed phrase exported from TrustWallet or Metamask?


I got a 12-word mnemonic seed phrase exported from TrustWallet, however, I need it as a thunderCore private key. How do I generate the thunderCore private key from it? What if the seed phrase is export from Metamask?


Solution

  • To generate private keys from 12-word mnemonic phrases, you need a derivation path (a string) as specified in BIP-0049.

    Derivation paths used in the field:

    • m/44'/1001'/0'/0: uses the correct coin type for ThunderCore (1001) as registered in SLIP-0044, used by TrustWallet
    • "m/44'/60'/0'/0: is the derivation path used for Ethereum mainnet, used by MetaMask

    Here's a self-contained example to generate private keys from the 12-word mnemonic using the ethereum-hdwallet library:

    hdwallet.js

    const EthereumHDWallet = require('ethereum-hdwallet')
    
    // https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki
    // https://github.com/satoshilabs/slips/blob/master/slip-0044.md
    const TrustWalletHdPath = "m/44'/1001'/0'/0" // coin_type 1001 is ThunderCore, this is the recommended path
    const MetaMaskHdPath = "m/44'/60'/0'/0"      // coin_type 60 is really Ethereum, but MetaMask use it for all EVM compatible chains
    
    class HdWallet {
      constructor(mnemonic) {
        this.mnemonic = this.mnemonic
        this.w = EthereumHDWallet.fromMnemonic(mnemonic)
      }
      deriveUsingTrustWalletPath() {
        return this.w.derive(TrustWalletHdPath)
      }
      deriveUsingMetaMaskPath() {
        return this.w.derive(MetaMaskHdPath)
      }
      metaMaskAddress(index /*: number */) /*: string */ {
        return '0x' + this.deriveUsingMetaMaskPath().derive(index).getAddress().toString('hex')
      }
      trustWalletAddress(index /*: number */) /*: string */ {
        return '0x' + this.deriveUsingTrustWalletPath().derive(index).getAddress().toString('hex')
      }
      metaMaskPrivateKey(index /*: number */) /*: string */ {
        return this.deriveUsingMetaMaskPath().derive(index).getPrivateKey().toString('hex')
      }
      trustWalletPrivateKey(index /*: number */) /*: string */ {
        return this.deriveUsingTrustWalletPath().derive(index).getPrivateKey().toString('hex')
      }
    }
    
    const fromMnemonic = (s /*: string or buffer */) => {
      return new HdWallet(s)
    }
    
    module.exports = {
      fromMnemonic: fromMnemonic,
    }
    

    testHdWallet.js

    const assert = require('assert');
    const HdWallet = require('../src/hdwallet');
    
    const mnemonic = 'feel pulp crunch segment buzz turn organ broccoli elder ask phone limit';
    
    describe('fromMnemonic', () => {
      it('trustWalletAddress', async() => {
        const w = HdWallet.fromMnemonic(mnemonic);
        console.log('TrustWallet:', w.trustWalletAddress(0));
        assert('0x2323Beb990514446bA4c073C2e1A4BDC0ECf06Af'.toLowerCase() ===
                w.trustWalletAddress(0).toLowerCase());
      });
      it('metaMaskAddress', async() => {
        const w = HdWallet.fromMnemonic(mnemonic);
        console.log('MetaMask:', w.metaMaskAddress(0));
        assert('0x9A7be7ae9a2779167bc5b64d1cC672cc5b2593e4'.toLowerCase() ===
                w.metaMaskAddress(0).toLowerCase());
      });
      it('trustWalletPrivateKey', async() => {
        const w = HdWallet.fromMnemonic(mnemonic);
        console.log('TrustWallet sk:', w.trustWalletPrivateKey(0));
        assert('6d7bf444545ce47d7fda9df58275f5f4dd5eb911494ab66d81f76f1aca2b763e'.toLowerCase() ===
                w.trustWalletPrivateKey(0).toLowerCase());
      });
      it('metaMaskPrivateKey', async() => {
        const w = HdWallet.fromMnemonic(mnemonic);
        console.log('MetaMask sk:', w.metaMaskPrivateKey(0));
        assert('6aad31c479c44230721b470570c12bd3f41e71b79d8f27ca08b913cbaeac25af'.toLowerCase() ===
                w.metaMaskPrivateKey(0).toLowerCase());
      });
    })
    

    See a complete project in the hdwallet branch of the field-support repo.