Skip to content

Commit 35f6a04

Browse files
committed
feat(client): add get_tx_outspends method
1 parent a5af9f8 commit 35f6a04

File tree

3 files changed

+50
-12
lines changed

3 files changed

+50
-12
lines changed

src/async.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,20 @@ use std::collections::HashMap;
1515
use std::marker::PhantomData;
1616
use std::str::FromStr;
1717

18+
use bitcoin::block::Header as BlockHeader;
1819
use bitcoin::consensus::{deserialize, serialize, Decodable, Encodable};
1920
use bitcoin::hashes::{sha256, Hash};
2021
use bitcoin::hex::{DisplayHex, FromHex};
21-
use bitcoin::Address;
22-
use bitcoin::{
23-
block::Header as BlockHeader, Block, BlockHash, MerkleBlock, Script, Transaction, Txid,
24-
};
22+
use bitcoin::{Address, Block, BlockHash, MerkleBlock, Script, Transaction, Txid};
2523

2624
#[allow(unused_imports)]
2725
use log::{debug, error, info, trace};
2826

2927
use reqwest::{header, Client, Response};
3028

31-
use crate::api::AddressStats;
3229
use crate::{
33-
BlockStatus, BlockSummary, Builder, Error, MerkleProof, OutputStatus, Tx, TxStatus, Utxo,
30+
AddressStats, BlockInformation, BlockStatus, BlockSummary, Builder, Error, MempoolRecentTx,
31+
MempoolStats, MerkleProof, OutputStatus, ScriptHashStats, Tx, TxStatus, Utxo,
3432
BASE_BACKOFF_MILLIS, RETRYABLE_ERROR_CODES,
3533
};
3634

@@ -315,6 +313,12 @@ impl<S: Sleeper> AsyncClient<S> {
315313
self.get_opt_response_json(&format!("/tx/{txid}")).await
316314
}
317315

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

src/blocking.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@ use log::{debug, error, info, trace};
2121

2222
use minreq::{Proxy, Request, Response};
2323

24+
use bitcoin::block::Header as BlockHeader;
2425
use bitcoin::consensus::{deserialize, serialize, Decodable};
2526
use bitcoin::hashes::{sha256, Hash};
2627
use bitcoin::hex::{DisplayHex, FromHex};
27-
use bitcoin::Address;
28-
use bitcoin::{
29-
block::Header as BlockHeader, Block, BlockHash, MerkleBlock, Script, Transaction, Txid,
30-
};
28+
use bitcoin::{Address, Block, BlockHash, MerkleBlock, Script, Transaction, Txid};
3129

32-
use crate::api::AddressStats;
3330
use crate::{
34-
BlockStatus, BlockSummary, Builder, Error, MerkleProof, OutputStatus, Tx, TxStatus, Utxo,
31+
AddressStats, BlockInformation, BlockStatus, BlockSummary, Builder, Error, MempoolRecentTx,
32+
MempoolStats, MerkleProof, OutputStatus, ScriptHashStats, Tx, TxStatus, Utxo,
3533
BASE_BACKOFF_MILLIS, RETRYABLE_ERROR_CODES,
3634
};
3735

@@ -229,6 +227,11 @@ impl BlockingClient {
229227
self.get_opt_response_json(&format!("/tx/{txid}"))
230228
}
231229

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

src/lib.rs

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

0 commit comments

Comments
 (0)