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) -> Result<()>;
51
52    async fn validate_address(&self, address: &str) -> Result<AddressValidation>;
53
54    async fn get_transaction(&self, txid: &str) -> Result<serde_json::Value>;
55
56    async fn get_block_count(&self) -> Result<u64>;
57
58    async fn get_best_block_hash(&self) -> Result<String>;
59}
60
61#[derive(Debug, Clone, Copy)]
62pub struct PaginationParams {
63    pub skip: usize,
64    pub count: usize,
65}
66
67#[async_trait]
68pub trait PaginatedBlockchainClient: BlockchainClient {
69    async fn list_transactions_paginated(
70        &self,
71        params: PaginationParams,
72        include_watchonly: bool,
73    ) -> Result<Vec<TransactionListItem>> {
74        let mut all = Vec::new();
75        let mut skip = params.skip;
76        let count = params.count;
77
78        loop {
79            let batch = self
80                .list_transactions(None, Some(count), Some(skip), include_watchonly)
81                .await?;
82
83            let batch_len = batch.len();
84            if batch_len == 0 {
85                break;
86            }
87
88            all.extend(batch);
89            skip += batch_len;
90
91            if batch_len < count {
92                break;
93            }
94        }
95
96        Ok(all)
97    }
98}
99
100impl<T> PaginatedBlockchainClient for T where T: BlockchainClient + ?Sized {}