Convert all tx results to use new concrete type.

This commit modifies all code paths which work with transaction result
objects to use the concrete ListTransactionsResult provided by the btcjson
package.  This provides nicer marshalling and unmarshalling as well as
access to properly typed fields.
This commit is contained in:
Dave Collins 2014-04-08 22:04:10 -05:00
parent 5194254715
commit 677ec10ee7
4 changed files with 69 additions and 70 deletions

View file

@ -21,6 +21,7 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/conformal/btcjson"
"github.com/conformal/btcutil"
"github.com/conformal/btcwallet/tx"
"github.com/conformal/btcwallet/wallet"
@ -165,29 +166,28 @@ func (a *Account) CurrentAddress() (btcutil.Address, error) {
return addr, nil
}
// ListSinceBlock returns a slice of maps with details about transactions since
// the given block. If the block is -1 then all transactions are included.
// transaction. This is intended to be used for listsinceblock RPC
// replies.
func (a *Account) ListSinceBlock(since, curBlockHeight int32, minconf int) ([]map[string]interface{}, error) {
var txInfoList []map[string]interface{}
// ListSinceBlock returns a slice of objects with details about transactions
// since the given block. If the block is -1 then all transactions are included.
// This is intended to be used for listsinceblock RPC replies.
func (a *Account) ListSinceBlock(since, curBlockHeight int32, minconf int) ([]btcjson.ListTransactionsResult, error) {
var txList []btcjson.ListTransactionsResult
for _, txRecord := range a.TxStore.SortedRecords() {
// check block number.
if since != -1 && txRecord.Height() <= since {
continue
}
txInfoList = append(txInfoList,
txList = append(txList,
txRecord.TxInfo(a.name, curBlockHeight, a.Net())...)
}
return txInfoList, nil
return txList, nil
}
// ListTransactions returns a slice of maps with details about a recorded
// ListTransactions returns a slice of objects with details about a recorded
// transaction. This is intended to be used for listtransactions RPC
// replies.
func (a *Account) ListTransactions(from, count int) ([]map[string]interface{}, error) {
func (a *Account) ListTransactions(from, count int) ([]btcjson.ListTransactionsResult, error) {
// Get current block. The block height used for calculating
// the number of tx confirmations.
bs, err := GetCurBlock()
@ -195,24 +195,24 @@ func (a *Account) ListTransactions(from, count int) ([]map[string]interface{}, e
return nil, err
}
var txInfoList []map[string]interface{}
var txList []btcjson.ListTransactionsResult
records := a.TxStore.SortedRecords()
lastLookupIdx := len(records) - count
// Search in reverse order: lookup most recently-added first.
for i := len(records) - 1; i >= from && i >= lastLookupIdx; i-- {
txInfoList = append(txInfoList,
txList = append(txList,
records[i].TxInfo(a.name, bs.Height, a.Net())...)
}
return txInfoList, nil
return txList, nil
}
// ListAddressTransactions returns a slice of maps with details about a
// ListAddressTransactions returns a slice of objects with details about
// recorded transactions to or from any address belonging to a set. This is
// intended to be used for listaddresstransactions RPC replies.
func (a *Account) ListAddressTransactions(pkHashes map[string]struct{}) (
[]map[string]interface{}, error) {
[]btcjson.ListTransactionsResult, error) {
// Get current block. The block height used for calculating
// the number of tx confirmations.
@ -221,7 +221,7 @@ func (a *Account) ListAddressTransactions(pkHashes map[string]struct{}) (
return nil, err
}
var txInfoList []map[string]interface{}
var txList []btcjson.ListTransactionsResult
for _, txRecord := range a.TxStore.SortedRecords() {
txout, ok := txRecord.(*tx.RecvTxOut)
if !ok {
@ -238,17 +238,17 @@ func (a *Account) ListAddressTransactions(pkHashes map[string]struct{}) (
if _, ok := pkHashes[string(apkh.ScriptAddress())]; ok {
info := txout.TxInfo(a.name, bs.Height, a.Net())
txInfoList = append(txInfoList, info...)
txList = append(txList, info...)
}
}
return txInfoList, nil
return txList, nil
}
// ListAllTransactions returns a slice of maps with details about a recorded
// ListAllTransactions returns a slice of objects with details about a recorded
// transaction. This is intended to be used for listalltransactions RPC
// replies.
func (a *Account) ListAllTransactions() ([]map[string]interface{}, error) {
func (a *Account) ListAllTransactions() ([]btcjson.ListTransactionsResult, error) {
// Get current block. The block height used for calculating
// the number of tx confirmations.
bs, err := GetCurBlock()
@ -258,13 +258,13 @@ func (a *Account) ListAllTransactions() ([]map[string]interface{}, error) {
// Search in reverse order: lookup most recently-added first.
records := a.TxStore.SortedRecords()
var txInfoList []map[string]interface{}
var txList []btcjson.ListTransactionsResult
for i := len(records) - 1; i >= 0; i-- {
info := records[i].TxInfo(a.name, bs.Height, a.Net())
txInfoList = append(txInfoList, info...)
txList = append(txList, info...)
}
return txInfoList, nil
return txList, nil
}
// DumpPrivKeys returns the WIF-encoded private keys for all addresses with

View file

@ -741,20 +741,20 @@ func (am *AccountManager) ListAccounts(minconf int) map[string]float64 {
return pairs
}
// ListSinceBlock returns a slice of maps of strings to interface containing
// structures defining all transactions in the wallets since the given block.
// ListSinceBlock returns a slice of objects representing all transactions in
// the wallets since the given block.
// To be used for the listsinceblock command.
func (am *AccountManager) ListSinceBlock(since, curBlockHeight int32, minconf int) ([]map[string]interface{}, error) {
func (am *AccountManager) ListSinceBlock(since, curBlockHeight int32, minconf int) ([]btcjson.ListTransactionsResult, error) {
// Create and fill a map of account names and their balances.
txInfoList := []map[string]interface{}{}
var txList []btcjson.ListTransactionsResult
for _, a := range am.AllAccounts() {
txTmp, err := a.ListSinceBlock(since, curBlockHeight, minconf)
if err != nil {
return nil, err
}
txInfoList = append(txInfoList, txTmp...)
txList = append(txList, txTmp...)
}
return txInfoList, nil
return txList, nil
}
// accountTx represents an account/transaction pair to be used by
@ -787,15 +787,13 @@ func (am *AccountManager) GetTransaction(txsha *btcwire.ShaHash) []accountTx {
return accumulatedTxen
}
// ListUnspent returns an array of objects representing the unspent
// wallet transactions fitting the given criteria. The confirmations will be
// more then minconf, less than maxconf and if addresses is populated only the
// addresses contained within it will be considered.
// a transaction on locally known wallets. If we know nothing about a
// ListUnspent returns a slice of objects representing the unspent wallet
// transactions fitting the given criteria. The confirmations will be more than
// minconf, less than maxconf and if addresses is populated only the addresses
// contained within it will be considered. If we know nothing about a
// transaction an empty array will be returned.
func (am *AccountManager) ListUnspent(minconf, maxconf int,
addresses map[string]bool) ([]*btcjson.ListUnSpentResult, error) {
bs, err := GetCurBlock()
if err != nil {
return nil, err

View file

@ -1949,9 +1949,9 @@ func NotifyWalletBalanceUnconfirmed(frontend chan []byte, account string, balanc
// NotifyNewTxDetails sends details of a new transaction to a frontend.
func NotifyNewTxDetails(frontend chan []byte, account string,
details map[string]interface{}) {
details btcjson.ListTransactionsResult) {
ntfn := btcws.NewTxNtfn(account, details)
ntfn := btcws.NewTxNtfn(account, &details)
mntfn, _ := ntfn.MarshalJSON()
frontend <- mntfn
}

View file

@ -24,6 +24,7 @@ import (
"io"
"time"
"github.com/conformal/btcjson"
"github.com/conformal/btcscript"
"github.com/conformal/btcutil"
"github.com/conformal/btcwire"
@ -56,7 +57,7 @@ type Record interface {
Time() time.Time
Tx() *btcutil.Tx
TxSha() *btcwire.ShaHash
TxInfo(string, int32, btcwire.BitcoinNet) []map[string]interface{}
TxInfo(string, int32, btcwire.BitcoinNet) []btcjson.ListTransactionsResult
}
type txRecord interface {
@ -923,10 +924,10 @@ func (st *SignedTx) Tx() *btcutil.Tx {
return st.tx
}
// TxInfo returns a slice of maps that may be marshaled as a JSON array
// TxInfo returns a slice of objects that may be marshaled as a JSON array
// of JSON objects for a listtransactions RPC reply.
func (st *SignedTx) TxInfo(account string, chainHeight int32, net btcwire.BitcoinNet) []map[string]interface{} {
reply := make([]map[string]interface{}, len(st.tx.MsgTx().TxOut))
func (st *SignedTx) TxInfo(account string, chainHeight int32, net btcwire.BitcoinNet) []btcjson.ListTransactionsResult {
reply := make([]btcjson.ListTransactionsResult, len(st.tx.MsgTx().TxOut))
var confirmations int32
if st.block != nil {
@ -939,21 +940,22 @@ func (st *SignedTx) TxInfo(account string, chainHeight int32, net btcwire.Bitcoi
if len(addrs) == 1 {
address = addrs[0].EncodeAddress()
}
info := map[string]interface{}{
"account": account,
"address": address,
"category": "send",
"amount": float64(-txout.Value) / float64(btcutil.SatoshiPerBitcoin),
"fee": float64(st.Fee()) / float64(btcutil.SatoshiPerBitcoin),
"confirmations": float64(confirmations),
"txid": st.txSha.String(),
"time": float64(st.created.Unix()),
"timereceived": float64(st.created.Unix()),
info := btcjson.ListTransactionsResult{
Account: account,
Address: address,
Category: "send",
Amount: float64(-txout.Value) / float64(btcutil.SatoshiPerBitcoin),
Fee: float64(st.Fee()) / float64(btcutil.SatoshiPerBitcoin),
Confirmations: int64(confirmations),
TxID: st.txSha.String(),
Time: st.created.Unix(),
TimeReceived: st.created.Unix(),
}
if st.block != nil {
info["blockhash"] = st.block.Hash.String()
info["blockindex"] = float64(st.block.Index)
info["blocktime"] = float64(st.block.Time.Unix())
info.BlockHash = st.block.Hash.String()
info.BlockIndex = int64(st.block.Index)
info.BlockTime = st.block.Time.Unix()
}
reply[i] = info
}
@ -1330,9 +1332,9 @@ func (rt *RecvTxOut) Tx() *btcutil.Tx {
return rt.tx
}
// TxInfo returns a slice of maps that may be marshaled as a JSON array
// TxInfo returns a slice of objects that may be marshaled as a JSON array
// of JSON objects for a listtransactions RPC reply.
func (rt *RecvTxOut) TxInfo(account string, chainHeight int32, net btcwire.BitcoinNet) []map[string]interface{} {
func (rt *RecvTxOut) TxInfo(account string, chainHeight int32, net btcwire.BitcoinNet) []btcjson.ListTransactionsResult {
tx := rt.tx.MsgTx()
outidx := rt.outpoint.Index
txout := tx.TxOut[outidx]
@ -1343,23 +1345,22 @@ func (rt *RecvTxOut) TxInfo(account string, chainHeight int32, net btcwire.Bitco
address = addrs[0].EncodeAddress()
}
txInfo := map[string]interface{}{
"account": account,
"category": "receive",
"address": address,
"amount": float64(txout.Value) / float64(btcutil.SatoshiPerBitcoin),
"txid": rt.outpoint.Hash.String(),
"timereceived": float64(rt.received.Unix()),
result := btcjson.ListTransactionsResult{
Account: account,
Category: "receive",
Address: address,
Amount: float64(txout.Value) / float64(btcutil.SatoshiPerBitcoin),
TxID: rt.outpoint.Hash.String(),
TimeReceived: rt.received.Unix(),
}
if rt.block != nil {
txInfo["blockhash"] = rt.block.Hash.String()
txInfo["blockindex"] = float64(rt.block.Index)
txInfo["blocktime"] = float64(rt.block.Time.Unix())
txInfo["confirmations"] = float64(chainHeight - rt.block.Height + 1)
result.BlockHash = rt.block.Hash.String()
result.BlockIndex = int64(rt.block.Index)
result.BlockTime = rt.block.Time.Unix()
result.Confirmations = int64(chainHeight - rt.block.Height + 1)
} else {
txInfo["confirmations"] = float64(0)
result.Confirmations = 0
}
return []map[string]interface{}{txInfo}
return []btcjson.ListTransactionsResult{result}
}