bitcoind_async_client/traits.rs
1use bitcoin::{bip32::Xpriv, block::Header, Address, Block, BlockHash, Network, Transaction, Txid};
2use corepc_types::model::{
3 GetAddressInfo, GetBlockchainInfo, GetMempoolInfo, GetRawMempool, GetRawMempoolVerbose,
4 GetRawTransaction, GetRawTransactionVerbose, GetTransaction, GetTxOut, ListTransactions,
5 ListUnspent, PsbtBumpFee, SignRawTransactionWithWallet, SubmitPackage, TestMempoolAccept,
6 WalletCreateFundedPsbt, WalletProcessPsbt,
7};
8use corepc_types::v29::ImportDescriptors;
9use std::future::Future;
10
11use crate::types::{ImportDescriptorInput, SighashType};
12use crate::{
13 types::{
14 CreateRawTransactionArguments, CreateRawTransactionInput, CreateRawTransactionOutput,
15 ListUnspentQueryOptions, PreviousTransactionOutput, PsbtBumpFeeOptions,
16 WalletCreateFundedPsbtOptions,
17 },
18 ClientResult,
19};
20
21/// Basic functionality that any Bitcoin client that interacts with the
22/// Bitcoin network should provide.
23///
24/// # Note
25///
26/// This is a fully `async` trait. The user should be responsible for
27/// handling the `async` nature of the trait methods. And if implementing
28/// this trait for a specific type that is not `async`, the user should
29/// consider wrapping with [`tokio`](https://tokio.rs)'s
30/// [`spawn_blocking`](https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html) or any other method.
31pub trait Reader {
32 /// Estimates the approximate fee per kilobyte needed for a transaction
33 /// to begin confirmation within conf_target blocks if possible and return
34 /// the number of blocks for which the estimate is valid.
35 ///
36 /// # Parameters
37 ///
38 /// - `conf_target`: Confirmation target in blocks.
39 ///
40 /// # Note
41 ///
42 /// Uses virtual transaction size as defined in
43 /// [BIP 141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
44 /// (witness data is discounted).
45 ///
46 /// By default uses the estimate mode of `CONSERVATIVE` which is the
47 /// default in Bitcoin Core v27.
48 fn estimate_smart_fee(
49 &self,
50 conf_target: u16,
51 ) -> impl Future<Output = ClientResult<u64>> + Send;
52
53 /// Gets a [`Header`] with the given hash.
54 fn get_block_header(
55 &self,
56 hash: &BlockHash,
57 ) -> impl Future<Output = ClientResult<Header>> + Send;
58
59 /// Gets a [`Block`] with the given hash.
60 fn get_block(&self, hash: &BlockHash) -> impl Future<Output = ClientResult<Block>> + Send;
61
62 /// Gets a block height with the given hash.
63 fn get_block_height(&self, hash: &BlockHash) -> impl Future<Output = ClientResult<u64>> + Send;
64
65 /// Gets a [`Header`] at given height.
66 fn get_block_header_at(&self, height: u64)
67 -> impl Future<Output = ClientResult<Header>> + Send;
68
69 /// Gets a [`Block`] at given height.
70 fn get_block_at(&self, height: u64) -> impl Future<Output = ClientResult<Block>> + Send;
71
72 /// Gets the height of the most-work fully-validated chain.
73 ///
74 /// # Note
75 ///
76 /// The genesis block has a height of 0.
77 fn get_block_count(&self) -> impl Future<Output = ClientResult<u64>> + Send;
78
79 /// Gets the [`BlockHash`] at given height.
80 fn get_block_hash(&self, height: u64) -> impl Future<Output = ClientResult<BlockHash>> + Send;
81
82 /// Gets various state info regarding blockchain processing.
83 fn get_blockchain_info(&self) -> impl Future<Output = ClientResult<GetBlockchainInfo>> + Send;
84
85 /// Gets the timestamp in the block header of the current best block in bitcoin.
86 ///
87 /// # Note
88 ///
89 /// Time is Unix epoch time in seconds.
90 fn get_current_timestamp(&self) -> impl Future<Output = ClientResult<u32>> + Send;
91
92 /// Gets all transaction ids in mempool.
93 fn get_raw_mempool(&self) -> impl Future<Output = ClientResult<GetRawMempool>> + Send;
94
95 /// Gets verbose representation of transactions in mempool.
96 fn get_raw_mempool_verbose(
97 &self,
98 ) -> impl Future<Output = ClientResult<GetRawMempoolVerbose>> + Send;
99
100 /// Returns details on the active state of the mempool.
101 fn get_mempool_info(&self) -> impl Future<Output = ClientResult<GetMempoolInfo>> + Send;
102
103 /// Gets a raw transaction by its [`Txid`].
104 fn get_raw_transaction_verbosity_zero(
105 &self,
106 txid: &Txid,
107 ) -> impl Future<Output = ClientResult<GetRawTransaction>> + Send;
108
109 /// Gets a raw transaction by its [`Txid`].
110 fn get_raw_transaction_verbosity_one(
111 &self,
112 txid: &Txid,
113 ) -> impl Future<Output = ClientResult<GetRawTransactionVerbose>> + Send;
114
115 /// Returns details about an unspent transaction output.
116 fn get_tx_out(
117 &self,
118 txid: &Txid,
119 vout: u32,
120 include_mempool: bool,
121 ) -> impl Future<Output = ClientResult<GetTxOut>> + Send;
122
123 /// Gets the underlying [`Network`] information.
124 fn network(&self) -> impl Future<Output = ClientResult<Network>> + Send;
125}
126
127/// Broadcasting functionality that any Bitcoin client that interacts with the
128/// Bitcoin network should provide.
129///
130/// # Note
131///
132/// This is a fully `async` trait. The user should be responsible for
133/// handling the `async` nature of the trait methods. And if implementing
134/// this trait for a specific type that is not `async`, the user should
135/// consider wrapping with [`tokio`](https://tokio.rs)'s
136/// [`spawn_blocking`](https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html)
137/// or any other method.
138pub trait Broadcaster {
139 /// Sends a raw transaction to the network.
140 ///
141 /// # Parameters
142 ///
143 /// - `tx`: The raw transaction to send. This should be a byte array containing the serialized
144 /// raw transaction data.
145 fn send_raw_transaction(
146 &self,
147 tx: &Transaction,
148 ) -> impl Future<Output = ClientResult<Txid>> + Send;
149
150 /// Tests if a raw transaction is valid.
151 fn test_mempool_accept(
152 &self,
153 tx: &Transaction,
154 ) -> impl Future<Output = ClientResult<TestMempoolAccept>> + Send;
155
156 /// Submit a package of raw transactions (serialized, hex-encoded) to local node.
157 ///
158 /// The package will be validated according to consensus and mempool policy rules. If any
159 /// transaction passes, it will be accepted to mempool. This RPC is experimental and the
160 /// interface may be unstable. Refer to doc/policy/packages.md for documentation on package
161 /// policies.
162 ///
163 /// # Warning
164 ///
165 /// Successful submission does not mean the transactions will propagate throughout the network.
166 fn submit_package(
167 &self,
168 txs: &[Transaction],
169 ) -> impl Future<Output = ClientResult<SubmitPackage>> + Send;
170}
171
172/// Wallet functionality that any Bitcoin client **without private keys** that
173/// interacts with the Bitcoin network should provide.
174///
175/// For signing transactions, see [`Signer`].
176///
177/// # Note
178///
179/// This is a fully `async` trait. The user should be responsible for
180/// handling the `async` nature of the trait methods. And if implementing
181/// this trait for a specific type that is not `async`, the user should
182/// consider wrapping with [`tokio`](https://tokio.rs)'s
183/// [`spawn_blocking`](https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html)
184/// or any other method.
185pub trait Wallet {
186 /// Generates new address under own control for the underlying Bitcoin
187 /// client's wallet.
188 fn get_new_address(&self) -> impl Future<Output = ClientResult<Address>> + Send;
189
190 /// Gets information related to a transaction.
191 ///
192 /// # Note
193 ///
194 /// This assumes that the transaction is present in the underlying Bitcoin
195 /// client's wallet.
196 fn get_transaction(
197 &self,
198 txid: &Txid,
199 ) -> impl Future<Output = ClientResult<GetTransaction>> + Send;
200
201 /// Lists transactions in the underlying Bitcoin client's wallet.
202 ///
203 /// # Parameters
204 ///
205 /// - `count`: The number of transactions to list. If `None`, assumes a maximum of 10
206 /// transactions.
207 fn list_transactions(
208 &self,
209 count: Option<usize>,
210 ) -> impl Future<Output = ClientResult<ListTransactions>> + Send;
211
212 /// Lists all wallets in the underlying Bitcoin client.
213 fn list_wallets(&self) -> impl Future<Output = ClientResult<Vec<String>>> + Send;
214
215 /// Creates a raw transaction.
216 fn create_raw_transaction(
217 &self,
218 raw_tx: CreateRawTransactionArguments,
219 ) -> impl Future<Output = ClientResult<Transaction>> + Send;
220
221 /// Creates and funds a PSBT with inputs and outputs from the wallet.
222 ///
223 /// Uses the wallet's UTXOs to automatically fund the specified outputs, creating
224 /// a partially signed Bitcoin transaction that can be further processed or signed.
225 ///
226 /// # Parameters
227 ///
228 /// - `inputs`: Array of specific transaction inputs to include (can be empty for automatic selection).
229 /// - `outputs`: Array of transaction outputs, supporting both address-amount pairs and OP_RETURN data.
230 /// - `locktime`: Optional locktime for the transaction (0 = no locktime).
231 /// - `options`: Optional funding options including fee rate, change address, and confirmation targets.
232 /// - `bip32_derivs`: Whether to include BIP32 derivation paths in the PSBT for signing.
233 ///
234 /// # Returns
235 ///
236 /// Returns a [`WalletCreateFundedPsbt`] containing the funded PSBT, calculated fee, and change output position.
237 ///
238 /// # Note
239 ///
240 /// The returned PSBT is not signed and requires further processing with `wallet_process_psbt`
241 /// or `finalize_psbt` before it can be broadcast to the network.
242 fn wallet_create_funded_psbt(
243 &self,
244 inputs: &[CreateRawTransactionInput],
245 outputs: &[CreateRawTransactionOutput],
246 locktime: Option<u32>,
247 options: Option<WalletCreateFundedPsbtOptions>,
248 bip32_derivs: Option<bool>,
249 ) -> impl Future<Output = ClientResult<WalletCreateFundedPsbt>> + Send;
250
251 /// Returns detailed information about the given address.
252 ///
253 /// Queries the wallet for comprehensive information about a Bitcoin address,
254 /// including ownership status, spending capabilities, and script details.
255 /// This is useful for determining if an address belongs to the wallet and
256 /// how it can be used for transactions.
257 ///
258 /// # Parameters
259 ///
260 /// - `address`: The Bitcoin address to analyze (any valid Bitcoin address format).
261 ///
262 /// # Returns
263 ///
264 /// Returns a [`GetAddressInfo`] containing:
265 /// - Address ownership status (`is_mine`)
266 /// - Watch-only status (`is_watchonly`)
267 /// - Spending capability (`solvable`)
268 /// - The queried address for confirmation
269 ///
270 /// # Note
271 ///
272 /// The address doesn't need to belong to the wallet to query information about it.
273 /// However, detailed ownership and spending information will only be available
274 /// for addresses that the wallet knows about.
275 fn get_address_info(
276 &self,
277 address: &Address,
278 ) -> impl Future<Output = ClientResult<GetAddressInfo>> + Send;
279
280 /// Lists unspent transaction outputs with filtering options.
281 ///
282 /// Queries the wallet for unspent transaction outputs (UTXOs) with comprehensive
283 /// filtering capabilities. This is essential for coin selection, balance calculation,
284 /// and preparing transaction inputs. Provides fine-grained control over which
285 /// UTXOs are returned based on confirmations, addresses, safety, and amounts.
286 ///
287 /// # Parameters
288 ///
289 /// - `min_conf`: Minimum number of confirmations required (default: 1). Use 0 for unconfirmed outputs.
290 /// - `max_conf`: Maximum number of confirmations to include (default: 9,999,999). Limits how old UTXOs can be.
291 /// - `addresses`: Optional list of specific addresses to filter by. If provided, only UTXOs from these addresses are returned.
292 /// - `include_unsafe`: Whether to include outputs that are not safe to spend (default: true). Unsafe outputs include unconfirmed transactions from external keys.
293 /// - `query_options`: Additional filtering options for amount ranges and result limits via [`ListUnspentQueryOptions`].
294 ///
295 /// # Returns
296 ///
297 /// Returns a vector of [`ListUnspent`] containing:
298 /// - Transaction ID and output index (`txid`, `vout`)
299 /// - Bitcoin address and amount (`address`, `amount`)
300 /// - Confirmation count and safety status (`confirmations`, `safe`)
301 /// - Spendability information (`spendable`, `solvable`)
302 /// - Script details (`script_pubkey`, `label`)
303 ///
304 /// # Note
305 ///
306 /// UTXOs must satisfy ALL specified criteria to be included in results.
307 /// This method is commonly used for wallet balance calculation and transaction
308 /// preparation. Consider using `query_options` for amount-based filtering
309 /// to optimize coin selection strategies.
310 fn list_unspent(
311 &self,
312 min_conf: Option<u32>,
313 max_conf: Option<u32>,
314 addresses: Option<&[Address]>,
315 include_unsafe: Option<bool>,
316 query_options: Option<ListUnspentQueryOptions>,
317 ) -> impl Future<Output = ClientResult<ListUnspent>> + Send;
318}
319
320/// Signing functionality that any Bitcoin client **with private keys** that
321/// interacts with the Bitcoin network should provide.
322///
323/// # Note
324///
325/// This is a fully `async` trait. The user should be responsible for
326/// handling the `async` nature of the trait methods. And if implementing
327/// this trait for a specific type that is not `async`, the user should
328/// consider wrapping with [`tokio`](https://tokio.rs)'s
329/// [`spawn_blocking`](https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html)
330/// or any other method.
331pub trait Signer {
332 /// Signs a transaction using the keys available in the underlying Bitcoin
333 /// client's wallet and returns a signed transaction.
334 ///
335 /// # Note
336 ///
337 /// The returned signed transaction might not be consensus-valid if it
338 /// requires additional signatures, such as in a multisignature context.
339 fn sign_raw_transaction_with_wallet(
340 &self,
341 tx: &Transaction,
342 prev_outputs: Option<Vec<PreviousTransactionOutput>>,
343 ) -> impl Future<Output = ClientResult<SignRawTransactionWithWallet>> + Send;
344
345 /// Gets the underlying [`Xpriv`] from the wallet.
346 fn get_xpriv(&self) -> impl Future<Output = ClientResult<Option<Xpriv>>> + Send;
347
348 /// Imports the descriptors into the wallet.
349 fn import_descriptors(
350 &self,
351 descriptors: Vec<ImportDescriptorInput>,
352 wallet_name: String,
353 ) -> impl Future<Output = ClientResult<ImportDescriptors>> + Send;
354
355 /// Updates a PSBT with input information from the wallet and optionally signs it.
356 ///
357 /// # Parameters
358 ///
359 /// - `psbt`: The PSBT to process as a base64 string.
360 /// - `sign`: Whether to sign the transaction (default: true).
361 /// - `sighashtype`: Optional signature hash type to use.
362 /// - `bip32_derivs`: Whether to include BIP32 derivation paths.
363 ///
364 /// # Returns
365 ///
366 /// Returns a [`WalletProcessPsbt`] with the processed PSBT and completion status.
367 fn wallet_process_psbt(
368 &self,
369 psbt: &str,
370 sign: Option<bool>,
371 sighashtype: Option<SighashType>,
372 bip32_derivs: Option<bool>,
373 ) -> impl Future<Output = ClientResult<WalletProcessPsbt>> + Send;
374
375 /// Bumps the fee of an opt-in-RBF transaction, replacing it with a new transaction.
376 ///
377 /// # Parameters
378 ///
379 /// - `txid`: The transaction ID to be bumped.
380 /// - `options`: Optional fee bumping options including:
381 /// - `conf_target`: Confirmation target in blocks
382 /// - `fee_rate`: Fee rate in sat/vB (overrides conf_target)
383 /// - `replaceable`: Whether the new transaction should be BIP-125 replaceable
384 /// - `estimate_mode`: Fee estimate mode ("unset", "economical", "conservative")
385 /// - `outputs`: New transaction outputs to replace existing ones
386 /// - `original_change_index`: Index of change output to recycle from original transaction
387 ///
388 /// # Returns
389 ///
390 /// Returns a [`PsbtBumpFee`] containing the new PSBT and fee information.
391 ///
392 /// # Note
393 ///
394 /// The transaction must be BIP-125 opt-in replaceable and the new fee rate must be
395 /// higher than the original.
396 fn psbt_bump_fee(
397 &self,
398 txid: &Txid,
399 options: Option<PsbtBumpFeeOptions>,
400 ) -> impl Future<Output = ClientResult<PsbtBumpFee>> + Send;
401}