@@ -457,6 +457,39 @@ where
457
457
Ok ( new_addresses_cached)
458
458
}
459
459
460
+ /// Return vector of n unused addresses from the [`KeychainKind`].
461
+ /// If less than n unused addresses are returned, the rest will be populated by new addresses.
462
+ /// The unused addresses returned are in order of oldest in keychain first, with increasing index.
463
+ pub fn get_batch_unused_addresses (
464
+ & self ,
465
+ n : usize ,
466
+ keychain : KeychainKind ,
467
+ ) -> Result < Vec < AddressInfo > , Error > {
468
+ let unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
469
+ let mut addresses = unused_key_indexes
470
+ . iter ( )
471
+ . map ( |i| {
472
+ let derived_key = self
473
+ . get_descriptor_for_keychain ( keychain)
474
+ . as_derived ( * i, & self . secp ) ;
475
+
476
+ derived_key
477
+ . address ( self . network )
478
+ . map ( |address| AddressInfo {
479
+ address,
480
+ index : * i,
481
+ keychain,
482
+ } )
483
+ . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
484
+ } )
485
+ . take ( n)
486
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
487
+ for _ in 0 ..( n - addresses. len ( ) ) {
488
+ addresses. push ( self . get_new_address ( keychain) ?)
489
+ }
490
+ Ok ( addresses)
491
+ }
492
+
460
493
/// Return whether or not a `script` is part of this wallet (either internal or external)
461
494
pub fn is_mine ( & self , script : & Script ) -> Result < bool , Error > {
462
495
self . database . borrow ( ) . is_mine ( script)
@@ -3970,6 +4003,57 @@ pub(crate) mod test {
3970
4003
) ;
3971
4004
}
3972
4005
4006
+ #[ test]
4007
+ fn test_batch_unused_addresses ( ) {
4008
+ let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" ;
4009
+ let descriptors = testutils ! ( @descriptors ( descriptor) ) ;
4010
+ let wallet = Wallet :: new (
4011
+ & descriptors. 0 ,
4012
+ None ,
4013
+ Network :: Testnet ,
4014
+ MemoryDatabase :: new ( ) ,
4015
+ )
4016
+ . unwrap ( ) ;
4017
+
4018
+ // get first two addresses, moving index
4019
+ for _ in 0 ..2 {
4020
+ let _ = wallet. get_address ( New ) ;
4021
+ }
4022
+
4023
+ // use the second address
4024
+ crate :: populate_test_db!(
4025
+ wallet. database. borrow_mut( ) ,
4026
+ testutils! ( @tx ( ( @external descriptors, 1 ) => 25_000 ) ( @confirmations 1 ) ) ,
4027
+ Some ( 100 ) ,
4028
+ ) ;
4029
+
4030
+ assert_eq ! (
4031
+ wallet
4032
+ . get_batch_unused_addresses( 3 , KeychainKind :: External )
4033
+ . unwrap( ) ,
4034
+ vec![
4035
+ AddressInfo {
4036
+ index: 0 ,
4037
+ address: Address :: from_str( "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a" )
4038
+ . unwrap( ) ,
4039
+ keychain: KeychainKind :: External ,
4040
+ } ,
4041
+ AddressInfo {
4042
+ index: 2 ,
4043
+ address: Address :: from_str( "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2" )
4044
+ . unwrap( ) ,
4045
+ keychain: KeychainKind :: External ,
4046
+ } ,
4047
+ AddressInfo {
4048
+ index: 3 ,
4049
+ address: Address :: from_str( "tb1q32a23q6u3yy89l8svrt80a54h06qvn7gnuvsen" )
4050
+ . unwrap( ) ,
4051
+ keychain: KeychainKind :: External ,
4052
+ }
4053
+ ]
4054
+ ) ;
4055
+ }
4056
+
3973
4057
#[ test]
3974
4058
fn test_peek_address_at_index ( ) {
3975
4059
let db = MemoryDatabase :: new ( ) ;
0 commit comments