output: vec![],
};
- let recipients = match ¶ms.single_recipient {
- Some(recipient) => vec![(recipient, 0)],
- None => params.recipients.iter().map(|(r, v)| (r, *v)).collect(),
- };
- if params.single_recipient.is_some()
- && !params.manually_selected_only
- && !params.drain_wallet
- && params.bumping_fee.is_none()
- {
- return Err(Error::SingleRecipientNoInputs);
- }
- if recipients.is_empty() {
- return Err(Error::NoRecipients);
- }
-
if params.manually_selected_only && params.utxos.is_empty() {
return Err(Error::NoUtxosSelected);
}
let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
fee_amount += calc_fee_bytes(tx.get_weight());
- for (index, (script_pubkey, satoshi)) in recipients.into_iter().enumerate() {
- let value = match params.single_recipient {
- Some(_) => 0,
- None if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
- None => satoshi,
- };
+ let recipients = params.recipients.iter().map(|(r, v)| (r, *v));
+
+ for (index, (script_pubkey, value)) in recipients.enumerate() {
+ if value.is_dust() {
+ return Err(Error::OutputBelowDustLimit(index));
+ }
if self.is_mine(script_pubkey)? {
received += value;
})
.collect();
- // prepare the change output
- let change_output = match params.single_recipient {
- Some(_) => None,
- None => {
- let change_script = self.get_change_address()?;
- let change_output = TxOut {
- script_pubkey: change_script,
- value: 0,
- };
+ // prepare the drain output
+ let mut drain_output = {
+ let script_pubkey = match params.drain_to {
+ Some(ref drain_recipient) => drain_recipient.clone(),
+ None => self.get_change_address()?,
+ };
- // take the change into account for fees
- fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
- Some(change_output)
+ TxOut {
+ script_pubkey,
+ value: 0,
}
};
- let mut fee_amount = fee_amount.ceil() as u64;
- let change_val = (coin_selection.selected_amount() - outgoing).saturating_sub(fee_amount);
-
- match change_output {
- None if change_val.is_dust() => {
- // single recipient, but the only output would be below dust limit
- // TODO: or OutputBelowDustLimit?
- return Err(Error::InsufficientFunds {
- needed: DUST_LIMIT_SATOSHI,
- available: change_val,
- });
- }
- Some(_) if change_val.is_dust() => {
- // skip the change output because it's dust -- just include it in the fee.
- fee_amount += change_val;
- }
- Some(mut change_output) => {
- change_output.value = change_val;
- received += change_val;
- tx.output.push(change_output);
- }
- None => {
- // there's only one output, send everything to it
- tx.output[0].value = change_val;
+ fee_amount += calc_fee_bytes(serialize(&drain_output).len() * 4);
- // the single recipient is our address
- if self.is_mine(&tx.output[0].script_pubkey)? {
- received = change_val;
+ let mut fee_amount = fee_amount.ceil() as u64;
+ let drain_val = (coin_selection.selected_amount() - outgoing).saturating_sub(fee_amount);
+
+ if tx.output.is_empty() {
+ if params.drain_to.is_some() {
+ if drain_val.is_dust() {
+ return Err(Error::InsufficientFunds {
+ needed: DUST_LIMIT_SATOSHI,
+ available: drain_val,
+ });
}
+ } else {
+ return Err(Error::NoRecipients);
}
}
+ if drain_val.is_dust() {
+ fee_amount += drain_val;
+ } else {
+ drain_output.value = drain_val;
+ if self.is_mine(&drain_output.script_pubkey)? {
+ received += drain_val;
+ }
+ tx.output.push(drain_output);
+ }
+
// sort input/outputs according to the chosen algorithm
params.ordering.sort_tx(&mut tx);
/// *repalce by fee* (RBF). If the transaction can be fee bumped then it returns a [`TxBuilder`]
/// pre-populated with the inputs and outputs of the original transaction.
///
- /// **NOTE**: if the original transaction was made with [`TxBuilder::set_single_recipient`],
- /// the [`TxBuilder::maintain_single_recipient`] flag should be enabled to correctly reduce the
- /// only output's value in order to increase the fees.
- ///
/// ## Example
///
/// ```no_run
}
#[test]
- fn test_create_tx_single_recipient_drain_wallet() {
+ fn test_create_tx_drain_wallet_and_drain_to() {
let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, details) = builder.finish().unwrap();
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
);
}
+ #[test]
+ fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() {
+ let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+ let addr = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+ let drain_addr = wallet.get_address(New).unwrap();
+ let mut builder = wallet.build_tx();
+ builder
+ .add_recipient(addr.script_pubkey(), 20_000)
+ .drain_to(drain_addr.script_pubkey())
+ .drain_wallet();
+ let (psbt, details) = builder.finish().unwrap();
+ dbg!(&psbt);
+ let outputs = psbt.global.unsigned_tx.output;
+
+ assert_eq!(outputs.len(), 2);
+ let main_output = outputs
+ .iter()
+ .find(|x| x.script_pubkey == addr.script_pubkey())
+ .unwrap();
+ let drain_output = outputs
+ .iter()
+ .find(|x| x.script_pubkey == drain_addr.script_pubkey())
+ .unwrap();
+ assert_eq!(main_output.value, 20_000,);
+ assert_eq!(drain_output.value, 30_000 - details.fee.unwrap_or(0));
+ }
+
#[test]
fn test_create_tx_default_fee_rate() {
let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.drain_wallet()
.fee_absolute(100);
let (psbt, details) = builder.finish().unwrap();
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.drain_wallet()
.fee_absolute(0);
let (psbt, details) = builder.finish().unwrap();
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.drain_wallet()
.fee_absolute(60_000);
let (_psbt, _details) = builder.finish().unwrap();
#[test]
#[should_panic(expected = "InsufficientFunds")]
- fn test_create_tx_single_recipient_dust_amount() {
+ fn test_create_tx_drain_to_dust_amount() {
let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
let addr = wallet.get_address(New).unwrap();
// very high fee rate, so that the only output would be below dust
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.drain_wallet()
.fee_rate(FeeRate::from_sat_per_vb(453.0));
builder.finish().unwrap();
let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1);
let addr = testutils!(@external descriptors, 5);
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1);
get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert_eq!(
get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert_eq!(psbt.inputs[0].redeem_script, None);
get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
let script = Script::from(
get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert!(psbt.inputs[0].non_witness_utxo.is_some());
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.only_witness_utxo()
.drain_wallet();
let (psbt, _) = builder.finish().unwrap();
get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert!(psbt.inputs[0].witness_utxo.is_some());
get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (psbt, _) = builder.finish().unwrap();
assert!(psbt.inputs[0].non_witness_utxo.is_some());
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.drain_wallet()
.enable_rbf();
let (psbt, mut original_details) = builder.finish().unwrap();
let mut builder = wallet.build_fee_bump(txid).unwrap();
builder
.fee_rate(FeeRate::from_sat_per_vb(2.5))
- .maintain_single_recipient()
+ .allow_shrinking(addr.script_pubkey())
.unwrap();
let (psbt, details) = builder.finish().unwrap();
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.drain_wallet()
.enable_rbf();
let (psbt, mut original_details) = builder.finish().unwrap();
let mut builder = wallet.build_fee_bump(txid).unwrap();
builder
- .maintain_single_recipient()
+ .allow_shrinking(addr.script_pubkey())
.unwrap()
.fee_absolute(300);
let (psbt, details) = builder.finish().unwrap();
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.add_utxo(outpoint)
.unwrap()
.manually_selected_only()
let mut builder = wallet.build_fee_bump(txid).unwrap();
builder
.drain_wallet()
- .maintain_single_recipient()
+ .allow_shrinking(addr.script_pubkey())
.unwrap()
.fee_rate(FeeRate::from_sat_per_vb(5.0));
let (_, details) = builder.finish().unwrap();
// them, and make sure that `bump_fee` doesn't try to add more. This fails because we've
// told the wallet it's not allowed to add more inputs AND it can't reduce the value of the
// existing output. In other words, bump_fee + manually_selected_only is always an error
- // unless you've also set "maintain_single_recipient".
+ // unless you've also set "allow_shrinking OR there is a change output".
let incoming_txid = crate::populate_test_db!(
wallet.database.borrow_mut(),
testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.add_utxo(outpoint)
.unwrap()
.manually_selected_only()
Some(100),
);
- // initially make a tx without change by using `set_single_recipient`
+ // initially make a tx without change by using `set_drain_recipient`
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.add_utxo(OutPoint {
txid: incoming_txid,
vout: 0,
.set_tx(&original_details)
.unwrap();
- // now bump the fees without using `maintain_single_recipient`. the wallet should add an
+ // now bump the fees without using `allow_shrinking`. the wallet should add an
// extra input and a change output, and leave the original output untouched
let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
- builder
- .set_single_recipient(addr.script_pubkey())
- .drain_wallet();
+ builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
psbt.inputs[0].bip32_derivation.clear();
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
- .set_single_recipient(addr.script_pubkey())
+ .drain_to(addr.script_pubkey())
.sighash(sighash)
.drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
pub(crate) struct TxParams {
pub(crate) recipients: Vec<(Script, u64)>,
pub(crate) drain_wallet: bool,
- pub(crate) single_recipient: Option<Script>,
+ pub(crate) drain_to: Option<Script>,
pub(crate) fee_policy: Option<FeePolicy>,
pub(crate) internal_policy_path: Option<BTreeMap<String, Vec<usize>>>,
pub(crate) external_policy_path: Option<BTreeMap<String, Vec<usize>>>,
self
}
- /// Set a single recipient that will get all the selected funds minus the fee. No change will
- /// be created
+ /// Sets the address to *drain* excess coins to.
///
- /// This method overrides any recipient set with [`set_recipients`](Self::set_recipients) or
- /// [`add_recipient`](Self::add_recipient).
- ///
- /// It can only be used in conjunction with [`drain_wallet`](Self::drain_wallet) to send the
- /// entire content of the wallet (minus filters) to a single recipient or with a
- /// list of manually selected UTXOs by enabling [`manually_selected_only`](Self::manually_selected_only)
- /// and selecting them with or [`add_utxo`](Self::add_utxo).
+ /// Usually, when there is excess coins they are sent to a change address generated by the
+ /// wallet. This option replaces the usual change address with an arbitrary `script_pubkey` of
+ /// your choosing. Just as with a change output, if the drain output is not needed (the excess
+ /// coins are too small) it will not be included in the resulting transaction. The only
+ /// difference is that it is valid to use `drain_to` without setting any ordinary recipients
+ /// with [`add_recipient`] (but it is perfectly find to add recipients as well).
///
/// When bumping the fees of a transaction made with this option, the user should remeber to
- /// add [`maintain_single_recipient`](Self::maintain_single_recipient) to correctly update the
+ /// add [`allow_shrinking`] to correctly update the
/// single output instead of adding one more for the change.
- pub fn set_single_recipient(&mut self, recipient: Script) -> &mut Self {
- self.params.single_recipient = Some(recipient);
- self.params.recipients.clear();
-
+ ///
+ /// # Example
+ ///
+ /// `drain_to` is very useful for draining all the coins in a wallet with [`drain_wallet`] to a
+ /// single address.
+ ///
+ /// ```
+ /// # use std::str::FromStr;
+ /// # use bitcoin::*;
+ /// # use bdk::*;
+ /// # use bdk::wallet::tx_builder::CreateTx;
+ /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+ /// # let wallet = doctest_wallet!();
+ /// let mut tx_builder = wallet.build_tx();
+ ///
+ /// tx_builder
+ /// // spend all outputs in this wallet
+ /// .drain_wallet()
+ /// // send the excess (which is all the coins minus the fee) to this address
+ /// .drain_to(to_address.script_pubkey())
+ /// .fee_rate(FeeRate::from_sat_per_vb(5.0))
+ /// .enable_rbf();
+ /// let (psbt, tx_details) = tx_builder.finish()?;
+ /// # Ok::<(), bdk::Error>(())
+ /// ```
+ ///
+ /// [`allow_shrinking`]: Self::allow_shrinking
+ /// [`add_recipient`]: Self::add_recipient
+ /// [`drain_wallet`]: Self::drain_wallet
+ pub fn drain_to(&mut self, script_pubkey: Script) -> &mut Self {
+ self.params.drain_to = Some(script_pubkey);
self
}
}
// methods supported only by bump_fee
impl<'a, B, D: BatchDatabase> TxBuilder<'a, B, D, DefaultCoinSelectionAlgorithm, BumpFee> {
- /// Bump the fees of a transaction made with [`set_single_recipient`](Self::set_single_recipient)
- ///
- /// Unless extra inputs are specified with [`add_utxo`], this flag will make
- /// `bump_fee` reduce the value of the existing output, or fail if it would be consumed
- /// entirely given the higher new fee rate.
- ///
- /// If extra inputs are added and they are not entirely consumed in fees, a change output will not
- /// be added; the existing output will simply grow in value.
- ///
- /// Fails if the transaction has more than one outputs.
- ///
- /// [`add_utxo`]: Self::add_utxo
- pub fn maintain_single_recipient(&mut self) -> Result<&mut Self, Error> {
- let mut recipients = self.params.recipients.drain(..).collect::<Vec<_>>();
- if recipients.len() != 1 {
- return Err(Error::SingleRecipientMultipleOutputs);
+ /// Explicitly tells the wallet that it is allowed to reduce the fee of the output matching this
+ /// `script_pubkey` in order to bump the transaction fee. Without specifying this the wallet
+ /// will attempt to find a change output to shrink instead.
+ ///
+ /// **Note** that the output may shrunk to below the dust limit and therefore removed. If it is
+ /// preserved then it is currently not guaranteed to be in the same position as it was
+ /// originally.
+ ///
+ /// Returns an `Err` if `script_pubkey` can't be found among the recipients of the
+ /// transaction we are bumping.
+ pub fn allow_shrinking(&mut self, script_pubkey: Script) -> Result<&mut Self, Error> {
+ match self
+ .params
+ .recipients
+ .iter()
+ .position(|(recipient_script, _)| *recipient_script == script_pubkey)
+ {
+ Some(position) => {
+ self.params.recipients.remove(position);
+ self.params.drain_to = Some(script_pubkey);
+ Ok(self)
+ }
+ None => Err(Error::Generic(format!(
+ "{} was not in the original transaction",
+ script_pubkey
+ ))),
}
- self.params.single_recipient = Some(recipients.pop().unwrap().0);
- Ok(self)
}
}