Search code examples
goethereumgo-ethereum

Getting Address and Private Key for Mnemonic


I am basically trying to get public and private keys by derivation paths from seed phrases for Ethereum accounts using Golang. I have this:

package generator

import (
    "fmt"

    "github.com/tyler-smith/go-bip32"
    "github.com/tyler-smith/go-bip39"
)

type HDWallet struct{}

const BIP_PATH = "m/44'/60'/0'/0/0"

func (wallet *HDWallet) GenerateAddressAndPrivateKey(seedPhrase string) (string, string, error) {
    seed, err := bip39.NewSeedWithErrorChecking(seedPhrase, "")
    if err != nil {
        return "", "", err
    }

    masterKey, err := bip32.NewMasterKey(seed)
    if err != nil {
        return "", "", err
    }

    publicKey := masterKey.PublicKey()
    if err != nil {
        return "", "", err
    }

    return ???, ???, nil
}

I have the master key but how do I get derived accounts (public and private keys)?


Solution

  • package main
    
    import (
        "crypto/ecdsa"
        "fmt"
        "log"
    
        "github.com/ethereum/go-ethereum/crypto"
        "github.com/tyler-smith/go-bip32"
        "github.com/tyler-smith/go-bip39"
    )
    
    func main() {
        seed := bip39.NewSeed("your seed phrase", "")
        masterPrivateKey, _ := bip32.NewMasterKey(seed)
        purposeKey, err := masterPrivateKey.NewChildKey(bip32.FirstHardenedChild + 44)
        if err != nil {
            log.Fatal(err)
        }
        coinTypeKey, err := purposeKey.NewChildKey(bip32.FirstHardenedChild + 60)
        if err != nil {
            log.Fatal(err)
        }
        accountKey, err := coinTypeKey.NewChildKey(bip32.FirstHardenedChild)
        if err != nil {
            log.Fatal(err)
        }
        changeKey, err := accountKey.NewChildKey(0)
        if err != nil {
            log.Fatal(err)
        }
        addressKey, err := changeKey.NewChildKey(0)
        if err != nil {
            log.Fatal(err)
        }
    
        ecdaPrivateKey := crypto.ToECDSAUnsafe(addressKey.Key)
        ecdaPublicKey := ecdaPrivateKey.Public().(*ecdsa.PublicKey)
    
        address := crypto.PubkeyToAddress(*ecdaPublicKey)
        fmt.Println("address:", address.Hex())
    }
    

    I checked the address with that in metamask, and they are same.