electrum_client/
api.rs

1//! Electrum APIs
2
3use std::borrow::Borrow;
4use std::convert::TryInto;
5
6use bitcoin::consensus::encode::{deserialize, serialize};
7use bitcoin::{block, Script, Transaction, Txid};
8
9use crate::batch::Batch;
10use crate::types::*;
11
12/// API calls exposed by an Electrum client
13pub trait ElectrumApi {
14    /// Gets the block header for height `height`.
15    fn block_header(&self, height: usize) -> Result<block::Header, Error> {
16        Ok(deserialize(&self.block_header_raw(height)?)?)
17    }
18
19    /// Subscribes to notifications for new block headers, by sending a `blockchain.headers.subscribe` call.
20    fn block_headers_subscribe(&self) -> Result<HeaderNotification, Error> {
21        self.block_headers_subscribe_raw()?.try_into()
22    }
23
24    /// Tries to pop one queued notification for a new block header that we might have received.
25    /// Returns `None` if there are no items in the queue.
26    fn block_headers_pop(&self) -> Result<Option<HeaderNotification>, Error> {
27        self.block_headers_pop_raw()?
28            .map(|raw| raw.try_into())
29            .transpose()
30    }
31
32    /// Gets the transaction with `txid`. Returns an error if not found.
33    fn transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
34        Ok(deserialize(&self.transaction_get_raw(txid)?)?)
35    }
36
37    /// Batch version of [`transaction_get`](#method.transaction_get).
38    ///
39    /// Takes a list of `txids` and returns a list of transactions.
40    fn batch_transaction_get<'t, I>(&self, txids: I) -> Result<Vec<Transaction>, Error>
41    where
42        I: IntoIterator + Clone,
43        I::Item: Borrow<&'t Txid>,
44    {
45        self.batch_transaction_get_raw(txids)?
46            .iter()
47            .map(|s| Ok(deserialize(s)?))
48            .collect()
49    }
50
51    /// Batch version of [`block_header`](#method.block_header).
52    ///
53    /// Takes a list of `heights` of blocks and returns a list of headers.
54    fn batch_block_header<I>(&self, heights: I) -> Result<Vec<block::Header>, Error>
55    where
56        I: IntoIterator + Clone,
57        I::Item: Borrow<u32>,
58    {
59        self.batch_block_header_raw(heights)?
60            .iter()
61            .map(|s| Ok(deserialize(s)?))
62            .collect()
63    }
64
65    /// Broadcasts a transaction to the network.
66    fn transaction_broadcast(&self, tx: &Transaction) -> Result<Txid, Error> {
67        let buffer: Vec<u8> = serialize(tx);
68        self.transaction_broadcast_raw(&buffer)
69    }
70
71    /// Executes the requested API call returning the raw answer.
72    fn raw_call(
73        &self,
74        method_name: &str,
75        params: impl IntoIterator<Item = Param>,
76    ) -> Result<serde_json::Value, Error>;
77
78    /// Execute a queue of calls stored in a [`Batch`](../batch/struct.Batch.html) struct. Returns
79    /// `Ok()` **only if** all of the calls are successful. The order of the JSON `Value`s returned
80    /// reflects the order in which the calls were made on the `Batch` struct.
81    fn batch_call(&self, batch: &Batch) -> Result<Vec<serde_json::Value>, Error>;
82
83    /// Subscribes to notifications for new block headers, by sending a `blockchain.headers.subscribe` call and
84    /// returns the current tip as raw bytes instead of deserializing them.
85    fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error>;
86
87    /// Tries to pop one queued notification for a new block header that we might have received.
88    /// Returns a the header in raw bytes if a notification is found in the queue, None otherwise.
89    fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error>;
90
91    /// Gets the raw bytes of block header for height `height`.
92    fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error>;
93
94    /// Tries to fetch `count` block headers starting from `start_height`.
95    fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error>;
96
97    /// Estimates the fee required in **Bitcoin per kilobyte** to confirm a transaction in `number` blocks.
98    fn estimate_fee(&self, number: usize) -> Result<f64, Error>;
99
100    /// Returns the minimum accepted fee by the server's node in **Bitcoin, not Satoshi**.
101    fn relay_fee(&self) -> Result<f64, Error>;
102
103    /// Subscribes to notifications for activity on a specific *scriptPubKey*.
104    ///
105    /// Returns a [`ScriptStatus`](../types/type.ScriptStatus.html) when successful that represents
106    /// the current status for the requested script.
107    ///
108    /// Returns [`Error::AlreadySubscribed`](../types/enum.Error.html#variant.AlreadySubscribed) if
109    /// already subscribed to the script.
110    fn script_subscribe(&self, script: &Script) -> Result<Option<ScriptStatus>, Error>;
111
112    /// Batch version of [`script_subscribe`](#method.script_subscribe).
113    ///
114    /// Takes a list of scripts and returns a list of script status responses.
115    ///
116    /// Note you should pass a reference to a collection because otherwise an expensive clone is made
117    fn batch_script_subscribe<'s, I>(&self, scripts: I) -> Result<Vec<Option<ScriptStatus>>, Error>
118    where
119        I: IntoIterator + Clone,
120        I::Item: Borrow<&'s Script>;
121
122    /// Subscribes to notifications for activity on a specific *scriptPubKey*.
123    ///
124    /// Returns a `bool` with the server response when successful.
125    ///
126    /// Returns [`Error::NotSubscribed`](../types/enum.Error.html#variant.NotSubscribed) if
127    /// not subscribed to the script.
128    fn script_unsubscribe(&self, script: &Script) -> Result<bool, Error>;
129
130    /// Tries to pop one queued notification for a the requested script. Returns `None` if there are no items in the queue.
131    fn script_pop(&self, script: &Script) -> Result<Option<ScriptStatus>, Error>;
132
133    /// Returns the balance for a *scriptPubKey*.
134    fn script_get_balance(&self, script: &Script) -> Result<GetBalanceRes, Error>;
135
136    /// Batch version of [`script_get_balance`](#method.script_get_balance).
137    ///
138    /// Takes a list of scripts and returns a list of balance responses.
139    fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
140    where
141        I: IntoIterator + Clone,
142        I::Item: Borrow<&'s Script>;
143
144    /// Returns the history for a *scriptPubKey*
145    fn script_get_history(&self, script: &Script) -> Result<Vec<GetHistoryRes>, Error>;
146
147    /// Batch version of [`script_get_history`](#method.script_get_history).
148    ///
149    /// Takes a list of scripts and returns a list of history responses.
150    fn batch_script_get_history<'s, I>(&self, scripts: I) -> Result<Vec<Vec<GetHistoryRes>>, Error>
151    where
152        I: IntoIterator + Clone,
153        I::Item: Borrow<&'s Script>;
154
155    /// Returns the list of unspent outputs for a *scriptPubKey*
156    fn script_list_unspent(&self, script: &Script) -> Result<Vec<ListUnspentRes>, Error>;
157
158    /// Batch version of [`script_list_unspent`](#method.script_list_unspent).
159    ///
160    /// Takes a list of scripts and returns a list of a list of utxos.
161    fn batch_script_list_unspent<'s, I>(
162        &self,
163        scripts: I,
164    ) -> Result<Vec<Vec<ListUnspentRes>>, Error>
165    where
166        I: IntoIterator + Clone,
167        I::Item: Borrow<&'s Script>;
168
169    /// Gets the raw bytes of a transaction with `txid`. Returns an error if not found.
170    fn transaction_get_raw(&self, txid: &Txid) -> Result<Vec<u8>, Error>;
171
172    /// Batch version of [`transaction_get_raw`](#method.transaction_get_raw).
173    ///
174    /// Takes a list of `txids` and returns a list of transactions raw bytes.
175    fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
176    where
177        I: IntoIterator + Clone,
178        I::Item: Borrow<&'t Txid>;
179
180    /// Batch version of [`block_header_raw`](#method.block_header_raw).
181    ///
182    /// Takes a list of `heights` of blocks and returns a list of block header raw bytes.
183    fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
184    where
185        I: IntoIterator + Clone,
186        I::Item: Borrow<u32>;
187
188    /// Batch version of [`estimate_fee`](#method.estimate_fee).
189    ///
190    /// Takes a list of `numbers` of blocks and returns a list of fee required in
191    /// **Satoshis per kilobyte** to confirm a transaction in the given number of blocks.
192    fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
193    where
194        I: IntoIterator + Clone,
195        I::Item: Borrow<usize>;
196
197    /// Broadcasts the raw bytes of a transaction to the network.
198    fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error>;
199
200    /// Returns the merkle path for the transaction `txid` confirmed in the block at `height`.
201    fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error>;
202
203    /// Returns a transaction hash, given a block `height` and a `tx_pos` in the block.
204    fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error>;
205
206    /// Returns a transaction hash and a merkle path, given a block `height` and a `tx_pos` in the
207    /// block.
208    fn txid_from_pos_with_merkle(
209        &self,
210        height: usize,
211        tx_pos: usize,
212    ) -> Result<TxidFromPosRes, Error>;
213
214    /// Returns the capabilities of the server.
215    fn server_features(&self) -> Result<ServerFeaturesRes, Error>;
216
217    /// Pings the server. This method can also be used as a "dummy" call to trigger the processing
218    /// of incoming block header or script notifications.
219    fn ping(&self) -> Result<(), Error>;
220
221    #[cfg(feature = "debug-calls")]
222    /// Returns the number of network calls made since the creation of the client.
223    fn calls_made(&self) -> Result<usize, Error>;
224}