Implement the getaccountaddress RPC command.
This commit is contained in:
parent
fa699ef4a5
commit
ac79a59c90
3 changed files with 116 additions and 1 deletions
47
account.go
47
account.go
|
@ -130,6 +130,31 @@ func (a *Account) Rollback(height int32, hash *btcwire.ShaHash) {
|
|||
}
|
||||
}
|
||||
|
||||
// AddressUsed returns whether there are any recorded transactions spending to
|
||||
// a given address. Assumming correct TxStore usage, this will return true iff
|
||||
// there are any transactions with outputs to this address in the blockchain or
|
||||
// the btcd mempool.
|
||||
func (a *Account) AddressUsed(pkHash []byte) bool {
|
||||
// This can be optimized by recording this data as it is read when
|
||||
// opening an account, and keeping it up to date each time a new
|
||||
// received tx arrives.
|
||||
|
||||
a.TxStore.RLock()
|
||||
defer a.TxStore.RUnlock()
|
||||
|
||||
for i := range a.TxStore.s {
|
||||
rtx, ok := a.TxStore.s[i].(*tx.RecvTx)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if bytes.Equal(rtx.ReceiverHash, pkHash) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CalculateBalance sums the amounts of all unspent transaction
|
||||
// outputs to addresses of a wallet and returns the balance as a
|
||||
// float64.
|
||||
|
@ -190,6 +215,28 @@ func (a *Account) CalculateAddressBalance(pubkeyHash []byte, confirms int) float
|
|||
return float64(bal) / float64(btcutil.SatoshiPerBitcoin)
|
||||
}
|
||||
|
||||
// CurrentAddress gets the most recently requested Bitcoin payment address
|
||||
// from an account. If the address has already been used (there is at least
|
||||
// one transaction spending to it in the blockchain or btcd mempool), the next
|
||||
// chained address is returned.
|
||||
func (a *Account) CurrentAddress() (string, error) {
|
||||
a.mtx.RLock()
|
||||
addr, err := a.Wallet.LastChainedAddress()
|
||||
a.mtx.RUnlock()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Get next chained address if the last one has already been used.
|
||||
pkHash, _, _ := btcutil.DecodeAddress(addr)
|
||||
if a.AddressUsed(pkHash) {
|
||||
addr, err = a.NewAddress()
|
||||
}
|
||||
|
||||
return addr, err
|
||||
}
|
||||
|
||||
// ListTransactions returns a slice of maps with details about a recorded
|
||||
// transaction. This is intended to be used for listtransactions RPC
|
||||
// replies.
|
||||
|
|
50
cmdmgr.go
50
cmdmgr.go
|
@ -44,6 +44,7 @@ var rpcHandlers = map[string]cmdHandler{
|
|||
// Standard bitcoind methods (implemented)
|
||||
"dumpprivkey": DumpPrivKey,
|
||||
"getaccount": GetAccount,
|
||||
"getaccountaddress": GetAccountAddress,
|
||||
"getaddressesbyaccount": GetAddressesByAccount,
|
||||
"getbalance": GetBalance,
|
||||
"getnewaddress": GetNewAddress,
|
||||
|
@ -61,7 +62,6 @@ var rpcHandlers = map[string]cmdHandler{
|
|||
"backupwallet": Unimplemented,
|
||||
"createmultisig": Unimplemented,
|
||||
"dumpwallet": Unimplemented,
|
||||
"getaccountaddress": Unimplemented,
|
||||
"getrawchangeaddress": Unimplemented,
|
||||
"getreceivedbyaccount": Unimplemented,
|
||||
"getreceivedbyaddress": Unimplemented,
|
||||
|
@ -369,6 +369,54 @@ func GetAccount(frontend chan []byte, icmd btcjson.Cmd) {
|
|||
ReplySuccess(frontend, cmd.Id(), aname)
|
||||
}
|
||||
|
||||
// GetAccountAddress replies to a getaccountaddress request with the most
|
||||
// recently-created chained address that has not yet been used (does not yet
|
||||
// appear in the blockchain, or any tx that has arrived in the btcd mempool).
|
||||
// If the most recently-requested address has been used, a new address (the
|
||||
// next chained address in the keypool) is used. This can fail if the keypool
|
||||
// runs out (and will return btcjson.ErrWalletKeypoolRanOut if that happens).
|
||||
func GetAccountAddress(frontend chan []byte, icmd btcjson.Cmd) {
|
||||
// Type assert icmd to access parameters.
|
||||
cmd, ok := icmd.(*btcjson.GetAccountAddressCmd)
|
||||
if !ok {
|
||||
ReplyError(frontend, icmd.Id(), &btcjson.ErrInternal)
|
||||
return
|
||||
}
|
||||
|
||||
// Lookup account for this request.
|
||||
a, err := accountstore.Account(cmd.Account)
|
||||
switch err {
|
||||
case nil:
|
||||
break
|
||||
|
||||
case ErrAcctNotExist:
|
||||
ReplyError(frontend, cmd.Id(),
|
||||
&btcjson.ErrWalletInvalidAccountName)
|
||||
|
||||
default: // all other non-nil errors
|
||||
e := &btcjson.Error{
|
||||
Code: btcjson.ErrWallet.Code,
|
||||
Message: err.Error(),
|
||||
}
|
||||
ReplyError(frontend, cmd.Id(), e)
|
||||
}
|
||||
|
||||
switch addr, err := a.CurrentAddress(); err {
|
||||
case nil:
|
||||
ReplySuccess(frontend, cmd.Id(), addr)
|
||||
|
||||
case wallet.ErrWalletLocked:
|
||||
ReplyError(frontend, cmd.Id(), &btcjson.ErrWalletKeypoolRanOut)
|
||||
|
||||
default: // all other non-nil errors
|
||||
e := &btcjson.Error{
|
||||
Code: btcjson.ErrWallet.Code,
|
||||
Message: err.Error(),
|
||||
}
|
||||
ReplyError(frontend, cmd.Id(), e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAddressBalance replies to a getaddressbalance extension request
|
||||
// by replying with the current balance (sum of unspent transaction
|
||||
// output amounts) for a single address.
|
||||
|
|
|
@ -851,6 +851,26 @@ func (w *Wallet) NextChainedAddress(bs *BlockStamp) (string, error) {
|
|||
return addr.paymentAddress(w.net)
|
||||
}
|
||||
|
||||
// LastChainedAddress returns the most recently requested chained
|
||||
// address from calling NextChainedAddress, or the root address if
|
||||
// no chained addresses have been requested.
|
||||
func (w *Wallet) LastChainedAddress() (string, error) {
|
||||
// Lookup pubkey hash for last used chained address.
|
||||
pkHash, ok := w.chainIdxMap[w.highestUsed]
|
||||
if !ok {
|
||||
return "", errors.New("chain index references unknown address")
|
||||
}
|
||||
|
||||
// Lookup address with this pubkey hash.
|
||||
addr, ok := w.addrMap[pkHash]
|
||||
if !ok {
|
||||
return "", errors.New("cannot find address by pubkey hash")
|
||||
}
|
||||
|
||||
// Create and return payment address from serialized pubkey.
|
||||
return addr.paymentAddress(w.net)
|
||||
}
|
||||
|
||||
// extendKeypool grows the keypool by n addresses.
|
||||
func (w *Wallet) extendKeypool(n uint, aeskey []byte, bs *BlockStamp) error {
|
||||
// Get last chained address. New chained addresses will be
|
||||
|
|
Loading…
Add table
Reference in a new issue