From bb1f86b6d01e27d7ff0ec5fb27fb523b5c0f6b1a Mon Sep 17 00:00:00 2001 From: Bjarne Magnussen Date: Thu, 2 Dec 2021 11:38:05 +0100 Subject: [PATCH] wallet: add GetTransaction returning data for any transaction --- wallet/wallet.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/wallet/wallet.go b/wallet/wallet.go index 362ca9b787..b388db37d1 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -2522,6 +2522,10 @@ type GetTransactionResult struct { func (w *Wallet) GetTransaction(txHash chainhash.Hash) (*GetTransactionResult, error) { + var bestHeight int32 + var blockHash *chainhash.Hash + + var summary *TransactionSummary var res GetTransactionResult err := walletdb.View(w.db, func(dbtx walletdb.ReadTx) error { txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey) @@ -2536,11 +2540,13 @@ func (w *Wallet) GetTransaction(txHash chainhash.Hash) (*GetTransactionResult, return fmt.Errorf("%w: txid %v", ErrNoTx, txHash) } + // Otherwise, we create a summary of the transaction detail. res = GetTransactionResult{ Summary: makeTxSummary(dbtx, w, txDetail), Timestamp: txDetail.Block.Time.Unix(), Confirmations: txDetail.Block.Height, } + summary = &res.Summary // If it is a confirmed transaction we set the corresponding // block height and hash. @@ -2554,6 +2560,85 @@ func (w *Wallet) GetTransaction(txHash chainhash.Hash) (*GetTransactionResult, if err != nil { return nil, err } + + // If the transaction was not found in the transaction store, we need to + // build the TransactionSummary from the backend RPC response. + if summary == nil { + chainClient, err := w.requireChainClient() + if err != nil { + return nil, err + } + + // Get the transaction data from the backend endpoint. + var txResult *btcjson.TxRawResult + switch client := chainClient.(type) { + case *chain.RPCClient: + txResult, err = client.GetRawTransactionVerbose(&txHash) + if err != nil { + return nil, err + } + case *chain.BitcoindClient: + txResult, err = client.GetRawTransactionVerbose(&txHash) + if err != nil { + return nil, err + } + + txRaw, err := hex.DecodeString(txResult.Hex) + if err != nil { + return nil, err + } + + summary = &TransactionSummary{ + Hash: &txHash, + Transaction: txRaw, + MyInputs: make([]TransactionSummaryInput, 0), + MyOutputs: make([]TransactionSummaryOutput, 0), + Timestamp: txResult.Time, + } + + // For a confirmed transaction we must decode the block hash and + // get the block height. + if txResult.BlockHash != "" { + blockHash, err = chainhash.NewHashFromStr( + txResult.BlockHash, + ) + if err != nil { + return nil, err + } + + // Obtain the block height from the backend. + switch client := chainClient.(type) { + case *chain.RPCClient: + header, err := client.GetBlockHeaderVerbose( + blockHash, + ) + if err != nil { + return nil, err + } + bestHeight = header.Height + case *chain.BitcoindClient: + bestHeight, err = client.GetBlockHeight( + blockHash, + ) + if err != nil { + return nil, err + } + } + } + + // Set the TransactionSummary in the GetTransactionResult. + res.Summary = *summary + res.Height = bestHeight + res.BlockHash = summary.Hash + res.Timestamp = summary.Timestamp + + // Calculate the number of confirmations. + if res.Height != -1 { + res.Confirmations = bestHeight - res.Height + 1 + } + } + + // Return the result. return &res, nil }