Skip to content

Commit

Permalink
gui(spend): display warnings for draft PSBTs
Browse files Browse the repository at this point in the history
  • Loading branch information
jp1ac4 committed Jan 29, 2024
1 parent a34070d commit 0af4fe3
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 23 deletions.
2 changes: 1 addition & 1 deletion gui/src/app/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub enum Message {
Coins(Result<Vec<Coin>, Error>),
Labels(Result<HashMap<String, String>, Error>),
SpendTxs(Result<Vec<SpendTx>, Error>),
Psbt(Result<Psbt, Error>),
Psbt(Result<(Psbt, Vec<String>), Error>),
Recovery(Result<SpendTx, Error>),
Signed(Fingerprint, Result<Psbt, Error>),
WalletRegistered(Result<Fingerprint, Error>),
Expand Down
44 changes: 25 additions & 19 deletions gui/src/app/state/spend/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct TransactionDraft {
network: Network,
inputs: Vec<Coin>,
recipients: Vec<Recipient>,
generated: Option<Psbt>,
generated: Option<(Psbt, Vec<String>)>,
batch_label: Option<String>,
labels: HashMap<String, String>,
}
Expand Down Expand Up @@ -83,7 +83,7 @@ pub struct DefineSpend {
batch_label: form::Value<String>,
amount_left_to_select: Option<Amount>,
feerate: form::Value<String>,
generated: Option<Psbt>,
generated: Option<(Psbt, Vec<String>)>,
warning: Option<Error>,
}

Expand Down Expand Up @@ -384,7 +384,9 @@ impl Step for DefineSpend {
.create_spend_tx(&inputs, &outputs, feerate_vb)
.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 },
Expand Down Expand Up @@ -438,7 +440,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
Expand Down Expand Up @@ -583,7 +585,7 @@ impl Recipient {

pub struct SaveSpend {
wallet: Arc<Wallet>,
spend: Option<psbt::PsbtState>,
spend: Option<(psbt::PsbtState, Vec<String>)>,
curve: secp256k1::Secp256k1<secp256k1::VerifyOnly>,
}

Expand All @@ -599,7 +601,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,
Expand All @@ -623,12 +625,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<Message> {
if let Some(spend) = &self.spend {
spend.subscription()
if let Some((psbt_state, _)) = &self.spend {
psbt_state.subscription()
} else {
Subscription::none()
}
Expand All @@ -640,26 +645,27 @@ impl Step for SaveSpend {
cache: &Cache,
message: Message,
) -> Command<Message> {
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
Expand Down
78 changes: 76 additions & 2 deletions gui/src/app/view/psbt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub fn psbt_view<'a>(
}),
)
.push(spend_header(tx, labels_editing))
.push(spend_overview_view(tx, desc_info, key_aliases))
.push(spend_overview_view(tx, desc_info, key_aliases, None))
.push(
Column::new()
.spacing(20)
Expand Down Expand Up @@ -255,6 +255,7 @@ pub fn spend_overview_view<'a>(
tx: &'a SpendTx,
desc_info: &'a LianaPolicy,
key_aliases: &'a HashMap<Fingerprint, String>,
warnings: Option<&'a Vec<String>>,
) -> Element<'a, Message> {
Column::new()
.spacing(20)
Expand Down Expand Up @@ -306,7 +307,8 @@ pub fn spend_overview_view<'a>(
.align_items(Alignment::Center),
),
)
.push(signatures(tx, desc_info, key_aliases)),
.push(signatures(tx, desc_info, key_aliases))
.push_maybe(warnings.map(|w| spend_warnings_view(w))),
)
.style(theme::Container::Card(theme::Card::Simple)),
)
Expand Down Expand Up @@ -336,6 +338,78 @@ pub fn spend_overview_view<'a>(
.into()
}

fn spend_warnings_button<'a>(
num_warnings: usize,
is_collapsed: bool,
) -> impl Fn() -> Button<'a, liana_ui::component::collapse::Event<Message>> {
let color = if num_warnings >= 1 {
color::ORANGE
} else {
color::GREEN
};
move || {
Button::new(
Row::new()
.align_items(Alignment::Center)
.spacing(20)
.push(p1_bold("Warnings"))
.push(
Row::new()
.spacing(5)
.align_items(Alignment::Center)
.push(if num_warnings >= 1 {
icon::warning_icon().style(color)
} else {
icon::circle_check_icon().style(color)
})
.push(
text(format!(
"{} warning{}",
num_warnings,
if num_warnings == 1 { "" } else { "s" }
))
.style(color),
)
.width(Length::Fill),
)
.push(if is_collapsed {
icon::collapsed_icon()
} else {
icon::collapse_icon()
}),
)
.padding(15)
.width(Length::Fill)
.style(theme::Button::TransparentBorder)
}
}

fn spend_warnings_view(warnings: &Vec<String>) -> Element<Message> {
Container::new(Collapse::new(
spend_warnings_button(warnings.len(), false),
spend_warnings_button(warnings.len(), true),
move || {
Into::<Element<Message>>::into(
warnings.iter().fold(
Column::new()
.padding(15)
.spacing(10)
.push(text(if warnings.is_empty() {
"No warnings were generated.".to_string()
} else {
format!(
"The following warning{} generated:",
if warnings.len() > 1 { "s were" } else { " was" }
)
})),
|col, warning| col.push(text(warning).style(color::GREY_3)),
),
)
},
))
.into()
}

pub fn signatures<'a>(
tx: &'a SpendTx,
desc_info: &'a LianaPolicy,
Expand Down
8 changes: 7 additions & 1 deletion gui/src/app/view/spend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::{
pub fn spend_view<'a>(
cache: &'a Cache,
tx: &'a SpendTx,
spend_warnings: &'a Vec<String>,
saved: bool,
desc_info: &'a LianaPolicy,
key_aliases: &'a HashMap<Fingerprint, String>,
Expand All @@ -48,7 +49,12 @@ pub fn spend_view<'a>(
.spacing(20)
.push(Container::new(h3("Send")).width(Length::Fill))
.push(psbt::spend_header(tx, labels_editing))
.push(psbt::spend_overview_view(tx, desc_info, key_aliases))
.push(psbt::spend_overview_view(
tx,
desc_info,
key_aliases,
if saved { None } else { Some(spend_warnings) },
))
.push(
Column::new()
.spacing(20)
Expand Down

0 comments on commit 0af4fe3

Please sign in to comment.