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}