func(s*PersonalAccountAPI)DeriveAccount(urlstring,pathstring,pin*bool)(accounts.Account,error){wallet,err:=s.am.Wallet(url)iferr!=nil{returnaccounts.Account{},err}derivPath,err:=accounts.ParseDerivationPath(path)iferr!=nil{returnaccounts.Account{},err}ifpin==nil{pin=new(bool)}returnwallet.Derive(derivPath,*pin)}// DeriveAccount requests an HD wallet to derive a new account, optionally pinning// it for later reuse.
EcRecover returns the address for the account that was used to create the signature. Note, this function is compatible with eth_sign and personal_sign. As such it recovers the address of: hash = keccak256(“\x19Ethereum Signed Message:\n”${message length}${message}) addr = ecrecover(hash, signature)
Note, the signature must conform to the secp256k1 curve R, S and V values, where the V value must be 27 or 28 for legacy reasons.
func(s*PersonalAccountAPI)EcRecover(ctxcontext.Context,data,sighexutil.Bytes)(common.Address,error){iflen(sig)!=crypto.SignatureLength{returncommon.Address{},fmt.Errorf("signature must be %d bytes long",crypto.SignatureLength)}ifsig[crypto.RecoveryIDOffset]!=27&&sig[crypto.RecoveryIDOffset]!=28{returncommon.Address{},errors.New("invalid Ethereum signature (V is not 27 or 28)")}sig[crypto.RecoveryIDOffset]-=27rpk,err:=crypto.SigToPub(accounts.TextHash(data),sig)iferr!=nil{returncommon.Address{},err}returncrypto.PubkeyToAddress(*rpk),nil}// EcRecover returns the address for the account that was used to create the signature.// Note, this function is compatible with eth_sign and personal_sign. As such it recovers// the address of:// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message})// addr = ecrecover(hash, signature)//// Note, the signature must conform to the secp256k1 curve R, S and V values, where// the V value must be 27 or 28 for legacy reasons.//// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
func(s*PersonalAccountAPI)ImportRawKey(privkeystring,passwordstring)(common.Address,error){key,err:=crypto.HexToECDSA(privkey)iferr!=nil{returncommon.Address{},err}ks,err:=fetchKeystore(s.am)iferr!=nil{returncommon.Address{},err}acc,err:=ks.ImportECDSA(key,password)returnacc.Address,err}// ImportRawKey stores the given hex encoded ECDSA key into the key directory,// encrypting it with the passphrase.
func(s*PersonalAccountAPI)InitializeWallet(ctxcontext.Context,urlstring)(string,error){wallet,err:=s.am.Wallet(url)iferr!=nil{return"",err}entropy,err:=bip39.NewEntropy(256)iferr!=nil{return"",err}mnemonic,err:=bip39.NewMnemonic(entropy)iferr!=nil{return"",err}seed:=bip39.NewSeed(mnemonic,"")switchwallet:=wallet.(// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key.type){case*scwallet.Wallet:returnmnemonic,wallet.Initialize(seed)default:return"",errors.New("specified wallet does not support initialization")}}
func(s*PersonalAccountAPI)ListAccounts()[// ListAccounts will return a list of addresses for accounts this node manages.]common.Address{returns.am.Accounts()}
func(s*PersonalAccountAPI)ListWallets()[// ListWallets will return a list of wallets this node manages.]rawWallet{wallets:=make([]rawWallet,0)for_,wallet:=ranges.am.Wallets(){status,failure:=wallet.Status()raw:=rawWallet{URL:wallet.URL().String(),Status:status,Accounts:wallet.Accounts()}iffailure!=nil{raw.Failure=failure.Error()}wallets=append(wallets,raw)}returnwallets}
func(s*PersonalAccountAPI)LockAccount(addrcommon.Address)bool{ifks,err:=fetchKeystore(s.am);err==nil{returnks.Lock(addr)==nil}returnfalse}// LockAccount will lock the account associated with the given address when it's unlocked.
func(s*PersonalAccountAPI)NewAccount(passwordstring)(common.AddressEIP55,error){ks,err:=fetchKeystore(s.am)iferr!=nil{returncommon.AddressEIP55{},err}acc,err:=ks.NewAccount(password)iferr==nil{addrEIP55:=common.AddressEIP55(acc.Address)log.Info("Your new key was generated","address",addrEIP55.String())log.Warn("Please backup your key file!","path",acc.URL.Path)log.Warn("Please remember your password!")returnaddrEIP55,nil}returncommon.AddressEIP55{},err}// NewAccount will create a new account and returns the address for the new account.
OpenWallet initiates a hardware wallet opening procedure, establishing a USB connection and attempting to authenticate via the provided passphrase. Note, the method may return an extra challenge requiring a second open (e.g. the Trezor PIN matrix challenge).
func(s*PersonalAccountAPI)OpenWallet(urlstring,passphrase*string)error{wallet,err:=s.am.Wallet(url)iferr!=nil{returnerr}pass:=""ifpassphrase!=nil{pass=*passphrase}returnwallet.Open(pass)}// OpenWallet initiates a hardware wallet opening procedure, establishing a USB// connection and attempting to authenticate via the provided passphrase. Note,// the method may return an extra challenge requiring a second open (e.g. the// Trezor PIN matrix challenge).
SendTransaction will create a transaction from the given arguments and tries to sign it with the key associated with args.From. If the given passwd isn’t able to decrypt the key it fails.
func(s*PersonalAccountAPI)SendTransaction(ctxcontext.Context,argsTransactionArgs,passwdstring)(common.Hash,error){ifargs.Nonce==nil{s.nonceLock.LockAddr(args.from())defers.nonceLock.UnlockAddr(args.from())}signed,err:=s.signTransaction(ctx,&args,passwd)iferr!=nil{log.Warn("Failed transaction send attempt","from",args.from(),"to",args.To,"value",args.Value.ToInt(),"err",err)returncommon.Hash{},err}returnSubmitTransaction(ctx,s.b,signed)}// SendTransaction will create a transaction from the given arguments and// tries to sign it with the key associated with args.From. If the given// passwd isn't able to decrypt the key it fails.
func(s*PersonalAccountAPI)Sign(ctxcontext.Context,datahexutil.Bytes,addrcommon.Address,passwdstring)(hexutil.Bytes,error){account:=accounts.Account{Address:addr}wallet,err:=s.b.AccountManager().Find(account)iferr!=nil{returnnil,err}signature,err:=wallet.SignTextWithPassphrase(account,passwd,data)iferr!=nil{log.Warn("Failed data sign attempt","address",addr,"err",err)returnnil,err}signature[crypto.RecoveryIDOffset]+=27returnsignature,nil}// Sign calculates an Ethereum ECDSA signature for:// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))//// Note, the produced signature conforms to the secp256k1 curve R, S and V values,// where the V value will be 27 or 28 for legacy reasons.//// The key used to calculate the signature is decrypted with the given password.//// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
SignTransaction will create a transaction from the given arguments and tries to sign it with the key associated with args.From. If the given passwd isn’t able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast to other nodes
func(s*PersonalAccountAPI)SignTransaction(ctxcontext.Context,argsTransactionArgs,passwdstring)(*SignTransactionResult,error){ifargs.From==nil{returnnil,errors.New("sender not specified")}ifargs.Gas==nil{returnnil,errors.New("gas not specified")}ifargs.GasPrice==nil&&(args.MaxFeePerGas==nil||args.MaxPriorityFeePerGas==nil){returnnil,errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")}ifargs.Nonce==nil{returnnil,errors.New("nonce not specified")}tx:=args.toTransaction()iferr:=checkTxFee(tx.GasPrice(),tx.Gas(),s.b.RPCTxFeeCap());err!=nil{returnnil,err}signed,err:=s.signTransaction(ctx,&args,passwd)iferr!=nil{log.Warn("Failed transaction sign attempt","from",args.from(),"to",args.To,"value",args.Value.ToInt(),"err",err)returnnil,err}data,err:=signed.MarshalBinary()iferr!=nil{returnnil,err}return&SignTransactionResult{data,signed},nil}// SignTransaction will create a transaction from the given arguments and// tries to sign it with the key associated with args.From. If the given passwd isn't// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast// to other nodes
UnlockAccount will unlock the account associated with the given address with the given password for duration seconds. If duration is nil it will use a default of 300 seconds. It returns an indication if the account was unlocked.
func(s*PersonalAccountAPI)UnlockAccount(ctxcontext.Context,addrcommon.Address,passwordstring,duration*uint64)(bool,error){ifs.b.ExtRPCEnabled()&&!s.b.AccountManager().Config().InsecureUnlockAllowed{returnfalse,errors.New("account unlock with HTTP access is forbidden")}constmax=uint64(time.Duration(math.MaxInt64)/time.Second)vardtime.Durationifduration==nil{d=300*time.Second}elseif*duration>max{returnfalse,errors.New("unlock duration too large")}else{d=time.Duration(*duration)*time.Second}ks,err:=fetchKeystore(s.am)iferr!=nil{returnfalse,err}err=ks.TimedUnlock(accounts.Account{Address:addr},password,d)iferr!=nil{log.Warn("Failed account unlock attempt","address",addr,"err",err)}returnerr==nil,err}// UnlockAccount will unlock the account associated with the given address with// the given password for duration seconds. If duration is nil it will use a// default of 300 seconds. It returns an indication if the account was unlocked.
func(s*PersonalAccountAPI)Unpair(ctxcontext.Context,urlstring,pinstring)error{wallet,err:=s.am.Wallet(url)iferr!=nil{returnerr}switchwallet:=wallet.(// Unpair deletes a pairing between wallet and geth.type){case*scwallet.Wallet:returnwallet.Unpair([]byte(pin))default:returnerrors.New("specified wallet does not support pairing")}}