Skip to main content

electrum_client/
batch.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Batch utilities
4//!
5//! This module contains definitions and helper functions used when making batch calls.
6
7use bitcoin::{Script, Txid};
8
9use crate::types::{Call, EstimationMode, Param, ToElectrumScriptHash};
10
11/// Helper structure that caches all the requests before they are actually sent to the server.
12///
13/// Calls on this function are stored and run when [`batch_call`](../client/struct.Client.html#method.batch_call)
14/// is run on a [`Client`](../client/struct.Client.html).
15///
16/// This structure can be used to make multiple *different* calls in one single run. For batch
17/// calls of the same type, there are shorthands methods defined on the
18/// [`Client`](../client/struct.Client.html), like
19/// [`batch_script_get_balance`](../client/struct.Client.html#method.batch_script_get_balance) to ask the
20/// server for the balance of multiple scripts with a single request.
21#[derive(Default)]
22pub struct Batch {
23    calls: Vec<Call>,
24}
25
26impl Batch {
27    /// Add a raw request to the batch queue
28    pub fn raw(&mut self, method: String, params: Vec<Param>) {
29        self.calls.push((method, params));
30    }
31
32    /// Add one `blockchain.scripthash.listunspent` request to the batch queue
33    pub fn script_list_unspent(&mut self, script: &Script) {
34        let params = vec![Param::String(script.to_electrum_scripthash().to_hex())];
35        self.calls
36            .push((String::from("blockchain.scripthash.listunspent"), params));
37    }
38
39    /// Add one `blockchain.scripthash.get_history` request to the batch queue
40    pub fn script_get_history(&mut self, script: &Script) {
41        let params = vec![Param::String(script.to_electrum_scripthash().to_hex())];
42        self.calls
43            .push((String::from("blockchain.scripthash.get_history"), params));
44    }
45
46    /// Add one `blockchain.scripthash.get_balance` request to the batch queue
47    pub fn script_get_balance(&mut self, script: &Script) {
48        let params = vec![Param::String(script.to_electrum_scripthash().to_hex())];
49        self.calls
50            .push((String::from("blockchain.scripthash.get_balance"), params));
51    }
52
53    /// Add one `blockchain.scripthash.listunspent` request to the batch queue
54    pub fn script_subscribe(&mut self, script: &Script) {
55        let params = vec![Param::String(script.to_electrum_scripthash().to_hex())];
56        self.calls
57            .push((String::from("blockchain.scripthash.subscribe"), params));
58    }
59
60    /// Add one `blockchain.transaction.get` request to the batch queue
61    pub fn transaction_get(&mut self, tx_hash: &Txid) {
62        let params = vec![Param::String(format!("{:x}", tx_hash))];
63        self.calls
64            .push((String::from("blockchain.transaction.get"), params));
65    }
66
67    /// Add one `blockchain.transaction.get_merkle` request to the batch queue
68    pub fn transaction_get_merkle(&mut self, tx_hash_and_height: &(Txid, usize)) {
69        let (tx_hash, height) = tx_hash_and_height;
70        let params = vec![
71            Param::String(format!("{:x}", tx_hash)),
72            Param::Usize(*height),
73        ];
74        self.calls
75            .push((String::from("blockchain.transaction.get_merkle"), params));
76    }
77
78    /// Add one `blockchain.estimatefee` request to the batch queue
79    pub fn estimate_fee(&mut self, number: usize, mode: Option<EstimationMode>) {
80        let mut params = vec![Param::Usize(number)];
81        if let Some(mode) = mode {
82            params.push(Param::String(mode.to_string()));
83        }
84        self.calls
85            .push((String::from("blockchain.estimatefee"), params));
86    }
87
88    /// Add one `blockchain.block.get_header` request to the batch queue
89    pub fn block_header(&mut self, height: u32) {
90        let params = vec![Param::U32(height)];
91        self.calls
92            .push((String::from("blockchain.block.header"), params));
93    }
94
95    /// Returns an iterator on the batch
96    pub fn iter(&self) -> BatchIter<'_> {
97        BatchIter {
98            batch: self,
99            index: 0,
100        }
101    }
102}
103
104impl std::iter::IntoIterator for Batch {
105    type Item = (String, Vec<Param>);
106    type IntoIter = std::vec::IntoIter<Self::Item>;
107
108    fn into_iter(self) -> Self::IntoIter {
109        self.calls.into_iter()
110    }
111}
112
113pub struct BatchIter<'a> {
114    batch: &'a Batch,
115    index: usize,
116}
117
118impl<'a> std::iter::Iterator for BatchIter<'a> {
119    type Item = &'a (String, Vec<Param>);
120
121    fn next(&mut self) -> Option<Self::Item> {
122        let val = self.batch.calls.get(self.index);
123        self.index += 1;
124        val
125    }
126}