From 53d32085147fe6f8c0094c26008314eddfcc3bd0 Mon Sep 17 00:00:00 2001 From: edouard Date: Fri, 7 Apr 2023 12:05:17 +0200 Subject: [PATCH] Add alias to hot signer --- gui/src/app/state/spend/detail.rs | 4 + gui/src/app/view/spend/detail.rs | 37 ++-------- gui/src/installer/step/descriptor.rs | 34 ++++----- gui/src/installer/view.rs | 64 +++++++--------- gui/src/signer.rs | 2 +- gui/ui/src/component/hw.rs | 106 +++++++++++++++++++++++++++ 6 files changed, 158 insertions(+), 89 deletions(-) diff --git a/gui/src/app/state/spend/detail.rs b/gui/src/app/state/spend/detail.rs index ef6b9765..3b4348fb 100644 --- a/gui/src/app/state/spend/detail.rs +++ b/gui/src/app/state/spend/detail.rs @@ -379,6 +379,10 @@ impl Action for SignAction { self.error.as_ref(), &self.hws, self.wallet.signer.as_ref().map(|s| s.fingerprint()), + self.wallet + .signer + .as_ref() + .and_then(|signer| self.wallet.keys_aliases.get(&signer.fingerprint)), self.processing, self.chosen_hw, &self.signed, diff --git a/gui/src/app/view/spend/detail.rs b/gui/src/app/view/spend/detail.rs index 1e3b51b8..142c572b 100644 --- a/gui/src/app/view/spend/detail.rs +++ b/gui/src/app/view/spend/detail.rs @@ -18,7 +18,7 @@ use liana_ui::{ component::{ badge, button, card, collapse::Collapse, - form, separation, + form, hw, separation, text::{text, Text}, }, icon, theme, @@ -710,6 +710,7 @@ pub fn sign_action<'a>( warning: Option<&Error>, hws: &'a [HardwareWallet], signer: Option, + signer_alias: Option<&'a String>, processing: bool, chosen_hw: Option, signed: &[Fingerprint], @@ -746,35 +747,11 @@ pub fn sign_action<'a>( }, )) .push_maybe(signer.map(|fingerprint| { - Button::new( - Row::new() - .align_items(Alignment::Center) - .push( - Column::new() - .width(Length::Fill) - .push(text("This computer").bold()) - .push( - text(format!("fingerprint: {}", fingerprint)) - .small(), - ) - .spacing(5) - .width(Length::Fill), - ) - .push_maybe(if signed.contains(&fingerprint) { - Some( - Row::new() - .align_items(Alignment::Center) - .spacing(5) - .push( - icon::circle_check_icon() - .style(color::legacy::SUCCESS), - ) - .push(text("Signed").style(color::legacy::SUCCESS)), - ) - } else { - None - }), - ) + Button::new(if signed.contains(&fingerprint) { + hw::sign_success_hot_signer(fingerprint, signer_alias) + } else { + hw::hot_signer(fingerprint, signer_alias) + }) .on_press(Message::Spend(SpendTxMessage::SelectHotSigner)) .padding(10) .style(theme::Button::Secondary) diff --git a/gui/src/installer/step/descriptor.rs b/gui/src/installer/step/descriptor.rs index 07d472ae..95fa07b3 100644 --- a/gui/src/installer/step/descriptor.rs +++ b/gui/src/installer/step/descriptor.rs @@ -725,11 +725,9 @@ pub struct EditXpubModal { form_xpub: form::Value, edit_name: bool, - chosen_hw: Option, hws: Vec, - - signer: Arc, - chosen_signer: bool, + hot_signer: Arc, + chosen_signer: Option, } impl EditXpubModal { @@ -742,7 +740,7 @@ impl EditXpubModal { network: Network, account_indexes: HashMap, keys_aliases: HashMap, - signer: Arc, + hot_signer: Arc, ) -> Self { Self { form_name: form::Value { @@ -757,14 +755,13 @@ impl EditXpubModal { account_indexes, path_index, key_index, - chosen_hw: None, processing: false, hws: Vec::new(), error: None, network, edit_name: false, - chosen_signer: Some(signer.fingerprint()) == key.map(|k| k.master_fingerprint()), - signer, + chosen_signer: key.map(|k| k.master_fingerprint()), + hot_signer, } } fn load(&self) -> Command { @@ -790,7 +787,7 @@ impl DescriptorEditModal for EditXpubModal { .. }) = self.hws.get(i) { - self.chosen_hw = Some(i); + self.chosen_signer = Some(*fingerprint); self.processing = true; // If another account n exists, the key is retrieved for the account n+1 let account_index = self @@ -815,10 +812,7 @@ impl DescriptorEditModal for EditXpubModal { Message::ConnectedHardwareWallets(hws) => { self.hws = hws; if let Ok(key) = DescriptorPublicKey::from_str(&self.form_xpub.value) { - self.chosen_hw = self - .hws - .iter() - .position(|hw| hw.fingerprint() == Some(key.master_fingerprint())); + self.chosen_signer = Some(key.master_fingerprint()); } } Message::Reload => { @@ -826,10 +820,9 @@ impl DescriptorEditModal for EditXpubModal { return self.load(); } Message::UseHotSigner => { - self.chosen_hw = None; - self.chosen_signer = true; + let fingerprint = self.hot_signer.fingerprint(); + self.chosen_signer = Some(fingerprint); self.form_xpub.valid = true; - let fingerprint = self.signer.fingerprint(); if let Some(alias) = self.keys_aliases.get(&fingerprint) { self.form_name.valid = true; self.form_name.value = alias.clone(); @@ -848,7 +841,7 @@ impl DescriptorEditModal for EditXpubModal { "[{}{}]{}", fingerprint, derivation_path.to_string().trim_start_matches('m'), - self.signer.get_extended_pubkey(&derivation_path) + self.hot_signer.get_extended_pubkey(&derivation_path) ); } Message::DefineDescriptor(message::DefineDescriptor::KeyModal(msg)) => match msg { @@ -863,12 +856,12 @@ impl DescriptorEditModal for EditXpubModal { } else { self.edit_name = true; } - self.chosen_signer = false; + self.chosen_signer = None; self.form_xpub.valid = true; self.form_xpub.value = key.to_string(); } Err(e) => { - self.chosen_hw = None; + self.chosen_signer = None; self.error = Some(e); } } @@ -944,8 +937,9 @@ impl DescriptorEditModal for EditXpubModal { &self.hws, self.error.as_ref(), self.processing, - self.chosen_hw, self.chosen_signer, + &self.hot_signer, + self.keys_aliases.get(&self.hot_signer.fingerprint), &self.form_xpub, &self.form_name, self.edit_name, diff --git a/gui/src/installer/view.rs b/gui/src/installer/view.rs index 2f4a0f90..827c7f27 100644 --- a/gui/src/installer/view.rs +++ b/gui/src/installer/view.rs @@ -5,7 +5,7 @@ use iced::{alignment, Alignment, Length}; use std::{collections::HashSet, str::FromStr}; -use liana::miniscript::bitcoin; +use liana::miniscript::bitcoin::{self, util::bip32::Fingerprint}; use liana_ui::{ color, component::{ @@ -25,6 +25,7 @@ use crate::{ message::{self, Message}, prompt, Error, }, + signer::Signer, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -1236,8 +1237,9 @@ pub fn edit_key_modal<'a>( hws: &'a [HardwareWallet], error: Option<&Error>, processing: bool, - chosen_hw: Option, - chosen_signer: bool, + chosen_signer: Option, + signer: &Signer, + signer_alias: Option<&'a String>, form_xpub: &form::Value, form_name: &'a form::Value, edit_name: bool, @@ -1269,37 +1271,21 @@ pub fn edit_key_modal<'a>( col.push(hw_list_view( i, hw, - Some(i) == chosen_hw, + hw.fingerprint() == chosen_signer, processing, !processing - && Some(i) == chosen_hw + && hw.fingerprint() == chosen_signer && form_xpub.valid && !form_xpub.value.is_empty(), )) }, )) .push( - Button::new( - Row::new() - .padding(5) - .width(Length::Fill) - .align_items(Alignment::Center) - .push( - Column::new() - .spacing(5) - .push(text("This computer").bold()) - .push( - text("Derive a key from a mnemonic stored on this computer").small(), - ) - .width(Length::Fill), - ) - .push_maybe(if chosen_signer { - Some(icon::circle_check_icon().style(color::legacy::SUCCESS)) - } else { - None - }) - .spacing(10), - ) + Button::new(if Some(signer.fingerprint) == chosen_signer { + hw::selected_hot_signer(signer.fingerprint, signer_alias) + } else { + hw::unselected_hot_signer(signer.fingerprint, signer_alias) + }) .width(Length::Fill) .on_press(Message::UseHotSigner) .style(theme::Button::Secondary), @@ -1315,7 +1301,9 @@ pub fn edit_key_modal<'a>( .push( form::Form::new("Extended public key", form_xpub, |msg| { Message::DefineDescriptor( - message::DefineDescriptor::KeyModal(message::ImportKeyModal::XPubEdited(msg)), + message::DefineDescriptor::KeyModal( + message::ImportKeyModal::XPubEdited(msg), + ), ) }) .warning(if network == bitcoin::Network::Bitcoin { @@ -1349,9 +1337,9 @@ pub fn edit_key_modal<'a>( .push(text(&form_name.value)), ) .push(button::border(Some(icon::pencil_icon()), "Edit").on_press( - Message::DefineDescriptor( - message::DefineDescriptor::KeyModal(message::ImportKeyModal::EditName), - ) + Message::DefineDescriptor(message::DefineDescriptor::KeyModal( + message::ImportKeyModal::EditName, + )), )), ) } else if !form_xpub.value.is_empty() && form_xpub.valid { @@ -1365,9 +1353,9 @@ pub fn edit_key_modal<'a>( ) .push( form::Form::new("Alias", form_name, |msg| { - Message::DefineDescriptor( - message::DefineDescriptor::KeyModal(message::ImportKeyModal::NameEdited(msg)), - ) + Message::DefineDescriptor(message::DefineDescriptor::KeyModal( + message::ImportKeyModal::NameEdited(msg), + )) }) .warning("Please enter correct alias") .size(20) @@ -1381,11 +1369,11 @@ pub fn edit_key_modal<'a>( if form_xpub.valid && !form_xpub.value.is_empty() && !form_name.value.is_empty() { button::primary(None, "Apply") - .on_press( - Message::DefineDescriptor( - message::DefineDescriptor::KeyModal(message::ImportKeyModal::ConfirmXpub), - ) - ) + .on_press(Message::DefineDescriptor( + message::DefineDescriptor::KeyModal( + message::ImportKeyModal::ConfirmXpub, + ), + )) .width(Length::Units(200)) } else { button::primary(None, "Apply").width(Length::Units(100)) diff --git a/gui/src/signer.rs b/gui/src/signer.rs index cad4ffc5..4e2da9e1 100644 --- a/gui/src/signer.rs +++ b/gui/src/signer.rs @@ -15,7 +15,7 @@ use liana::{ pub struct Signer { curve: secp256k1::Secp256k1, key: HotSigner, - fingerprint: Fingerprint, + pub fingerprint: Fingerprint, } impl std::fmt::Debug for Signer { diff --git a/gui/ui/src/component/hw.rs b/gui/ui/src/component/hw.rs index 335badbb..a06dd801 100644 --- a/gui/ui/src/component/hw.rs +++ b/gui/ui/src/component/hw.rs @@ -235,3 +235,109 @@ pub fn unsupported_hardware_wallet<'a, T: 'a, K: Display, V: Display>( ) .padding(10) } + +pub fn sign_success_hot_signer<'a, T: 'a, F: Display>( + fingerprint: F, + alias: Option>>, +) -> Container<'a, T> { + container( + row(vec![ + column(vec![ + Row::new() + .spacing(5) + .push_maybe(alias.map(|a| text(a).bold())) + .push(text(format!("#{}", fingerprint))) + .into(), + Row::new() + .spacing(5) + .push(text("This computer").small()) + .into(), + ]) + .width(Length::Fill) + .into(), + row(vec![ + icon::circle_check_icon() + .style(color::legacy::SUCCESS) + .into(), + text("Signed").style(color::legacy::SUCCESS).into(), + ]) + .align_items(Alignment::Center) + .spacing(5) + .into(), + ]) + .align_items(Alignment::Center), + ) + .padding(10) +} + +pub fn selected_hot_signer<'a, T: 'a, F: Display>( + fingerprint: F, + alias: Option>>, +) -> Container<'a, T> { + container( + row(vec![ + column(vec![ + Row::new() + .spacing(5) + .push_maybe(alias.map(|a| text(a).bold())) + .push(text(format!("#{}", fingerprint))) + .into(), + Row::new() + .spacing(5) + .push(text("This computer").small()) + .push(text("(A derived key from a mnemonic stored locally)").small()) + .into(), + ]) + .width(Length::Fill) + .into(), + icon::circle_check_icon() + .style(color::legacy::SUCCESS) + .into(), + ]) + .align_items(Alignment::Center), + ) + .padding(10) +} + +pub fn unselected_hot_signer<'a, T: 'a, F: Display>( + fingerprint: F, + alias: Option>>, +) -> Container<'a, T> { + Container::new( + column(vec![ + Row::new() + .spacing(5) + .push_maybe(alias.map(|a| text(a).bold())) + .push(text(format!("#{}", fingerprint))) + .into(), + Row::new() + .spacing(5) + .push(text("This computer").small()) + .push(text("(A derived key from a mnemonic stored locally)").small()) + .into(), + ]) + .width(Length::Fill), + ) + .padding(10) +} + +pub fn hot_signer<'a, T: 'a, F: Display>( + fingerprint: F, + alias: Option>>, +) -> Container<'a, T> { + Container::new( + column(vec![ + Row::new() + .spacing(5) + .push_maybe(alias.map(|a| text(a).bold())) + .push(text(format!("#{}", fingerprint))) + .into(), + Row::new() + .spacing(5) + .push(text("This computer").small()) + .into(), + ]) + .width(Length::Fill), + ) + .padding(10) +}