Skip to content

Commit 0cef6a9

Browse files
committed
Merge #134: feat: add get_address_utxos method
86d3d44 feat(client): add `get_address_utxos()` (Luis Schwab) 3c8b6e3 feat(api): create `UtxoStatus` and `Utxo` structs (Luis Schwab) Pull request description: Closes #133. This PR adds the `get_address_utxos` method, which hits the `/address/{addr}/utxo` endpoint, returning a `Vec<Utxo>`. # Changelog - Create `UtxoStatus`. - Create `Utxo`. - Create `get_address_utxos` for both blocking and async clients. - Add a functional test for it. ACKs for top commit: oleonardolima: ACK 86d3d44 Tree-SHA512: 9fa3e210be06d47e350d1afe01ab6b5c9173a2504ae769c6af364a1badbeb93034e3d053ebc95a8605030ba87dac264772c0c1a277561671a7a84b9d6a3f628d
2 parents 5740ceb + 86d3d44 commit 0cef6a9

File tree

4 files changed

+68
-2
lines changed

4 files changed

+68
-2
lines changed

src/api.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,33 @@ pub struct AddressTxsSummary {
123123
pub tx_count: u32,
124124
}
125125

126+
/// Information about an UTXO's status: confirmation status,
127+
/// confirmation height, confirmation block hash and confirmation block time.
128+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)]
129+
pub struct UtxoStatus {
130+
/// Whether or not the UTXO is confirmed.
131+
pub confirmed: bool,
132+
/// The block height in which the UTXO was confirmed.
133+
pub block_height: Option<u32>,
134+
/// The block hash in which the UTXO was confirmed.
135+
pub block_hash: Option<BlockHash>,
136+
/// The UNIX timestamp in which the UTXO was confirmed.
137+
pub block_time: Option<u64>,
138+
}
139+
140+
/// Information about an UTXO's outpoint, confirmation status and value.
141+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)]
142+
pub struct Utxo {
143+
/// The [`Txid`] of the transaction that created the UTXO.
144+
pub txid: Txid,
145+
/// The output index of the UTXO on the transaction that created the it.
146+
pub vout: u32,
147+
/// The confirmation status of the UTXO.
148+
pub status: UtxoStatus,
149+
/// The value of the UTXO as an [`Amount`].
150+
pub value: Amount,
151+
}
152+
126153
impl Tx {
127154
pub fn to_tx(&self) -> Transaction {
128155
Transaction {

src/async.rs

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

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

@@ -449,6 +449,12 @@ impl<S: Sleeper> AsyncClient<S> {
449449
Ok(blocks)
450450
}
451451

452+
/// Get all UTXOs locked to an address.
453+
pub async fn get_address_utxos(&self, address: &Address) -> Result<Vec<Utxo>, Error> {
454+
self.get_response_json(&format!("/address/{address}/utxo"))
455+
.await
456+
}
457+
452458
/// Get the underlying base URL.
453459
pub fn url(&self) -> &str {
454460
&self.url

src/blocking.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use bitcoin::{
3131

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

@@ -377,6 +377,11 @@ impl BlockingClient {
377377
Ok(blocks)
378378
}
379379

380+
/// Get all UTXOs locked to an address.
381+
pub fn get_address_utxos(&self, address: &Address) -> Result<Vec<Utxo>, Error> {
382+
self.get_response_json(&format!("/address/{address}/utxo"))
383+
}
384+
380385
/// Sends a GET request to the given `url`, retrying failed attempts
381386
/// for retryable error codes until max retries hit.
382387
fn get_with_retry(&self, url: &str) -> Result<Response, Error> {

src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,4 +1037,32 @@ mod test {
10371037
assert_eq!(address_txs_blocking, address_txs_async);
10381038
assert_eq!(address_txs_async[0].txid, txid);
10391039
}
1040+
1041+
#[cfg(all(feature = "blocking", feature = "async"))]
1042+
#[tokio::test]
1043+
async fn test_get_address_utxos() {
1044+
let (blocking_client, async_client) = setup_clients().await;
1045+
1046+
let address = BITCOIND
1047+
.client
1048+
.new_address_with_type(AddressType::Legacy)
1049+
.unwrap();
1050+
1051+
let _txid = BITCOIND
1052+
.client
1053+
.send_to_address(&address, Amount::from_sat(21000))
1054+
.unwrap()
1055+
.txid()
1056+
.unwrap();
1057+
1058+
let _miner = MINER.lock().await;
1059+
generate_blocks_and_wait(1);
1060+
1061+
let address_utxos_blocking = blocking_client.get_address_utxos(&address).unwrap();
1062+
let address_utxos_async = async_client.get_address_utxos(&address).await.unwrap();
1063+
1064+
assert_ne!(address_utxos_blocking.len(), 0);
1065+
assert_ne!(address_utxos_async.len(), 0);
1066+
assert_eq!(address_utxos_blocking, address_utxos_async);
1067+
}
10401068
}

0 commit comments

Comments
 (0)