bdkffi/
wallet.rs

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