Skip to content

Commit b22e3f7

Browse files
committed
feat(client): add get_tx_outspends
1 parent 5f531dc commit b22e3f7

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

src/async.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use reqwest::{header, Client, Response};
3030

3131
use crate::api::AddressStats;
3232
use crate::{
33-
BlockStatus, BlockSummary, Builder, Error, MerkleProof, OutputStatus, Tx, TxStatus, Utxo,
34-
BASE_BACKOFF_MILLIS, RETRYABLE_ERROR_CODES,
33+
BlockStatus, BlockSummary, Builder, Error, MerkleProof, OutputSpendStatus, OutputStatus, Tx,
34+
TxStatus, Utxo, BASE_BACKOFF_MILLIS, RETRYABLE_ERROR_CODES,
3535
};
3636

3737
#[derive(Debug, Clone)]
@@ -315,6 +315,12 @@ impl<S: Sleeper> AsyncClient<S> {
315315
self.get_opt_response_json(&format!("/tx/{txid}")).await
316316
}
317317

318+
/// Get the spend status of a [`Transaction`]'s outputs, given it's [`Txid`].
319+
pub async fn get_tx_outspends(&self, txid: &Txid) -> Result<Vec<OutputSpendStatus>, Error> {
320+
self.get_response_json(&format!("/tx/{txid}/outspends"))
321+
.await
322+
}
323+
318324
/// Get a [`BlockHeader`] given a particular block hash.
319325
pub async fn get_header_by_hash(&self, block_hash: &BlockHash) -> Result<BlockHeader, Error> {
320326
self.get_response_hex(&format!("/block/{block_hash}/header"))

src/blocking.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use bitcoin::{
3131

3232
use crate::api::AddressStats;
3333
use crate::{
34-
BlockStatus, BlockSummary, Builder, Error, MerkleProof, OutputStatus, Tx, TxStatus, Utxo,
35-
BASE_BACKOFF_MILLIS, RETRYABLE_ERROR_CODES,
34+
BlockStatus, BlockSummary, Builder, Error, MerkleProof, OutputSpendStatus, OutputStatus, Tx,
35+
TxStatus, Utxo, BASE_BACKOFF_MILLIS, RETRYABLE_ERROR_CODES,
3636
};
3737

3838
#[derive(Debug, Clone)]
@@ -229,6 +229,11 @@ impl BlockingClient {
229229
self.get_opt_response_json(&format!("/tx/{txid}"))
230230
}
231231

232+
/// Get the spend status of a [`Transaction`]'s outputs, given it's [`Txid`].
233+
pub fn get_tx_outspends(&self, txid: &Txid) -> Result<Vec<OutputSpendStatus>, Error> {
234+
self.get_response_json(&format!("/tx/{txid}/outspends"))
235+
}
236+
232237
/// Get a [`BlockHeader`] given a particular block hash.
233238
pub fn get_header_by_hash(&self, block_hash: &BlockHash) -> Result<BlockHeader, Error> {
234239
self.get_response_hex(&format!("/block/{block_hash}/header"))

src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,4 +1067,36 @@ mod test {
10671067
assert_ne!(address_utxos_async.len(), 0);
10681068
assert_eq!(address_utxos_blocking, address_utxos_async);
10691069
}
1070+
1071+
#[cfg(all(feature = "blocking", feature = "async"))]
1072+
#[tokio::test]
1073+
async fn test_get_tx_outspends() {
1074+
let (blocking_client, async_client) = setup_clients().await;
1075+
1076+
let address = BITCOIND
1077+
.client
1078+
.new_address_with_type(AddressType::Legacy)
1079+
.unwrap();
1080+
1081+
let txid = BITCOIND
1082+
.client
1083+
.send_to_address(&address, Amount::from_sat(21000))
1084+
.unwrap()
1085+
.txid()
1086+
.unwrap();
1087+
1088+
let _miner = MINER.lock().await;
1089+
generate_blocks_and_wait(1);
1090+
1091+
let txid_outspends_blocking = blocking_client.get_tx_outspends(&txid).unwrap();
1092+
let txid_outspends_async = async_client.get_tx_outspends(&txid).await.unwrap();
1093+
1094+
// Assert that there are 2 outputs: 21K sat and (coinbase - 21K sat).
1095+
assert_eq!(txid_outspends_blocking.len(), 2);
1096+
assert_eq!(txid_outspends_async.len(), 2);
1097+
assert_eq!(txid_outspends_blocking, txid_outspends_async);
1098+
1099+
// Assert that both outputs are returned as unspent (spend == false).
1100+
assert!(txid_outspends_blocking.iter().all(|output| !output.spent));
1101+
}
10701102
}

0 commit comments

Comments
 (0)