diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index 8e697a2a9a..4429bb52c0 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use bdk_chain::collections::btree_map; use bdk_chain::{ - bitcoin::{BlockHash, OutPoint, ScriptBuf, Txid}, + bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, collections::BTreeMap, local_chain::{self, CheckPoint}, BlockId, ConfirmationTimeHeightAnchor, TxGraph, @@ -204,6 +204,24 @@ impl EsploraAsyncExt for esplora_client::AsyncClient { if let Some(anchor) = anchor_from_status(&tx.status) { let _ = graph.insert_anchor(tx.txid, anchor); } + + let previous_outputs = tx.vin.iter().filter_map(|vin| { + let prevout = vin.prevout.as_ref()?; + Some(( + OutPoint { + txid: vin.txid, + vout: vin.vout, + }, + TxOut { + script_pubkey: prevout.scriptpubkey.clone(), + value: prevout.value, + }, + )) + }); + + for (outpoint, txout) in previous_outputs { + let _ = graph.insert_txout(outpoint, txout); + } } } diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index a7ee290b00..4aa11c5819 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -3,7 +3,7 @@ use std::thread::JoinHandle; use bdk_chain::collections::btree_map; use bdk_chain::collections::BTreeMap; use bdk_chain::{ - bitcoin::{BlockHash, OutPoint, ScriptBuf, Txid}, + bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, local_chain::{self, CheckPoint}, BlockId, ConfirmationTimeHeightAnchor, TxGraph, }; @@ -194,6 +194,24 @@ impl EsploraExt for esplora_client::BlockingClient { if let Some(anchor) = anchor_from_status(&tx.status) { let _ = graph.insert_anchor(tx.txid, anchor); } + + let previous_outputs = tx.vin.iter().filter_map(|vin| { + let prevout = vin.prevout.as_ref()?; + Some(( + OutPoint { + txid: vin.txid, + vout: vin.vout, + }, + TxOut { + script_pubkey: prevout.scriptpubkey.clone(), + value: prevout.value, + }, + )) + }); + + for (outpoint, txout) in previous_outputs { + let _ = graph.insert_txout(outpoint, txout); + } } } diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index 3124bd2d11..ccbf839a95 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -109,6 +109,31 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { ) .await?; + // Check that there are exactly two transactions. + assert_eq!(graph_update.full_txs().count(), 2); + + // Check to see if we have the floating txouts available from our two created transactions' + // previous outputs in order to calculate transaction fees. + for tx in graph_update.full_txs() { + // Retrieve the calculated fee from `TxGraph`, which will panic if we do not have the + // floating txouts available from the transactions' previous outputs. + let fee = graph_update.calculate_fee(tx.tx).expect("Fee must exist"); + + // Retrieve the fee in the transaction data from `bitcoind`. + let tx_fee = env + .bitcoind + .client + .get_transaction(&tx.txid, None) + .expect("Tx must exist") + .fee + .expect("Fee must exist") + .abs() + .to_sat() as u64; + + // Check that the calculated fee matches the fee from the transaction data. + assert_eq!(fee, tx_fee); + } + let mut graph_update_txids: Vec = graph_update.full_txs().map(|tx| tx.txid).collect(); graph_update_txids.sort(); let mut expected_txids = vec![txid1, txid2]; diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index b91231d1d1..2e20d9d500 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -136,6 +136,31 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { 1, )?; + // Check that there are exactly two transactions. + assert_eq!(graph_update.full_txs().count(), 2); + + // Check to see if we have the floating txouts available from our two created transactions' + // previous outputs in order to calculate transaction fees. + for tx in graph_update.full_txs() { + // Retrieve the calculated fee from `TxGraph`, which will panic if we do not have the + // floating txouts available from the transactions' previous outputs. + let fee = graph_update.calculate_fee(tx.tx).expect("Fee must exist"); + + // Retrieve the fee in the transaction data from `bitcoind`. + let tx_fee = env + .bitcoind + .client + .get_transaction(&tx.txid, None) + .expect("Tx must exist") + .fee + .expect("Fee must exist") + .abs() + .to_sat() as u64; + + // Check that the calculated fee matches the fee from the transaction data. + assert_eq!(fee, tx_fee); + } + let mut graph_update_txids: Vec = graph_update.full_txs().map(|tx| tx.txid).collect(); graph_update_txids.sort(); let mut expected_txids = vec![txid1, txid2];