@@ -431,6 +431,35 @@ where
431
431
Ok ( new_addresses_cached)
432
432
}
433
433
434
+ /// Return vector of n unused addresses from the [`KeychainKind`].
435
+ /// If less than n unused addresses are returned, the rest will be populated by new addresses.
436
+ /// The unused addresses returned are in order of oldest in keychain first, with increasing index.
437
+ pub fn get_batch_unused_addresses (
438
+ & self ,
439
+ n : usize ,
440
+ keychain : KeychainKind ,
441
+ ) -> Result < Vec < AddressInfo > , Error > {
442
+ let unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
443
+ let mut addresses = unused_key_indexes
444
+ . iter ( )
445
+ . map ( |i| {
446
+ let derived_key = self
447
+ . get_descriptor_for_keychain ( keychain)
448
+ . as_derived ( * i, & self . secp ) ;
449
+
450
+ derived_key
451
+ . address ( self . network )
452
+ . map ( |address| AddressInfo { address, index : * i } )
453
+ . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
454
+ } )
455
+ . take ( n)
456
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
457
+ for _ in 0 ..( n - addresses. len ( ) ) {
458
+ addresses. push ( self . get_new_address ( keychain) ?)
459
+ }
460
+ Ok ( addresses)
461
+ }
462
+
434
463
/// Return whether or not a `script` is part of this wallet (either internal or external)
435
464
pub fn is_mine ( & self , script : & Script ) -> Result < bool , Error > {
436
465
self . database . borrow ( ) . is_mine ( script)
@@ -3878,7 +3907,7 @@ pub(crate) mod test {
3878
3907
fn test_firstunused_address ( ) {
3879
3908
let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" ;
3880
3909
let descriptors = testutils ! ( @descriptors ( descriptor) ) ;
3881
- let wallet = Wallet :: new_offline (
3910
+ let wallet = Wallet :: new (
3882
3911
& descriptors. 0 ,
3883
3912
None ,
3884
3913
Network :: Testnet ,
@@ -3904,6 +3933,54 @@ pub(crate) mod test {
3904
3933
) ;
3905
3934
}
3906
3935
3936
+ #[ test]
3937
+ fn test_batch_unused_addresses ( ) {
3938
+ let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" ;
3939
+ let descriptors = testutils ! ( @descriptors ( descriptor) ) ;
3940
+ let wallet = Wallet :: new (
3941
+ & descriptors. 0 ,
3942
+ None ,
3943
+ Network :: Testnet ,
3944
+ MemoryDatabase :: new ( ) ,
3945
+ )
3946
+ . unwrap ( ) ;
3947
+
3948
+ // get first two addresses, moving index
3949
+ for _ in 0 ..2 {
3950
+ let _ = wallet. get_address ( New ) ;
3951
+ }
3952
+
3953
+ // use the second address
3954
+ crate :: populate_test_db!(
3955
+ wallet. database. borrow_mut( ) ,
3956
+ testutils! ( @tx ( ( @external descriptors, 1 ) => 25_000 ) ( @confirmations 1 ) ) ,
3957
+ Some ( 100 ) ,
3958
+ ) ;
3959
+
3960
+ assert_eq ! (
3961
+ wallet
3962
+ . get_batch_unused_addresses( 3 , KeychainKind :: External )
3963
+ . unwrap( ) ,
3964
+ vec![
3965
+ AddressInfo {
3966
+ index: 0 ,
3967
+ address: Address :: from_str( "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a" )
3968
+ . unwrap( ) ,
3969
+ } ,
3970
+ AddressInfo {
3971
+ index: 2 ,
3972
+ address: Address :: from_str( "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2" )
3973
+ . unwrap( ) ,
3974
+ } ,
3975
+ AddressInfo {
3976
+ index: 3 ,
3977
+ address: Address :: from_str( "tb1q32a23q6u3yy89l8svrt80a54h06qvn7gnuvsen" )
3978
+ . unwrap( ) ,
3979
+ }
3980
+ ]
3981
+ ) ;
3982
+ }
3983
+
3907
3984
#[ test]
3908
3985
fn test_peek_address_at_index ( ) {
3909
3986
let db = MemoryDatabase :: new ( ) ;
0 commit comments