wallet/pkg/eth/eth_account.go
Anton Nesterov 80299cc2c4
[init]
2024-08-31 16:55:59 +02:00

117 lines
2.2 KiB
Go

package eth
import (
"crypto/ecdsa"
"strings"
"custodial/pkg/locker"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/tyler-smith/go-bip39"
)
const MAX_ACCOUNT_INDEX int = 4294967295
type EthAccount struct {
privateKey *ecdsa.PrivateKey
publicKey *ecdsa.PublicKey
address common.Address
}
func (e *EthAccount) PrivateKey() *ecdsa.PrivateKey {
return e.privateKey
}
func (e *EthAccount) PublicKey() *ecdsa.PublicKey {
return e.publicKey
}
func (e *EthAccount) Address() common.Address {
return e.address
}
const path = "m/44'/60'/0'/0"
var master *hdkeychain.ExtendedKey
func InitMaster(mnemonic, passphrase string) {
if master != nil {
return
}
seed := bip39.NewSeed(strings.TrimSpace(mnemonic), strings.TrimSpace(passphrase))
dpath, err := accounts.ParseDerivationPath(path)
if err != nil {
panic(err)
}
key, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
panic(err)
}
for _, n := range dpath {
key, err = key.Child(n)
if err != nil {
panic(err)
}
}
master = key
privateKey, err := key.ECPrivKey()
privateKeyECDSA := privateKey.ToECDSA()
if err != nil {
panic(err)
}
publicKey := privateKeyECDSA.Public()
_, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
panic("error casting public key to ECDSA")
}
}
func InitMasterFromPrivateSettings() {
mnemonic := locker.GetPrivateEnv("BIP39_MNEMONIC")
passphrase := locker.GetPrivateEnv("PASSPHRASE")
if mnemonic == "" {
panic("BIP39_MNEMONIC is not set")
}
InitMaster(mnemonic, passphrase)
}
func DeriveAccount(index int) (*EthAccount, error) {
address, err := master.Child(uint32(index))
if err != nil {
return nil, err
}
privateKey, err := address.ECPrivKey()
privateKeyECDSA := privateKey.ToECDSA()
if err != nil {
return nil, err
}
publicKey, _ := address.ECPubKey()
publicKeyECDSA := publicKey.ToECDSA()
e := EthAccount{
privateKey: privateKeyECDSA,
publicKey: publicKeyECDSA,
address: crypto.PubkeyToAddress(*publicKeyECDSA),
}
return &e, nil
}
func GetSpender() (*EthAccount, error) {
return DeriveAccount(MAX_ACCOUNT_INDEX)
}