@@ -192,6 +192,13 @@ pub enum AddressIndex {
192
192
/// caller is untrusted; for example when deriving donation addresses on-demand for a public
193
193
/// web page.
194
194
LastUnused ,
195
+ /// Return the address for the first address in the keychain that has not been used in a received
196
+ /// transaction. Otherwise return a new address as with [`AddressIndex::New`].
197
+ ///
198
+ /// Use with caution, if the wallet has not yet detected an address has been used it could
199
+ /// return an already used address. This function is primarily meant for making use of addresses earlier
200
+ /// in the keychain that were infact never used.
201
+ FirstUnused ,
195
202
/// Return the address for a specific descriptor index. Does not change the current descriptor
196
203
/// index used by `AddressIndex::New` and `AddressIndex::LastUsed`.
197
204
///
@@ -291,7 +298,7 @@ where
291
298
292
299
// Return the the last previously derived address for `keychain` if it has not been used in a
293
300
// received transaction. Otherwise return a new address using [`Wallet::get_new_address`].
294
- fn get_unused_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
301
+ fn get_last_unused_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
295
302
let mut unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
296
303
match unused_key_indexes. pop ( ) {
297
304
None => self . get_new_address ( keychain) ,
@@ -311,6 +318,26 @@ where
311
318
}
312
319
}
313
320
321
+ // Return the the first address in the keychain which has not been a recipient of a transaction
322
+ fn get_first_unused_address ( & self , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
323
+ let unused_key_indexes = self . get_unused_key_indexes ( keychain) ?;
324
+ if unused_key_indexes. is_empty ( ) {
325
+ self . get_new_address ( keychain)
326
+ } else {
327
+ let derived_key = self
328
+ . get_descriptor_for_keychain ( keychain)
329
+ . as_derived ( unused_key_indexes[ 0 ] , & self . secp ) ;
330
+
331
+ derived_key
332
+ . address ( self . network )
333
+ . map ( |address| AddressInfo {
334
+ address,
335
+ index : unused_key_indexes[ 0 ] ,
336
+ } )
337
+ . map_err ( |_| Error :: ScriptDoesntHaveAddressForm )
338
+ }
339
+ }
340
+
314
341
// Return derived address for the descriptor of given [`KeychainKind`] at a specific index
315
342
fn peek_address ( & self , index : u32 , keychain : KeychainKind ) -> Result < AddressInfo , Error > {
316
343
self . get_descriptor_for_keychain ( keychain)
@@ -357,7 +384,8 @@ where
357
384
) -> Result < AddressInfo , Error > {
358
385
match address_index {
359
386
AddressIndex :: New => self . get_new_address ( keychain) ,
360
- AddressIndex :: LastUnused => self . get_unused_address ( keychain) ,
387
+ AddressIndex :: LastUnused => self . get_last_unused_address ( keychain) ,
388
+ AddressIndex :: FirstUnused => self . get_first_unused_address ( keychain) ,
361
389
AddressIndex :: Peek ( index) => self . peek_address ( index, keychain) ,
362
390
AddressIndex :: Reset ( index) => self . reset_address ( index, keychain) ,
363
391
}
@@ -1659,7 +1687,7 @@ pub(crate) mod test {
1659
1687
1660
1688
use super :: * ;
1661
1689
use crate :: signer:: { SignOptions , SignerError } ;
1662
- use crate :: wallet:: AddressIndex :: { LastUnused , New , Peek , Reset } ;
1690
+ use crate :: wallet:: AddressIndex :: { FirstUnused , LastUnused , New , Peek , Reset } ;
1663
1691
1664
1692
#[ test]
1665
1693
fn test_cache_addresses_fixed ( ) {
@@ -3867,6 +3895,36 @@ pub(crate) mod test {
3867
3895
) ;
3868
3896
}
3869
3897
3898
+ #[ test]
3899
+ fn test_firstunused_address ( ) {
3900
+ let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" ;
3901
+ let descriptors = testutils ! ( @descriptors ( descriptor) ) ;
3902
+ let wallet = Wallet :: new_offline (
3903
+ & descriptors. 0 ,
3904
+ None ,
3905
+ Network :: Testnet ,
3906
+ MemoryDatabase :: new ( ) ,
3907
+ )
3908
+ . unwrap ( ) ;
3909
+
3910
+ assert_eq ! (
3911
+ wallet. get_address( FirstUnused ) . unwrap( ) . to_string( ) ,
3912
+ "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
3913
+ ) ;
3914
+
3915
+ // use the first address
3916
+ crate :: populate_test_db!(
3917
+ wallet. database. borrow_mut( ) ,
3918
+ testutils! ( @tx ( ( @external descriptors, 0 ) => 25_000 ) ( @confirmations 1 ) ) ,
3919
+ Some ( 100 ) ,
3920
+ ) ;
3921
+
3922
+ assert_eq ! (
3923
+ wallet. get_address( FirstUnused ) . unwrap( ) . to_string( ) ,
3924
+ "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
3925
+ ) ;
3926
+ }
3927
+
3870
3928
#[ test]
3871
3929
fn test_peek_address_at_index ( ) {
3872
3930
let db = MemoryDatabase :: new ( ) ;
0 commit comments