diff --git a/bdk-ffi/src/tests/wallet.rs b/bdk-ffi/src/tests/wallet.rs index 6219fa7b..c8fcd86f 100644 --- a/bdk-ffi/src/tests/wallet.rs +++ b/bdk-ffi/src/tests/wallet.rs @@ -150,3 +150,41 @@ fn test_create_two_path_wallet() { assert_eq!(wallet.derivation_index(KeychainKind::External), Some(0)); assert_eq!(wallet.derivation_index(KeychainKind::Internal), Some(0)); } + +#[test] +fn test_load_from_two_path_descriptor() { + let persister = Arc::new(Persister::new_in_memory().unwrap()); + let wallet = Wallet::create_from_two_path_descriptor( + two_path_descriptor(), + Network::Signet, + Arc::clone(&persister), + 25, + ) + .unwrap(); + + wallet.reveal_next_address(KeychainKind::External); + wallet.reveal_next_address(KeychainKind::Internal); + assert!(wallet.persist(Arc::clone(&persister)).unwrap()); + + let loaded_wallet = + Wallet::load_from_two_path_descriptor(two_path_descriptor(), Arc::clone(&persister), 25) + .unwrap(); + + assert_eq!(loaded_wallet.network(), Network::Signet); + assert_eq!( + loaded_wallet.derivation_index(KeychainKind::External), + Some(0) + ); + assert_eq!( + loaded_wallet.derivation_index(KeychainKind::Internal), + Some(0) + ); + assert_eq!( + loaded_wallet.next_derivation_index(KeychainKind::External), + 1 + ); + assert_eq!( + loaded_wallet.next_derivation_index(KeychainKind::Internal), + 1 + ); +} diff --git a/bdk-ffi/src/wallet.rs b/bdk-ffi/src/wallet.rs index acd73c6a..0a06ccd0 100644 --- a/bdk-ffi/src/wallet.rs +++ b/bdk-ffi/src/wallet.rs @@ -109,13 +109,18 @@ impl Wallet { /// Build a new `Wallet` from a two-path descriptor. /// - /// This function parses a multipath descriptor with exactly 2 paths and creates a wallet using the existing receive and change wallet creation logic. + /// This function parses a multipath descriptor with exactly 2 paths and creates a wallet + /// using the existing receive and change wallet creation logic. /// - /// 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. + /// The provided descriptor may only contain extended public keys (`xpub`) with exactly 2 paths. + /// + /// 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. /// /// If you have previously created a wallet, use load instead. /// - /// Returns an error if the descriptor is invalid or not a 2-path multipath descriptor. + /// Returns an error if the descriptor is not a 2-path multipath descriptor. #[uniffi::constructor(default(lookahead = 25))] pub fn create_from_two_path_descriptor( two_path_descriptor: Arc, @@ -168,6 +173,34 @@ impl Wallet { }) } + /// Build a two-path descriptor `Wallet` by loading from persistence. + /// + /// Checks that the provided two-path descriptor matches exactly what is loaded + /// for both the external and internal keychains. + /// + /// The provided descriptor may only contain extended public keys (`xpub`) with exactly 2 paths. + #[uniffi::constructor(default(lookahead = 25))] + pub fn load_from_two_path_descriptor( + two_path_descriptor: Arc, + persister: Arc, + lookahead: u32, + ) -> Result { + let descriptor = two_path_descriptor.to_string(); + let mut persist_lock = persister.inner.lock().unwrap(); + let deref = persist_lock.deref_mut(); + + let wallet: PersistedWallet = BdkWallet::load() + .two_path_descriptor(descriptor) + .lookahead(lookahead) + .load_wallet(deref) + .map_err(LoadWithPersistError::from)? + .ok_or(LoadWithPersistError::CouldNotLoad)?; + + Ok(Wallet { + inner_mutex: Mutex::new(wallet), + }) + } + /// Build a single-descriptor Wallet by loading from persistence. /// /// Note that the descriptor secret keys are not persisted to the db.