Skip to content

Commit 00a3b9b

Browse files
feat: add Wallet::get_tx_details method
1 parent 7cdc985 commit 00a3b9b

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

wallet/src/wallet/mod.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ use crate::wallet::{
7272
error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError},
7373
signer::{SignOptions, SignerError, SignerOrdering, SignersContainer, TransactionSigner},
7474
tx_builder::{FeePolicy, TxBuilder, TxParams},
75-
utils::{check_nsequence_rbf, After, Older, SecpCtx},
75+
utils::{check_nsequence_rbf, After, Older, SecpCtx, TxDetails},
7676
};
7777

7878
// re-exports
@@ -822,6 +822,31 @@ impl Wallet {
822822
.map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo))
823823
}
824824

825+
/// Build a [`TxDetails`] struct for a given transaction.
826+
///
827+
/// If the transaction with txid [`Txid`] cannot be found in the wallet's transaction graph,
828+
/// `None` is returned.
829+
pub fn get_tx_details(&self, txid: Txid) -> Option<TxDetails> {
830+
let tx: WalletTx = self.transactions().find(|c| c.tx_node.txid == txid)?;
831+
832+
let (sent, received) = self.sent_and_received(&tx.tx_node.tx);
833+
let fee: Option<Amount> = self.calculate_fee(&tx.tx_node.tx).ok();
834+
let fee_rate: Option<FeeRate> = self.calculate_fee_rate(&tx.tx_node.tx).ok();
835+
let chain_position = tx.chain_position;
836+
837+
let tx_details: TxDetails = TxDetails {
838+
txid,
839+
received,
840+
sent,
841+
fee,
842+
fee_rate,
843+
chain_position,
844+
tx: tx.tx_node.tx,
845+
};
846+
847+
Some(tx_details)
848+
}
849+
825850
/// List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).
826851
///
827852
/// To list only unspent outputs (UTXOs), use [`Wallet::list_unspent`] instead.

wallet/src/wallet/utils.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
// You may not use this file except in accordance with one or both of these
1010
// licenses.
1111

12+
use alloc::sync::Arc;
1213
use bitcoin::secp256k1::{All, Secp256k1};
13-
use bitcoin::{absolute, relative, Amount, Script, Sequence};
14-
14+
use bitcoin::{absolute, relative, Amount, FeeRate, Script, Sequence, Transaction, Txid};
15+
use chain::{ChainPosition, ConfirmationBlockTime};
1516
use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
1617

1718
use rand_core::RngCore;
@@ -133,6 +134,18 @@ pub(crate) fn shuffle_slice<T>(list: &mut [T], rng: &mut impl RngCore) {
133134

134135
pub(crate) type SecpCtx = Secp256k1<All>;
135136

137+
/// Details about a transaction the wallet knows about.
138+
#[derive(Debug)]
139+
pub struct TxDetails {
140+
pub txid: Txid,
141+
pub received: Amount,
142+
pub sent: Amount,
143+
pub fee: Option<Amount>,
144+
pub fee_rate: Option<FeeRate>,
145+
pub chain_position: ChainPosition<ConfirmationBlockTime>,
146+
pub tx: Arc<Transaction>,
147+
}
148+
136149
#[cfg(test)]
137150
mod test {
138151
// When nSequence is lower than this flag the timelock is interpreted as block-height-based,

wallet/tests/wallet.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4314,3 +4314,25 @@ fn test_wallet_transactions_relevant() {
43144314
assert!(full_tx_count_before < full_tx_count_after);
43154315
assert!(canonical_tx_count_before < canonical_tx_count_after);
43164316
}
4317+
4318+
#[test]
4319+
fn test_tx_details_method() {
4320+
let (test_wallet, txid_1) = get_funded_wallet_wpkh();
4321+
let tx_details_1_option = test_wallet.get_tx_details(txid_1);
4322+
4323+
assert!(tx_details_1_option.is_some());
4324+
let tx_details_1 = tx_details_1_option.unwrap();
4325+
4326+
assert_eq!(
4327+
tx_details_1.txid.to_string(),
4328+
"f2a03cdfe1bb6a295b0a4bb4385ca42f95e4b2c6d9a7a59355d32911f957a5b3"
4329+
);
4330+
assert_eq!(tx_details_1.received, Amount::from_sat(50000));
4331+
assert_eq!(tx_details_1.sent, Amount::from_sat(76000));
4332+
assert_eq!(tx_details_1.fee.unwrap(), Amount::from_sat(1000));
4333+
4334+
// Transaction id not part of the TxGraph
4335+
let txid_2 = Txid::from_raw_hash(Hash::all_zeros());
4336+
let tx_details_2_option = test_wallet.get_tx_details(txid_2);
4337+
assert!(tx_details_2_option.is_none());
4338+
}

0 commit comments

Comments
 (0)