Skip to content

Commit

Permalink
gui(spend): use create_spend_tx for missing amount
Browse files Browse the repository at this point in the history
  • Loading branch information
jp1ac4 committed Jan 30, 2024
1 parent fae32df commit 3f28d27
Showing 1 changed file with 26 additions and 75 deletions.
101 changes: 26 additions & 75 deletions gui/src/app/state/spend/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ use iced::{Command, Subscription};
use liana::{
descriptors::LianaDescriptor,
miniscript::bitcoin::{
self, address, psbt::Psbt, secp256k1, Address, Amount, Denomination, Network, OutPoint,
},
spend::{
create_spend, CandidateCoin, SpendCreationError, SpendOutputAddress, SpendTxFees, TxGetter,
MAX_FEERATE,
address, psbt::Psbt, secp256k1, Address, Amount, Denomination, Network, OutPoint,
},
spend::{SpendCreationError, MAX_FEERATE},
};

use liana_ui::{component::form, widget::Element};
Expand Down Expand Up @@ -192,86 +189,50 @@ impl DefineSpend {
return;
}

let destinations: Vec<(SpendOutputAddress, Amount)> = self
let destinations: HashMap<Address<address::NetworkUnchecked>, u64> = self
.recipients
.iter()
.map(|recipient| {
(
SpendOutputAddress {
addr: Address::from_str(&recipient.address.value)
.expect("Checked before")
.assume_checked(),
info: None,
},
Amount::from_sat(recipient.amount().expect("Checked before")),
Address::from_str(&recipient.address.value).expect("Checked before"),
recipient.amount().expect("Checked before"),
)
})
.collect();

let coins: Vec<CandidateCoin> = if self.is_user_coin_selection {
let outpoints = if self.is_user_coin_selection {
self.coins
.iter()
.filter_map(|(c, selected)| {
if *selected {
Some(CandidateCoin {
amount: c.amount,
outpoint: c.outpoint,
deriv_index: c.derivation_index,
is_change: c.is_change,
sequence: None,
must_select: *selected,
})
} else {
None
}
})
.filter_map(
|(c, selected)| {
if *selected {
Some(c.outpoint)
} else {
None
}
},
)
.collect()
} else {
// For automated coin selection, only confirmed coins are considered
self.coins
.iter()
.filter_map(|(c, _)| {
if c.block_height.is_some() {
Some(CandidateCoin {
amount: c.amount,
outpoint: c.outpoint,
deriv_index: c.derivation_index,
is_change: c.is_change,
sequence: None,
must_select: false,
})
} else {
None
}
})
.collect()
Vec::new() // pass empty list for auto-selection
};

// Use a fixed change address so that we don't increment the change index.
let dummy_address = self
.descriptor
.change_descriptor()
.derive(0.into(), &self.curve)
.address(self.network);
.address(self.network)
.as_unchecked()
.clone();

let feerate_vb = self.feerate.value.parse::<u64>().expect("Checked before");
// Create a spend with empty inputs in order to use auto-selection.
match create_spend(
&self.descriptor,
&self.curve,
&mut DaemonTxGetter(&daemon),
&destinations,
&coins,
SpendTxFees::Regular(feerate_vb),
SpendOutputAddress {
addr: dummy_address,
info: None,
},
) {
Ok(spend) => {

match daemon.create_spend_tx(&outpoints, &destinations, feerate_vb, Some(dummy_address)) {
Ok(CreateSpendResult::Success { psbt, .. }) => {
self.warning = None;
if !self.is_user_coin_selection {
let selected_coins: Vec<OutPoint> = spend
.psbt
let selected_coins: Vec<OutPoint> = psbt
.unsigned_tx
.input
.iter()
Expand All @@ -290,8 +251,8 @@ impl DefineSpend {
// User can then either:
// - modify recipient amounts and/or feerate and let coin selection run again, or
// - select coins manually.
Err(SpendCreationError::CoinSelection(amount)) => {
self.amount_left_to_select = Some(Amount::from_sat(amount.missing));
Ok(CreateSpendResult::InsufficientFunds { missing }) => {
self.amount_left_to_select = Some(Amount::from_sat(missing));
}
Err(e) => {
self.warning = Some(e.into());
Expand All @@ -300,16 +261,6 @@ impl DefineSpend {
}
}

pub struct DaemonTxGetter<'a>(&'a Arc<dyn Daemon + Sync + Send>);
impl<'a> TxGetter for DaemonTxGetter<'a> {
fn get_tx(&mut self, txid: &bitcoin::Txid) -> Option<bitcoin::Transaction> {
self.0
.list_txs(&[*txid])
.ok()
.and_then(|mut txs| txs.transactions.pop().map(|tx| tx.tx))
}
}

impl Step for DefineSpend {
fn update(
&mut self,
Expand Down

0 comments on commit 3f28d27

Please sign in to comment.