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}