diff --git a/CHANGELOG.md b/CHANGELOG.md index 96d32ff9..99a9ad22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Changed - `FeeRate` constructors `from_sat_per_vb` and `default_min_relay_fee` are now `const` functions +#### Added +- Added `get_unused_address()` which returns the last generated address if it has not been used or if used in a received transaction returns a new address + ## [v0.4.0] - [v0.3.0] ### Keys diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 29070bd3..2b17871a 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -177,6 +177,39 @@ where .map_err(|_| Error::ScriptDoesntHaveAddressForm) } + /// Return the the last previously generated address if it has not been used in a received + /// transaction. Otherwise return a new address using [`Wallet::get_new_address`]. + /// + /// Use with caution, if the wallet has not yet detected an address has been used it could + /// return an already used address. This function is primarily meant for situations where the + /// caller is untrusted; for example when generating donation addresses on-demand for a public + /// web page. + /// + pub fn get_unused_address(&self) -> Result
{ + let index = self.fetch_index(KeychainKind::External)?; + + let script = self + .descriptor + .as_derived(index, &self.secp) + .script_pubkey(); + + let found_used = self + .list_transactions(true)? + .iter() + .flat_map(|tx_details| tx_details.transaction.as_ref()) + .flat_map(|tx| tx.output.iter()) + .any(|o| o.script_pubkey == script); + + if found_used { + self.get_new_address() + } else { + self.descriptor + .as_derived(index, &self.secp) + .address(self.network) + .map_err(|_| Error::ScriptDoesntHaveAddressForm) + } + } + /// Return whether or not a `script` is part of this wallet (either internal or external) pub fn is_mine(&self, script: &Script) -> Result