bdkffi/wallet.rs
1use crate::bitcoin::{Amount, FeeRate, OutPoint, Psbt, Script, Transaction, TxOut, Txid};
2use crate::descriptor::Descriptor;
3use crate::error::{
4 CalculateFeeError, CannotConnectError, CreateWithPersistError, DescriptorError,
5 LoadWithPersistError, PersistenceError, SignerError, TxidParseError,
6};
7use crate::store::{PersistenceType, Persister};
8use crate::types::{
9 AddressInfo, Balance, BlockId, CanonicalTx, ChangeSet, EvictedTx, FullScanRequestBuilder,
10 KeychainAndIndex, KeychainKind, LocalOutput, Policy, SentAndReceivedValues, SignOptions,
11 SyncRequestBuilder, UnconfirmedTx, Update, WalletEvent,
12};
13
14use bdk_wallet::bitcoin::Network;
15#[allow(deprecated)]
16use bdk_wallet::signer::SignOptions as BdkSignOptions;
17use bdk_wallet::{PersistedWallet, Wallet as BdkWallet};
18
19use std::ops::DerefMut;
20use std::sync::{Arc, Mutex, MutexGuard};
21
22/// A Bitcoin wallet.
23///
24/// The Wallet acts as a way of coherently interfacing with output descriptors and related transactions. Its main components are:
25/// 1. output descriptors from which it can derive addresses.
26/// 2. signers that can contribute signatures to addresses instantiated from the descriptors.
27///
28/// The user is responsible for loading and writing wallet changes which are represented as
29/// ChangeSets (see take_staged). Also see individual functions and example for instructions on when
30/// Wallet state needs to be persisted.
31///
32/// The Wallet descriptor (external) and change descriptor (internal) must not derive the same
33/// script pubkeys. See KeychainTxOutIndex::insert_descriptor() for more details.
34#[derive(uniffi::Object)]
35pub struct Wallet {
36 inner_mutex: Mutex<PersistedWallet<PersistenceType>>,
37}
38
39#[uniffi::export]
40impl Wallet {
41 /// Build a new Wallet.
42 ///
43 /// If you have previously created a wallet, use load instead.
44 #[uniffi::constructor(default(lookahead = 25))]
45 pub fn new(
46 descriptor: Arc<Descriptor>,
47 change_descriptor: Arc<Descriptor>,
48 network: Network,
49 persister: Arc<Persister>,
50 lookahead: u32,
51 ) -> Result<Self, CreateWithPersistError> {
52 let descriptor = descriptor.to_string_with_secret();
53 let change_descriptor = change_descriptor.to_string_with_secret();
54 let mut persist_lock = persister.inner.lock().unwrap();
55 let deref = persist_lock.deref_mut();
56
57 let wallet: PersistedWallet<PersistenceType> =
58 BdkWallet::create(descriptor, change_descriptor)
59 .network(network)
60 .lookahead(lookahead)
61 .create_wallet(deref)
62 .map_err(CreateWithPersistError::from)?;
63
64 Ok(Wallet {
65 inner_mutex: Mutex::new(wallet),
66 })
67 }
68
69 /// Build a new single descriptor `Wallet`.
70 ///
71 /// If you have previously created a wallet, use `Wallet::load` instead.
72 ///
73 /// # Note
74 ///
75 /// Only use this method when creating a wallet designed to be used with a single
76 /// descriptor and keychain. Otherwise the recommended way to construct a new wallet is
77 /// by using `Wallet::new`. It's worth noting that not all features are available
78 /// with single descriptor wallets, for example setting a `change_policy` on `TxBuilder`
79 /// and related methods such as `do_not_spend_change`. This is because all payments are
80 /// received on the external keychain (including change), and without a change keychain
81 /// BDK lacks enough information to distinguish between change and outside payments.
82 ///
83 /// Additionally because this wallet has no internal (change) keychain, all methods that
84 /// require a `KeychainKind` as input, e.g. `reveal_next_address` should only be called
85 /// using the `External` variant. In most cases passing `Internal` is treated as the
86 /// equivalent of `External` but this behavior must not be relied on.
87 #[uniffi::constructor(default(lookahead = 25))]
88 pub fn create_single(
89 descriptor: Arc<Descriptor>,
90 network: Network,
91 persister: Arc<Persister>,
92 lookahead: u32,
93 ) -> Result<Self, CreateWithPersistError> {
94 let descriptor = descriptor.to_string_with_secret();
95 let mut persist_lock = persister.inner.lock().unwrap();
96 let deref = persist_lock.deref_mut();
97
98 let wallet: PersistedWallet<PersistenceType> = BdkWallet::create_single(descriptor)
99 .network(network)
100 .lookahead(lookahead)
101 .create_wallet(deref)
102 .map_err(CreateWithPersistError::from)?;
103
104 Ok(Wallet {
105 inner_mutex: Mutex::new(wallet),
106 })
107 }
108
109 /// Build a new `Wallet` from a two-path descriptor.
110 ///
111 /// This function parses a multipath descriptor with exactly 2 paths and creates a wallet using the existing receive and change wallet creation logic.
112 ///
113 /// Multipath descriptors follow [BIP-389](https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki) and allow defining both receive and change derivation paths in a single descriptor using the <0;1> syntax.
114 ///
115 /// If you have previously created a wallet, use load instead.
116 ///
117 /// Returns an error if the descriptor is invalid or not a 2-path multipath descriptor.
118 #[uniffi::constructor(default(lookahead = 25))]
119 pub fn create_from_two_path_descriptor(
120 two_path_descriptor: Arc<Descriptor>,
121 network: Network,
122 persister: Arc<Persister>,
123 lookahead: u32,
124 ) -> Result<Self, CreateWithPersistError> {
125 let descriptor = two_path_descriptor.to_string_with_secret();
126 let mut persist_lock = persister.inner.lock().unwrap();
127 let deref = persist_lock.deref_mut();
128
129 let wallet: PersistedWallet<PersistenceType> =
130 BdkWallet::create_from_two_path_descriptor(descriptor)
131 .network(network)
132 .lookahead(lookahead)
133 .create_wallet(deref)
134 .map_err(CreateWithPersistError::from)?;
135
136 Ok(Wallet {
137 inner_mutex: Mutex::new(wallet),
138 })
139 }
140
141 /// Build Wallet by loading from persistence.
142 ///
143 /// Note that the descriptor secret keys are not persisted to the db.
144 #[uniffi::constructor(default(lookahead = 25))]
145 pub fn load(
146 descriptor: Arc<Descriptor>,
147 change_descriptor: Arc<Descriptor>,
148 persister: Arc<Persister>,
149 lookahead: u32,
150 ) -> Result<Wallet, LoadWithPersistError> {
151 let descriptor = descriptor.to_string_with_secret();
152 let change_descriptor = change_descriptor.to_string_with_secret();
153 let mut persist_lock = persister.inner.lock().unwrap();
154 let deref = persist_lock.deref_mut();
155
156 let wallet: PersistedWallet<PersistenceType> = BdkWallet::load()
157 .descriptor(KeychainKind::External, Some(descriptor))
158 .descriptor(KeychainKind::Internal, Some(change_descriptor))
159 .lookahead(lookahead)
160 .extract_keys()
161 .load_wallet(deref)
162 .map_err(LoadWithPersistError::from)?
163 .ok_or(LoadWithPersistError::CouldNotLoad)?;
164
165 Ok(Wallet {
166 inner_mutex: Mutex::new(wallet),
167 })
168 }
169
170 /// Build a single-descriptor Wallet by loading from persistence.
171 ///
172 /// Note that the descriptor secret keys are not persisted to the db.
173 #[uniffi::constructor(default(lookahead = 25))]
174 pub fn load_single(
175 descriptor: Arc<Descriptor>,
176 persister: Arc<Persister>,
177 lookahead: u32,
178 ) -> Result<Wallet, LoadWithPersistError> {
179 let descriptor = descriptor.to_string_with_secret();
180 let mut persist_lock = persister.inner.lock().unwrap();
181 let deref = persist_lock.deref_mut();
182
183 let wallet: PersistedWallet<PersistenceType> = BdkWallet::load()
184 .descriptor(KeychainKind::External, Some(descriptor))
185 .lookahead(lookahead)
186 .extract_keys()
187 .load_wallet(deref)
188 .map_err(LoadWithPersistError::from)?
189 .ok_or(LoadWithPersistError::CouldNotLoad)?;
190
191 Ok(Wallet {
192 inner_mutex: Mutex::new(wallet),
193 })
194 }
195
196 /// Finds how the wallet derived the script pubkey `spk`.
197 ///
198 /// Will only return `Some(_)` if the wallet has given out the spk.
199 pub fn derivation_of_spk(&self, spk: Arc<Script>) -> Option<KeychainAndIndex> {
200 self.get_wallet()
201 .derivation_of_spk(spk.0.clone())
202 .map(|(k, i)| KeychainAndIndex {
203 keychain: k,
204 index: i,
205 })
206 }
207
208 /// Returns the utxo owned by this wallet corresponding to `outpoint` if it exists in the
209 /// wallet's database.
210 pub fn get_utxo(&self, op: OutPoint) -> Option<LocalOutput> {
211 self.get_wallet()
212 .get_utxo(op.into())
213 .map(|local_output| local_output.into())
214 }
215
216 /// Attempt to reveal the next address of the given `keychain`.
217 ///
218 /// This will increment the keychain's derivation index. If the keychain's descriptor doesn't
219 /// contain a wildcard or every address is already revealed up to the maximum derivation
220 /// index defined in [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki),
221 /// then the last revealed address will be returned.
222 pub fn reveal_next_address(&self, keychain: KeychainKind) -> AddressInfo {
223 self.get_wallet().reveal_next_address(keychain).into()
224 }
225
226 /// Peek an address of the given `keychain` at `index` without revealing it.
227 ///
228 /// For non-wildcard descriptors this returns the same address at every provided index.
229 ///
230 /// # Panics
231 ///
232 /// This panics when the caller requests for an address of derivation index greater than the
233 /// [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) max index.
234 pub fn peek_address(&self, keychain: KeychainKind, index: u32) -> AddressInfo {
235 self.get_wallet().peek_address(keychain, index).into()
236 }
237
238 /// The index of the next address that you would get if you were to ask the wallet for a new
239 /// address.
240 pub fn next_derivation_index(&self, keychain: KeychainKind) -> u32 {
241 self.get_wallet().next_derivation_index(keychain)
242 }
243
244 /// Get the next unused address for the given `keychain`, i.e. the address with the lowest
245 /// derivation index that hasn't been used in a transaction.
246 ///
247 /// This will attempt to reveal a new address if all previously revealed addresses have
248 /// been used, in which case the returned address will be the same as calling [`Wallet::reveal_next_address`].
249 ///
250 /// **WARNING**: To avoid address reuse you must persist the changes resulting from one or more
251 /// calls to this method before closing the wallet. See [`Wallet::reveal_next_address`].
252 pub fn next_unused_address(&self, keychain: KeychainKind) -> AddressInfo {
253 self.get_wallet().next_unused_address(keychain).into()
254 }
255
256 /// Marks an address used of the given `keychain` at `index`.
257 ///
258 /// Returns whether the given index was present and then removed from the unused set.
259 pub fn mark_used(&self, keychain: KeychainKind, index: u32) -> bool {
260 self.get_wallet().mark_used(keychain, index)
261 }
262
263 /// Undoes the effect of [`mark_used`] and returns whether the `index` was inserted
264 /// back into the unused set.
265 ///
266 /// Since this is only a superficial marker, it will have no effect if the address at the given
267 /// `index` was actually used, i.e. the wallet has previously indexed a tx output for the
268 /// derived spk.
269 ///
270 /// [`mark_used`]: Self::mark_used
271 pub fn unmark_used(&self, keychain: KeychainKind, index: u32) -> bool {
272 self.get_wallet().unmark_used(keychain, index)
273 }
274
275 /// Reveal addresses up to and including the target `index` and return an iterator
276 /// of newly revealed addresses.
277 ///
278 /// If the target `index` is unreachable, we make a best effort to reveal up to the last
279 /// possible index. If all addresses up to the given `index` are already revealed, then
280 /// no new addresses are returned.
281 ///
282 /// **WARNING**: To avoid address reuse you must persist the changes resulting from one or more
283 /// calls to this method before closing the wallet. See [`Wallet::reveal_next_address`].
284 pub fn reveal_addresses_to(&self, keychain: KeychainKind, index: u32) -> Vec<AddressInfo> {
285 self.get_wallet()
286 .reveal_addresses_to(keychain, index)
287 .map(|address_info| address_info.into())
288 .collect()
289 }
290
291 /// List addresses that are revealed but unused.
292 ///
293 /// Note if the returned iterator is empty you can reveal more addresses
294 /// by using [`reveal_next_address`](Self::reveal_next_address) or
295 /// [`reveal_addresses_to`](Self::reveal_addresses_to).
296 pub fn list_unused_addresses(&self, keychain: KeychainKind) -> Vec<AddressInfo> {
297 self.get_wallet()
298 .list_unused_addresses(keychain)
299 .map(|address_info| address_info.into())
300 .collect()
301 }
302
303 /// Applies an update to the wallet and stages the changes (but does not persist them).
304 ///
305 /// Usually you create an `update` by interacting with some blockchain data source and inserting
306 /// transactions related to your wallet into it.
307 ///
308 /// After applying updates you should persist the staged wallet changes. For an example of how
309 /// to persist staged wallet changes see [`Wallet::reveal_next_address`].
310 pub fn apply_update(&self, update: Arc<Update>) -> Result<(), CannotConnectError> {
311 self.get_wallet()
312 .apply_update(update.0.clone())
313 .map_err(CannotConnectError::from)
314 }
315
316 /// Applies an update to the wallet, stages the changes, and returns events.
317 ///
318 /// Usually you create an `update` by interacting with some blockchain data source and inserting
319 /// transactions related to your wallet into it. Staged changes are NOT persisted.
320 ///
321 /// After applying updates you should process the events in your app before persisting the
322 /// staged wallet changes. For an example of how to persist staged wallet changes see
323 /// [`Wallet::reveal_next_address`].
324 pub fn apply_update_events(
325 &self,
326 update: Arc<Update>,
327 ) -> Result<Vec<WalletEvent>, CannotConnectError> {
328 match self.get_wallet().apply_update_events(update.0.clone()) {
329 Ok(events) => Ok(events.into_iter().map(|e| e.into()).collect()),
330 Err(e) => Err(CannotConnectError::from(e)),
331 }
332 }
333
334 /// Apply relevant unconfirmed transactions to the wallet.
335 /// Transactions that are not relevant are filtered out.
336 pub fn apply_unconfirmed_txs(&self, unconfirmed_txs: Vec<UnconfirmedTx>) {
337 self.get_wallet().apply_unconfirmed_txs(
338 unconfirmed_txs
339 .into_iter()
340 .map(|utx| (Arc::new(utx.tx.as_ref().into()), utx.last_seen)),
341 )
342 }
343
344 /// Apply relevant unconfirmed transactions to the wallet and returns events.
345 ///
346 /// See [`apply_unconfirmed_txs`] for more information.
347 ///
348 /// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
349 ///
350 /// [`apply_unconfirmed_txs`]: Self::apply_unconfirmed_txs
351 /// [`apply_update_events`]: Self::apply_update_events
352 pub fn apply_unconfirmed_txs_events(
353 &self,
354 unconfirmed_txs: Vec<UnconfirmedTx>,
355 ) -> Vec<WalletEvent> {
356 self.get_wallet()
357 .apply_unconfirmed_txs_events(
358 unconfirmed_txs
359 .into_iter()
360 .map(|utx| (Arc::new(utx.tx.as_ref().into()), utx.last_seen)),
361 )
362 .into_iter()
363 .map(|event| event.into())
364 .collect()
365 }
366
367 /// Apply transactions that have been evicted from the mempool.
368 /// Transactions may be evicted for paying too-low fee, or for being malformed.
369 /// Irrelevant transactions are ignored.
370 ///
371 /// For more information: https://docs.rs/bdk_wallet/latest/bdk_wallet/struct.Wallet.html#method.apply_evicted_txs
372 pub fn apply_evicted_txs(&self, evicted_txs: Vec<EvictedTx>) {
373 self.get_wallet().apply_evicted_txs(
374 evicted_txs
375 .into_iter()
376 .map(|etx| (etx.txid.0, etx.evicted_at)),
377 );
378 }
379
380 /// Apply evictions of the given transaction IDs with their associated timestamps and returns
381 /// events.
382 ///
383 /// See [`apply_evicted_txs`] for more information.
384 ///
385 /// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
386 ///
387 /// [`apply_evicted_txs`]: Self::apply_evicted_txs
388 /// [`apply_update_events`]: Self::apply_update_events
389 pub fn apply_evicted_txs_events(&self, evicted_txs: Vec<EvictedTx>) -> Vec<WalletEvent> {
390 self.get_wallet()
391 .apply_evicted_txs_events(
392 evicted_txs
393 .into_iter()
394 .map(|etx| (etx.txid.0, etx.evicted_at)),
395 )
396 .into_iter()
397 .map(|event| event.into())
398 .collect()
399 }
400
401 /// The derivation index of this wallet. It will return `None` if it has not derived any addresses.
402 /// Otherwise, it will return the index of the highest address it has derived.
403 pub fn derivation_index(&self, keychain: KeychainKind) -> Option<u32> {
404 self.get_wallet().derivation_index(keychain)
405 }
406
407 /// Return the checksum of the public descriptor associated to `keychain`.
408 ///
409 /// Internally calls [`Self::public_descriptor`] to fetch the right descriptor.
410 pub fn descriptor_checksum(&self, keychain: KeychainKind) -> String {
411 self.get_wallet().descriptor_checksum(keychain)
412 }
413
414 /// Return the spending policies for the wallet’s descriptor.
415 pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Arc<Policy>>, DescriptorError> {
416 self.get_wallet()
417 .policies(keychain)
418 .map_err(DescriptorError::from)
419 .map(|e| e.map(|p| Arc::new(p.into())))
420 }
421
422 /// Get the Bitcoin network the wallet is using.
423 pub fn network(&self) -> Network {
424 self.get_wallet().network()
425 }
426
427 /// Return the balance, separated into available, trusted-pending, untrusted-pending and
428 /// immature values.
429 pub fn balance(&self) -> Balance {
430 let bdk_balance = self.get_wallet().balance();
431 Balance::from(bdk_balance)
432 }
433
434 /// Return whether or not a `script` is part of this wallet (either internal or external).
435 pub fn is_mine(&self, script: Arc<Script>) -> bool {
436 self.get_wallet().is_mine(script.0.clone())
437 }
438
439 /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
440 /// [`SignerOrdering`]. This function returns the `Result` type with an encapsulated `bool` that
441 /// has the value true if the PSBT was finalized, or false otherwise.
442 ///
443 /// The [`SignOptions`] can be used to tweak the behavior of the software signers, and the way
444 /// the transaction is finalized at the end. Note that it can't be guaranteed that *every*
445 /// signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
446 /// in this library will.
447 #[uniffi::method(default(sign_options = None))]
448 #[allow(deprecated)]
449 pub fn sign(
450 &self,
451 psbt: Arc<Psbt>,
452 sign_options: Option<SignOptions>,
453 ) -> Result<bool, SignerError> {
454 let mut psbt = psbt.0.lock().unwrap();
455 let bdk_sign_options: BdkSignOptions = match sign_options {
456 Some(sign_options) => BdkSignOptions::from(sign_options),
457 None => BdkSignOptions::default(),
458 };
459
460 self.get_wallet()
461 .sign(&mut psbt, bdk_sign_options)
462 .map_err(SignerError::from)
463 }
464
465 /// Finalize a PSBT, i.e., for each input determine if sufficient data is available to pass
466 /// validation and construct the respective `scriptSig` or `scriptWitness`. Please refer to
467 /// [BIP174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#Input_Finalizer),
468 /// and [BIP371](https://github.com/bitcoin/bips/blob/master/bip-0371.mediawiki)
469 /// for further information.
470 ///
471 /// Returns `true` if the PSBT could be finalized, and `false` otherwise.
472 ///
473 /// The [`SignOptions`] can be used to tweak the behavior of the finalizer.
474 #[uniffi::method(default(sign_options = None))]
475 #[allow(deprecated)]
476 pub fn finalize_psbt(
477 &self,
478 psbt: Arc<Psbt>,
479 sign_options: Option<SignOptions>,
480 ) -> Result<bool, SignerError> {
481 let mut psbt = psbt.0.lock().unwrap();
482 let bdk_sign_options: BdkSignOptions = match sign_options {
483 Some(sign_options) => BdkSignOptions::from(sign_options),
484 None => BdkSignOptions::default(),
485 };
486
487 self.get_wallet()
488 .finalize_psbt(&mut psbt, bdk_sign_options)
489 .map_err(SignerError::from)
490 }
491
492 /// Compute the `tx`'s sent and received [`Amount`]s.
493 ///
494 /// This method returns a tuple `(sent, received)`. Sent is the sum of the txin amounts
495 /// that spend from previous txouts tracked by this wallet. Received is the summation
496 /// of this tx's outputs that send to script pubkeys tracked by this wallet.
497 pub fn sent_and_received(&self, tx: &Transaction) -> SentAndReceivedValues {
498 let (sent, received) = self.get_wallet().sent_and_received(&tx.into());
499 SentAndReceivedValues {
500 sent: Arc::new(sent.into()),
501 received: Arc::new(received.into()),
502 }
503 }
504
505 /// Iterate over the transactions in the wallet.
506 pub fn transactions(&self) -> Vec<CanonicalTx> {
507 self.get_wallet()
508 .transactions_sort_by(|tx1, tx2| tx2.chain_position.cmp(&tx1.chain_position))
509 .into_iter()
510 .map(|tx| tx.into())
511 .collect()
512 }
513
514 /// Get a single transaction from the wallet as a [`WalletTx`] (if the transaction exists).
515 ///
516 /// `WalletTx` contains the full transaction alongside meta-data such as:
517 /// * Blocks that the transaction is [`Anchor`]ed in. These may or may not be blocks that exist
518 /// in the best chain.
519 /// * The [`ChainPosition`] of the transaction in the best chain - whether the transaction is
520 /// confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the
521 /// confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when
522 /// the transaction was last seen in the mempool is provided.
523 pub fn get_tx(&self, txid: Arc<Txid>) -> Result<Option<CanonicalTx>, TxidParseError> {
524 Ok(self.get_wallet().get_tx(txid.0).map(|tx| tx.into()))
525 }
526
527 /// Inserts a [`TxOut`] at [`OutPoint`] into the wallet's transaction graph.
528 ///
529 /// This is used for providing a previous output's value so that we can use [`calculate_fee`]
530 /// or [`calculate_fee_rate`] on a given transaction. Outputs inserted with this method will
531 /// not be returned in [`list_unspent`] or [`list_output`].
532 ///
533 /// **WARNINGS:** This should only be used to add `TxOut`s that the wallet does not own. Only
534 /// insert `TxOut`s that you trust the values for!
535 ///
536 /// You must persist the changes resulting from one or more calls to this method if you need
537 /// the inserted `TxOut` data to be reloaded after closing the wallet.
538 /// See [`Wallet::reveal_next_address`].
539 ///
540 /// [`calculate_fee`]: Self::calculate_fee
541 /// [`calculate_fee_rate`]: Self::calculate_fee_rate
542 /// [`list_unspent`]: Self::list_unspent
543 /// [`list_output`]: Self::list_output
544 pub fn insert_txout(&self, outpoint: OutPoint, txout: TxOut) {
545 self.get_wallet()
546 .insert_txout(outpoint.into(), txout.into());
547 }
548
549 /// Calculates the fee of a given transaction. Returns [`Amount::ZERO`] if `tx` is a coinbase transaction.
550 ///
551 /// To calculate the fee for a [`Transaction`] with inputs not owned by this wallet you must
552 /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function.
553 ///
554 /// Note `tx` does not have to be in the graph for this to work.
555 pub fn calculate_fee(&self, tx: &Transaction) -> Result<Arc<Amount>, CalculateFeeError> {
556 self.get_wallet()
557 .calculate_fee(&tx.into())
558 .map(Amount::from)
559 .map(Arc::new)
560 .map_err(|e| e.into())
561 }
562
563 /// Calculate the [`FeeRate`] for a given transaction.
564 ///
565 /// To calculate the fee rate for a [`Transaction`] with inputs not owned by this wallet you must
566 /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function.
567 ///
568 /// Note `tx` does not have to be in the graph for this to work.
569 pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<Arc<FeeRate>, CalculateFeeError> {
570 self.get_wallet()
571 .calculate_fee_rate(&tx.into())
572 .map(|bdk_fee_rate| Arc::new(FeeRate(bdk_fee_rate)))
573 .map_err(|e| e.into())
574 }
575
576 /// Return the list of unspent outputs of this wallet.
577 pub fn list_unspent(&self) -> Vec<LocalOutput> {
578 self.get_wallet().list_unspent().map(|o| o.into()).collect()
579 }
580
581 /// List the locked outpoints.
582 pub fn list_locked_outpoints(&self) -> Vec<OutPoint> {
583 self.get_wallet()
584 .list_locked_outpoints()
585 .map(Into::into)
586 .collect()
587 }
588
589 /// List unspent outpoints that are currently locked.
590 pub fn list_locked_unspent(&self) -> Vec<OutPoint> {
591 self.get_wallet()
592 .list_locked_unspent()
593 .map(Into::into)
594 .collect()
595 }
596
597 /// Whether the `outpoint` is locked. See `Wallet::lock_outpoint` for more.
598 pub fn is_outpoint_locked(&self, outpoint: OutPoint) -> bool {
599 self.get_wallet().is_outpoint_locked(outpoint.into())
600 }
601
602 /// Lock a wallet output identified by the given `outpoint`.
603 ///
604 /// A locked UTXO will not be selected as an input to fund a transaction. This is useful
605 /// for excluding or reserving candidate inputs during transaction creation.
606 ///
607 /// **You must persist the staged change for the lock status to be persistent**. To unlock a
608 /// previously locked outpoint, see `Wallet::unlock_outpoint`.
609 pub fn lock_outpoint(&self, outpoint: OutPoint) {
610 self.get_wallet().lock_outpoint(outpoint.into());
611 }
612
613 /// Unlock the wallet output of the specified `outpoint`.
614 ///
615 /// **You must persist the staged change for the lock status to be persistent**.
616 pub fn unlock_outpoint(&self, outpoint: OutPoint) {
617 self.get_wallet().unlock_outpoint(outpoint.into());
618 }
619
620 /// List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).
621 ///
622 /// To list only unspent outputs (UTXOs), use [`Wallet::list_unspent`] instead.
623 pub fn list_output(&self) -> Vec<LocalOutput> {
624 self.get_wallet().list_output().map(|o| o.into()).collect()
625 }
626
627 /// Create a [`FullScanRequest] for this wallet.
628 ///
629 /// This is the first step when performing a spk-based wallet full scan, the returned
630 /// [`FullScanRequest] collects iterators for the wallet's keychain script pub keys needed to
631 /// start a blockchain full scan with a spk based blockchain client.
632 ///
633 /// This operation is generally only used when importing or restoring a previously used wallet
634 /// in which the list of used scripts is not known.
635 pub fn start_full_scan(&self) -> Arc<FullScanRequestBuilder> {
636 let builder = self.get_wallet().start_full_scan();
637 Arc::new(FullScanRequestBuilder(Mutex::new(Some(builder))))
638 }
639
640 /// Create a [`FullScanRequest`] builder at `start_time`.
641 pub fn start_full_scan_at(&self, start_time: u64) -> Arc<FullScanRequestBuilder> {
642 let builder = self.get_wallet().start_full_scan_at(start_time);
643 Arc::new(FullScanRequestBuilder(Mutex::new(Some(builder))))
644 }
645
646 /// Create a partial [`SyncRequest`] for all revealed spks at `start_time`.
647 ///
648 /// The `start_time` is used to record the time that a mempool transaction was last seen
649 /// (or evicted). See [`Wallet::start_sync_with_revealed_spks`] for more.
650 pub fn start_sync_with_revealed_spks_at(&self, start_time: u64) -> Arc<SyncRequestBuilder> {
651 let builder = self
652 .get_wallet()
653 .start_sync_with_revealed_spks_at(start_time);
654 Arc::new(SyncRequestBuilder(Mutex::new(Some(builder))))
655 }
656
657 /// Create a partial [`SyncRequest`] for this wallet for all revealed spks.
658 ///
659 /// This is the first step when performing a spk-based wallet partial sync, the returned
660 /// [`SyncRequest`] collects all revealed script pubkeys from the wallet keychain needed to
661 /// start a blockchain sync with a spk based blockchain client.
662 pub fn start_sync_with_revealed_spks(&self) -> Arc<SyncRequestBuilder> {
663 let builder = self.get_wallet().start_sync_with_revealed_spks();
664 Arc::new(SyncRequestBuilder(Mutex::new(Some(builder))))
665 }
666
667 /// Persist staged changes of wallet into persister.
668 ///
669 /// Returns whether any new changes were persisted.
670 ///
671 /// If the persister errors, the staged changes will not be cleared.
672 pub fn persist(&self, persister: Arc<Persister>) -> Result<bool, PersistenceError> {
673 let mut persist_lock = persister.inner.lock().unwrap();
674 let deref = persist_lock.deref_mut();
675 self.get_wallet()
676 .persist(deref)
677 .map_err(|e| PersistenceError::Reason {
678 error_message: e.to_string(),
679 })
680 }
681
682 /// Get a reference of the staged [`ChangeSet`] that is yet to be committed (if any).
683 pub fn staged(&self) -> Option<Arc<ChangeSet>> {
684 self.get_wallet()
685 .staged()
686 .map(|changeset| Arc::new(changeset.clone().into()))
687 }
688
689 /// Take the staged [`ChangeSet`] to be persisted now (if any).
690 pub fn take_staged(&self) -> Option<Arc<ChangeSet>> {
691 self.get_wallet()
692 .take_staged()
693 .map(|changeset| Arc::new(changeset.into()))
694 }
695
696 /// Returns the latest checkpoint.
697 pub fn latest_checkpoint(&self) -> BlockId {
698 self.get_wallet().latest_checkpoint().block_id().into()
699 }
700
701 /// Get all the checkpoints the wallet is currently storing indexed by height.
702 pub fn checkpoints(&self) -> Vec<BlockId> {
703 self.get_wallet()
704 .checkpoints()
705 .map(|checkpoint| checkpoint.block_id().into())
706 .collect()
707 }
708
709 /// Get the [`TxDetails`] of a wallet transaction.
710 pub fn tx_details(&self, txid: Arc<Txid>) -> Option<crate::types::TxDetails> {
711 self.get_wallet()
712 .tx_details(txid.0)
713 .map(|details| details.into())
714 }
715
716 /// Returns the descriptor used to create addresses for a particular `keychain`.
717 ///
718 /// It's the "public" version of the wallet's descriptor, meaning a new descriptor that has
719 /// the same structure but with the all secret keys replaced by their corresponding public key.
720 /// This can be used to build a watch-only version of a wallet.
721 pub fn public_descriptor(&self, keychain: KeychainKind) -> String {
722 self.get_wallet().public_descriptor(keychain).to_string()
723 }
724}
725
726impl Wallet {
727 pub(crate) fn get_wallet(&self) -> MutexGuard<'_, PersistedWallet<PersistenceType>> {
728 self.inner_mutex.lock().expect("wallet")
729 }
730}