diff --git a/gui/src/app/message.rs b/gui/src/app/message.rs index 93fafab32..5f3488c02 100644 --- a/gui/src/app/message.rs +++ b/gui/src/app/message.rs @@ -29,7 +29,7 @@ pub enum Message { Coins(Result, Error>), Labels(Result, Error>), SpendTxs(Result, Error>), - Psbt(Result), + Psbt(Result<(Psbt, Vec), Error>), RbfPsbt(Result), Recovery(Result), Signed(Fingerprint, Result), diff --git a/gui/src/app/state/spend/step.rs b/gui/src/app/state/spend/step.rs index ff575cf96..ddf4add59 100644 --- a/gui/src/app/state/spend/step.rs +++ b/gui/src/app/state/spend/step.rs @@ -29,7 +29,7 @@ pub struct TransactionDraft { network: Network, inputs: Vec, recipients: Vec, - generated: Option, + generated: Option<(Psbt, Vec)>, batch_label: Option, labels: HashMap, } @@ -80,7 +80,7 @@ pub struct DefineSpend { batch_label: form::Value, amount_left_to_select: Option, feerate: form::Value, - generated: Option, + generated: Option<(Psbt, Vec)>, warning: Option, } @@ -351,7 +351,9 @@ impl Step for DefineSpend { .create_spend_tx(&inputs, &outputs, feerate_vb, None) .map_err(|e| e.into()) .and_then(|res| match res { - CreateSpendResult::Success { psbt, .. } => Ok(psbt), + CreateSpendResult::Success { psbt, warnings } => { + Ok((psbt, warnings)) + } CreateSpendResult::InsufficientFunds { missing } => { Err(SpendCreationError::CoinSelection( liana::spend::InsufficientFunds { missing }, @@ -405,7 +407,7 @@ impl Step for DefineSpend { .filter_map(|(coin, selected)| if *selected { Some(coin) } else { None }) .cloned() .collect(); - if let Some(psbt) = &self.generated { + if let Some((psbt, _)) = &self.generated { draft.labels = self.coins_labels.clone(); for (i, output) in psbt.unsigned_tx.output.iter().enumerate() { if let Some(label) = self @@ -550,7 +552,7 @@ impl Recipient { pub struct SaveSpend { wallet: Arc, - spend: Option, + spend: Option<(psbt::PsbtState, Vec)>, curve: secp256k1::Secp256k1, } @@ -566,7 +568,7 @@ impl SaveSpend { impl Step for SaveSpend { fn load(&mut self, draft: &TransactionDraft) { - let psbt = draft.generated.clone().unwrap(); + let (psbt, warnings) = draft.generated.clone().unwrap(); let mut tx = SpendTx::new( None, psbt, @@ -590,12 +592,15 @@ impl Step for SaveSpend { } } - self.spend = Some(psbt::PsbtState::new(self.wallet.clone(), tx, false)); + self.spend = Some(( + psbt::PsbtState::new(self.wallet.clone(), tx, false), + warnings, + )); } fn subscription(&self) -> Subscription { - if let Some(spend) = &self.spend { - spend.subscription() + if let Some((psbt_state, _)) = &self.spend { + psbt_state.subscription() } else { Subscription::none() } @@ -607,26 +612,27 @@ impl Step for SaveSpend { cache: &Cache, message: Message, ) -> Command { - if let Some(spend) = &mut self.spend { - spend.update(daemon, cache, message) + if let Some((psbt_state, _)) = &mut self.spend { + psbt_state.update(daemon, cache, message) } else { Command::none() } } fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> { - let spend = self.spend.as_ref().unwrap(); + let (psbt_state, warnings) = self.spend.as_ref().unwrap(); let content = view::spend::spend_view( cache, - &spend.tx, - spend.saved, - &spend.desc_policy, - &spend.wallet.keys_aliases, - spend.labels_edited.cache(), + &psbt_state.tx, + warnings, + psbt_state.saved, + &psbt_state.desc_policy, + &psbt_state.wallet.keys_aliases, + psbt_state.labels_edited.cache(), cache.network, - spend.warning.as_ref(), + psbt_state.warning.as_ref(), ); - if let Some(action) = &spend.action { + if let Some(action) = &psbt_state.action { action.as_ref().view(content) } else { content diff --git a/gui/src/app/view/spend/mod.rs b/gui/src/app/view/spend/mod.rs index be4d451ff..50370c189 100644 --- a/gui/src/app/view/spend/mod.rs +++ b/gui/src/app/view/spend/mod.rs @@ -33,6 +33,7 @@ use crate::{ pub fn spend_view<'a>( cache: &'a Cache, tx: &'a SpendTx, + spend_warnings: &'a Vec, saved: bool, desc_info: &'a LianaPolicy, key_aliases: &'a HashMap, @@ -48,6 +49,21 @@ pub fn spend_view<'a>( .spacing(20) .push(Container::new(h3("Send")).width(Length::Fill)) .push(psbt::spend_header(tx, labels_editing)) + .push_maybe(if spend_warnings.is_empty() || saved { + None + } else { + Some(spend_warnings.iter().fold( + Column::new().padding(15).spacing(5), + |col, warning| { + col.push( + Row::new() + .spacing(5) + .push(icon::warning_icon().style(color::ORANGE)) + .push(text(warning).style(color::ORANGE)), + ) + }, + )) + }) .push(psbt::spend_overview_view(tx, desc_info, key_aliases)) .push( Column::new()