Merge #1662: Show fee next to feerate input when creating a new spend

b426d31914bf906d65307bdeb6851430d59b399d Adapt redraft to display fees (thomas)

Pull request description:

  ![Capture d’écran du 2025-04-21 07-41-39](https://github.com/user-attachments/assets/d9de2c77-a458-4116-bce2-e3ca530372cf)

  ![Capture d’écran du 2025-04-21 07-42-33](https://github.com/user-attachments/assets/a9648183-74f2-4ec6-8a8f-8667baa70fea)

  Closes #1653

ACKs for top commit:
  edouardparis:
    ACK b426d31914bf906d65307bdeb6851430d59b399d

Tree-SHA512: 23d3b15d0b3ec560a0a6992c2efe2557b3f5a142c690878a0c67893182560431e14ee3f4e5f9acc0a0adaaa5bcf41656964e9ed96a28da83bf312d0e08c2f4c2
This commit is contained in:
edouardparis 2025-04-23 09:59:25 +02:00
commit 0ff3479d56
No known key found for this signature in database
GPG Key ID: E65F7A089C20DC8F
2 changed files with 32 additions and 27 deletions

View File

@ -88,6 +88,7 @@ pub struct DefineSpend {
batch_label: form::Value<String>,
amount_left_to_select: Option<Amount>,
feerate: form::Value<String>,
fee_amount: Option<Amount>,
generated: Option<(Psbt, Vec<String>)>,
warning: Option<Error>,
}
@ -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<dyn Daemon + Sync + Send>) {
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<Address<address::NetworkUnchecked>, 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<OutPoint> = 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(),
)
}

View File

@ -119,6 +119,7 @@ pub fn create_spend_tx<'a>(
batch_label: &form::Value<String>,
amount_left: Option<&Amount>,
feerate: &form::Value<String>,
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(