diff --git a/gui/src/app/mod.rs b/gui/src/app/mod.rs index 610e1f61..0fe97cf6 100644 --- a/gui/src/app/mod.rs +++ b/gui/src/app/mod.rs @@ -80,6 +80,7 @@ impl App { menu::Menu::Spend => SpendPanel::new(self.config.clone(), &self.cache.spend_txs).into(), menu::Menu::CreateSpendTx => CreateSpendPanel::new( self.config.clone(), + self.daemon.config().main_descriptor.clone(), &self.cache.coins, self.daemon.config().main_descriptor.timelock_value(), self.cache.blockheight as u32, diff --git a/gui/src/app/state/spend/mod.rs b/gui/src/app/state/spend/mod.rs index c07a5e9b..cbbe990f 100644 --- a/gui/src/app/state/spend/mod.rs +++ b/gui/src/app/state/spend/mod.rs @@ -4,6 +4,8 @@ use std::sync::Arc; use iced::{Command, Element}; +use liana::descriptors::MultipathDescriptor; + use super::{redirect, State}; use crate::{ app::{cache::Cache, config::Config, error::Error, menu::Menu, message::Message, view}, @@ -104,13 +106,20 @@ pub struct CreateSpendPanel { } impl CreateSpendPanel { - pub fn new(config: Config, coins: &[Coin], timelock: u32, blockheight: u32) -> Self { + pub fn new( + config: Config, + descriptor: MultipathDescriptor, + coins: &[Coin], + timelock: u32, + blockheight: u32, + ) -> Self { Self { draft: step::TransactionDraft::default(), current: 0, steps: vec![ Box::new(step::ChooseRecipients::new(coins)), Box::new(step::ChooseCoins::new( + descriptor, coins.to_vec(), timelock, blockheight, diff --git a/gui/src/app/state/spend/step.rs b/gui/src/app/state/spend/step.rs index 933c929b..ba5e7fb9 100644 --- a/gui/src/app/state/spend/step.rs +++ b/gui/src/app/state/spend/step.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use iced::{Command, Element}; use liana::{ - config::Config as DaemonConfig, + descriptors::MultipathDescriptor, miniscript::bitcoin::{ self, util::psbt::Psbt, Address, Amount, Denomination, Network, OutPoint, }, @@ -223,8 +223,8 @@ impl Recipient { } } -#[derive(Default)] pub struct ChooseCoins { + descriptor: MultipathDescriptor, timelock: u32, coins: Vec<(Coin, bool)>, recipients: Vec<(Address, Amount)>, @@ -236,7 +236,12 @@ pub struct ChooseCoins { } impl ChooseCoins { - pub fn new(coins: Vec, timelock: u32, blockheight: u32) -> Self { + pub fn new( + descriptor: MultipathDescriptor, + coins: Vec, + timelock: u32, + blockheight: u32, + ) -> Self { let mut coins: Vec<(Coin, bool)> = coins .into_iter() .filter_map(|c| { @@ -259,6 +264,7 @@ impl ChooseCoins { } }); Self { + descriptor, timelock, coins, recipients: Vec::new(), @@ -269,7 +275,7 @@ impl ChooseCoins { } } - fn amount_left_to_select(&mut self, cfg: &DaemonConfig) { + fn amount_left_to_select(&mut self) { // We need the feerate in order to compute the required amount of BTC to // select. Return early if we don't to not do unnecessary computation. let feerate = match self.feerate.value.parse::() { @@ -309,7 +315,7 @@ impl ChooseCoins { }; // nValue size + scriptPubKey CompactSize + OP_0 + PUSH32 + const CHANGE_TXO_SIZE: usize = 8 + 1 + 1 + 1 + 32; - let satisfaction_vsize = cfg.main_descriptor.max_sat_weight() / 4; + let satisfaction_vsize = self.descriptor.max_sat_weight() / 4; let transaction_size = tx_template.vsize() + satisfaction_vsize * tx_template.input.len() + CHANGE_TXO_SIZE; @@ -333,6 +339,7 @@ impl Step for ChooseCoins { .iter() .map(|(k, v)| (k.clone(), Amount::from_sat(*v))) .collect(); + self.amount_left_to_select(); } fn apply(&self, draft: &mut TransactionDraft) { @@ -358,7 +365,7 @@ impl Step for ChooseCoins { if s.parse::().is_ok() { self.feerate.value = s; self.feerate.valid = true; - self.amount_left_to_select(daemon.config()); + self.amount_left_to_select(); } else if s.is_empty() { self.feerate.value = "".to_string(); self.feerate.valid = true; @@ -400,7 +407,7 @@ impl Step for ChooseCoins { Message::View(view::Message::CreateSpend(view::CreateSpendMessage::SelectCoin(i))) => { if let Some(coin) = self.coins.get_mut(i) { coin.1 = !coin.1; - self.amount_left_to_select(daemon.config()); + self.amount_left_to_select(); } } _ => {}