diff --git a/psbt/src/constructor.rs b/psbt/src/constructor.rs index 47d4f17..1322077 100644 --- a/psbt/src/constructor.rs +++ b/psbt/src/constructor.rs @@ -24,8 +24,8 @@ use std::num::ParseIntError; use std::str::FromStr; use derive::{ - Address, AddressParseError, Keychain, LockTime, Network, NormalIndex, Outpoint, Sats, - ScriptPubkey, SeqNo, Terminal, Vout, + Address, AddressNetwork, AddressParseError, Keychain, LockTime, Network, NormalIndex, Outpoint, + Sats, ScriptPubkey, SeqNo, Terminal, Vout, }; use descriptors::Descriptor; @@ -175,10 +175,19 @@ impl TxParams { } } +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct ChangeInfo { + pub vout: Vout, + pub terminal: Terminal, +} + #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct PsbtMeta { - pub change_vout: Option, - pub change_terminal: Option, + pub network: AddressNetwork, + pub fee: Sats, + pub weight: u32, + pub size: u32, + pub change: Option, } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] @@ -276,22 +285,36 @@ pub trait PsbtConstructor { } // 3. Add change - only if exceeded the dust limit - let (change_vout, change_terminal) = - if remaining_value > self.descriptor().class().dust_limit() { - let change_index = - self.next_derivation_index(params.change_keychain, params.change_shift); - let change_terminal = Terminal::new(params.change_keychain, change_index); - let change_vout = psbt - .append_change_expect(self.descriptor(), change_terminal, remaining_value) - .index(); - (Some(Vout::from_u32(change_vout as u32)), Some(change_terminal)) - } else { - (None, None) - }; - - Ok((psbt, PsbtMeta { - change_vout, - change_terminal, - })) + let change = if remaining_value > self.descriptor().class().dust_limit() { + let change_index = + self.next_derivation_index(params.change_keychain, params.change_shift); + let change_terminal = Terminal::new(params.change_keychain, change_index); + let change_vout = psbt + .append_change_expect(self.descriptor(), change_terminal, remaining_value) + .index(); + Some(ChangeInfo { + vout: Vout::from_u32(change_vout as u32), + terminal: change_terminal, + }) + } else { + None + }; + + let meta = PsbtMeta { + network: self.network().into(), + fee: params.fee, + weight: 0, // TODO: Implement weight/size computation + size: 0, + change, + }; + self.after_construct_psbt(&psbt, &meta); + + Ok((psbt, meta)) + } + + /// A hook which is called by the default `Self::construct_psbt` before returning the newly + /// constructed PSBT to the caller. + fn after_construct_psbt(&mut self, _psbt: &Psbt, _meta: &PsbtMeta) { + // By default, we do not use the hook } } diff --git a/psbt/src/lib.rs b/psbt/src/lib.rs index 6a52d9a..99cdfd6 100644 --- a/psbt/src/lib.rs +++ b/psbt/src/lib.rs @@ -40,8 +40,8 @@ mod sign; pub use coders::{Decode, DecodeError, Encode, PsbtError}; pub use constructor::{ - Beneficiary, BeneficiaryParseError, ConstructionError, Payment, PsbtConstructor, PsbtMeta, - TxParams, Utxo, + Beneficiary, BeneficiaryParseError, ChangeInfo, ConstructionError, Payment, PsbtConstructor, + PsbtMeta, TxParams, Utxo, }; #[cfg(feature = "client-side-validation")] pub use csval::*;