From b426d31914bf906d65307bdeb6851430d59b399d Mon Sep 17 00:00:00 2001 From: thomas Date: Tue, 22 Apr 2025 14:41:36 +0200 Subject: [PATCH] Adapt redraft to display fees --- liana-gui/src/app/state/spend/step.rs | 20 ++++++++------ liana-gui/src/app/view/spend/mod.rs | 39 ++++++++++++++------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/liana-gui/src/app/state/spend/step.rs b/liana-gui/src/app/state/spend/step.rs index 504966e4..54a1c3e3 100644 --- a/liana-gui/src/app/state/spend/step.rs +++ b/liana-gui/src/app/state/spend/step.rs @@ -88,6 +88,7 @@ pub struct DefineSpend { batch_label: form::Value, amount_left_to_select: Option, feerate: form::Value, + fee_amount: Option, generated: Option<(Psbt, Vec)>, warning: Option, } @@ -125,6 +126,7 @@ impl DefineSpend { is_valid: false, is_duplicate: false, feerate: form::Value::default(), + fee_amount: None, amount_left_to_select: None, warning: None, } @@ -197,10 +199,7 @@ impl DefineSpend { /// redraft calculates the amount left to select and auto selects coins /// if the user did not select a coin manually fn redraft(&mut self, daemon: Arc) { - if !self.form_values_are_valid(true) - || self.exists_duplicate() - || self.recipients.is_empty() - { + if !self.form_values_are_valid(true) || self.exists_duplicate() { // The current form details are not valid to draft a spend, so remove any previously // calculated amount as it will no longer be valid and could be misleading, e.g. if // the user removes the amount from one of the recipients. @@ -218,9 +217,10 @@ impl DefineSpend { view::CreateSpendMessage::RecipientEdited(i, "amount", "".to_string()), ); } + self.fee_amount = None; return; } - + let is_self_transfer = self.recipients.is_empty(); let destinations: HashMap, u64> = self .recipients .iter() @@ -252,8 +252,7 @@ impl DefineSpend { } else { None }; - - let outpoints = if self.is_user_coin_selection { + let outpoints = if self.is_user_coin_selection || is_self_transfer { let outpoints: Vec<_> = self .coins .iter() @@ -279,10 +278,11 @@ impl DefineSpend { // doesn't take account of the fee, but passing an empty list to `create_spend_tx` // would use auto-selection and so we settle for this approximation. self.amount_left_to_select = Some(Amount::from_sat(destinations.values().sum())); + self.fee_amount = None; return; } outpoints - } else if self.send_max_to_recipient.is_some() { + } else if !self.is_user_coin_selection && self.send_max_to_recipient.is_some() { // If user has not selected coins, send the max available from all owned coins. self.coins .iter() @@ -323,6 +323,7 @@ impl DefineSpend { }) { Ok(CreateSpendResult::Success { psbt, .. }) => { self.warning = None; + self.fee_amount = Some(psbt.fee().expect("Valid fees")); if !self.is_user_coin_selection { let selected_coins: Vec = psbt .unsigned_tx @@ -358,6 +359,7 @@ impl DefineSpend { } } Ok(CreateSpendResult::InsufficientFunds { missing }) => { + self.fee_amount = None; self.amount_left_to_select = Some(Amount::from_sat(missing)); if !self.is_user_coin_selection { // The missing amount is based on all candidates for coin selection @@ -388,6 +390,7 @@ impl DefineSpend { } Err(e) => { self.warning = Some(e.into()); + self.fee_amount = None; } } } @@ -646,6 +649,7 @@ impl Step for DefineSpend { &self.batch_label, self.amount_left_to_select.as_ref(), &self.feerate, + self.fee_amount.as_ref(), self.warning.as_ref(), ) } diff --git a/liana-gui/src/app/view/spend/mod.rs b/liana-gui/src/app/view/spend/mod.rs index eb3cdc26..e8b9973a 100644 --- a/liana-gui/src/app/view/spend/mod.rs +++ b/liana-gui/src/app/view/spend/mod.rs @@ -119,6 +119,7 @@ pub fn create_spend_tx<'a>( batch_label: &form::Value, amount_left: Option<&Amount>, feerate: &form::Value, + fee_amount: Option<&Amount>, error: Option<&Error>, ) -> Element<'a, Message> { let is_self_send = recipients.is_empty(); @@ -176,28 +177,28 @@ pub fn create_spend_tx<'a>( ) .push( Row::new() + .spacing(10) + .align_y(Alignment::Center) + .push(Container::new(p1_bold("Feerate:")).padding(10)) .push( - Row::new() - .push(Container::new(p1_bold("Feerate")).padding(10)) - .spacing(10) - .push( - form::Form::new_trimmed( - "42 (in sats/vbyte)", - feerate, - move |msg| { - Message::CreateSpend(CreateSpendMessage::FeerateEdited(msg)) - }, - ) - .warning( - "Feerate must be an integer less than \ - or equal to 1000 sats/vbyte", - ) - .size(P1_SIZE) - .padding(10), + Container::new( + form::Form::new_trimmed("42 (in sats/vbyte)", feerate, move |msg| { + Message::CreateSpend(CreateSpendMessage::FeerateEdited(msg)) + }) + .warning( + "Feerate must be an integer less than or equal to 1000 sats/vbyte", ) - .width(Length::FillPortion(1)), + .size(P1_SIZE) + .padding(10), + ) + .width(Length::Fixed(150.0)), ) - .push(Space::with_width(Length::FillPortion(1))), + .push_maybe(fee_amount.map(|fee| { + Row::new() + .spacing(10) + .push(p1_regular("Fee:").style(theme::text::secondary)) + .push(amount_with_size(fee, P1_SIZE)) + })), ) .push( Container::new(