Skip to main content

blockchain_client/
traits.rs

1use async_trait::async_trait;
2
3use crate::error::Result;
4use crate::types::{
5    AddressValidation, BlockchainInfo, RawTransaction, ReceivedByAddress, TransactionListItem, Utxo,
6};
7
8#[async_trait]
9pub trait BlockchainClient: Send + Sync {
10    async fn get_blockchain_info(&self) -> Result<BlockchainInfo>;
11
12    async fn get_raw_transaction(&self, txid: &str, verbose: bool) -> Result<RawTransaction> {
13        self.get_raw_transaction_with_block(txid, verbose, None)
14            .await
15    }
16
17    async fn get_raw_transaction_with_block(
18        &self,
19        txid: &str,
20        verbose: bool,
21        blockhash: Option<&str>,
22    ) -> Result<RawTransaction>;
23
24    async fn list_unspent(
25        &self,
26        min_conf: Option<u32>,
27        max_conf: Option<u32>,
28        addresses: Option<&[String]>,
29    ) -> Result<Vec<Utxo>>;
30
31    async fn list_transactions(
32        &self,
33        label: Option<&str>,
34        count: Option<usize>,
35        skip: Option<usize>,
36        include_watchonly: bool,
37    ) -> Result<Vec<TransactionListItem>>;
38
39    async fn get_received_by_address(&self, address: &str, min_conf: Option<u32>) -> Result<f64>;
40
41    async fn list_received_by_address(
42        &self,
43        min_conf: Option<u32>,
44        include_empty: bool,
45        include_watchonly: bool,
46    ) -> Result<Vec<ReceivedByAddress>>;
47
48    async fn is_address_watched(&self, address: &str) -> Result<bool>;
49
50    async fn import_address(&self, address: &str, label: Option<&str>, rescan: bool)
51        -> Result<()>;
52
53    async fn validate_address(&self, address: &str) -> Result<AddressValidation>;
54
55    async fn get_transaction(&self, txid: &str) -> Result<serde_json::Value>;
56
57    async fn get_block_count(&self) -> Result<u64>;
58
59    async fn get_best_block_hash(&self) -> Result<String>;
60}
61
62#[derive(Debug, Clone, Copy)]
63pub struct PaginationParams {
64    pub skip: usize,
65    pub count: usize,
66}
67
68#[async_trait]
69pub trait PaginatedBlockchainClient: BlockchainClient {
70    async fn list_transactions_paginated(
71        &self,
72        params: PaginationParams,
73        include_watchonly: bool,
74    ) -> Result<Vec<TransactionListItem>> {
75        let mut all = Vec::new();
76        let mut skip = params.skip;
77        let count = params.count;
78
79        loop {
80            let batch = self
81                .list_transactions(None, Some(count), Some(skip), include_watchonly)
82                .await?;
83
84            let batch_len = batch.len();
85            if batch_len == 0 {
86                break;
87            }
88
89            all.extend(batch);
90            skip += batch_len;
91
92            if batch_len < count {
93                break;
94            }
95        }
96
97        Ok(all)
98    }
99}
100
101impl<T> PaginatedBlockchainClient for T where T: BlockchainClient + ?Sized {}