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}