Remove participate wallet process for share xpubs simple panel
This commit is contained in:
parent
86a79759e6
commit
6cbf81a3c5
@ -12,7 +12,7 @@ use async_hwi::{DeviceKind, Version};
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Message {
|
||||
CreateWallet,
|
||||
ParticipateWallet,
|
||||
ShareXpubs,
|
||||
ImportWallet,
|
||||
UserActionDone(bool),
|
||||
Exit(PathBuf, Option<Bitcoind>),
|
||||
|
||||
@ -27,8 +27,8 @@ use crate::{
|
||||
pub use message::Message;
|
||||
use step::{
|
||||
BackupDescriptor, BackupMnemonic, DefineBitcoind, DefineDescriptor, Final, ImportDescriptor,
|
||||
InternalBitcoindStep, ParticipateXpub, RecoverMnemonic, RegisterDescriptor,
|
||||
SelectBitcoindTypeStep, Step, Welcome,
|
||||
InternalBitcoindStep, RecoverMnemonic, RegisterDescriptor, SelectBitcoindTypeStep, ShareXpubs,
|
||||
Step, Welcome,
|
||||
};
|
||||
|
||||
pub struct Installer {
|
||||
@ -155,17 +155,10 @@ impl Installer {
|
||||
];
|
||||
self.next()
|
||||
}
|
||||
Message::ParticipateWallet => {
|
||||
Message::ShareXpubs => {
|
||||
self.steps = vec![
|
||||
Welcome::default().into(),
|
||||
ParticipateXpub::new(self.network, self.signer.clone()).into(),
|
||||
ImportDescriptor::new(self.network).into(),
|
||||
BackupMnemonic::new(self.signer.clone()).into(),
|
||||
RegisterDescriptor::new_import_wallet().into(),
|
||||
SelectBitcoindTypeStep::new().into(),
|
||||
InternalBitcoindStep::new(&self.context.data_dir).into(),
|
||||
DefineBitcoind::new().into(),
|
||||
Final::new().into(),
|
||||
ShareXpubs::new(self.network, self.signer.clone()).into(),
|
||||
];
|
||||
self.next()
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use liana::{
|
||||
descriptors::{LianaDescriptor, LianaPolicy, PathInfo},
|
||||
miniscript::{
|
||||
bitcoin::{
|
||||
bip32::{ChildNumber, DerivationPath, Fingerprint},
|
||||
bip32::{DerivationPath, Fingerprint},
|
||||
Network,
|
||||
},
|
||||
descriptor::{
|
||||
@ -1064,7 +1064,7 @@ impl DescriptorEditModal for EditXpubModal {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_derivation_path(network: Network) -> DerivationPath {
|
||||
pub fn default_derivation_path(network: Network) -> DerivationPath {
|
||||
DerivationPath::from_str({
|
||||
if network == Network::Bitcoin {
|
||||
"m/48'/0'/0'/2'"
|
||||
@ -1077,7 +1077,7 @@ fn default_derivation_path(network: Network) -> DerivationPath {
|
||||
|
||||
/// LIANA_STANDARD_PATH: m/48'/0'/0'/2';
|
||||
/// LIANA_TESTNET_STANDARD_PATH: m/48'/1'/0'/2';
|
||||
async fn get_extended_pubkey(
|
||||
pub async fn get_extended_pubkey(
|
||||
hw: std::sync::Arc<dyn async_hwi::HWI + Send + Sync>,
|
||||
fingerprint: Fingerprint,
|
||||
network: Network,
|
||||
@ -1095,178 +1095,6 @@ async fn get_extended_pubkey(
|
||||
}))
|
||||
}
|
||||
|
||||
pub struct HardwareWalletXpubs {
|
||||
fingerprint: Fingerprint,
|
||||
xpubs: Vec<String>,
|
||||
processing: bool,
|
||||
error: Option<Error>,
|
||||
}
|
||||
|
||||
pub struct SignerXpubs {
|
||||
signer: Arc<Mutex<Signer>>,
|
||||
xpubs: Vec<String>,
|
||||
next_account: ChildNumber,
|
||||
}
|
||||
|
||||
impl SignerXpubs {
|
||||
fn new(signer: Arc<Mutex<Signer>>) -> Self {
|
||||
Self {
|
||||
signer,
|
||||
xpubs: Vec::new(),
|
||||
next_account: ChildNumber::from_hardened_idx(0).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn select(&mut self, network: Network) {
|
||||
self.next_account = self.next_account.increment().unwrap();
|
||||
let signer = self.signer.lock().unwrap();
|
||||
let derivation_path = default_derivation_path(network);
|
||||
// We keep only one for the moment.
|
||||
self.xpubs = vec![format!(
|
||||
"[{}{}]{}",
|
||||
signer.fingerprint(),
|
||||
derivation_path.to_string().trim_start_matches('m'),
|
||||
signer.get_extended_pubkey(&derivation_path)
|
||||
)];
|
||||
}
|
||||
|
||||
pub fn view(&self) -> Element<Message> {
|
||||
view::signer_xpubs(&self.xpubs)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParticipateXpub {
|
||||
network: Network,
|
||||
|
||||
shared: bool,
|
||||
|
||||
hw_xpubs: Vec<HardwareWalletXpubs>,
|
||||
xpubs_signer: SignerXpubs,
|
||||
}
|
||||
|
||||
impl ParticipateXpub {
|
||||
pub fn new(network: Network, signer: Arc<Mutex<Signer>>) -> Self {
|
||||
Self {
|
||||
network,
|
||||
hw_xpubs: Vec::new(),
|
||||
shared: false,
|
||||
xpubs_signer: SignerXpubs::new(signer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Step for ParticipateXpub {
|
||||
// form value is set as valid each time it is edited.
|
||||
// Verification of the values is happening when the user click on Next button.
|
||||
fn update(&mut self, hws: &mut HardwareWallets, message: Message) -> Command<Message> {
|
||||
match message {
|
||||
Message::UserActionDone(shared) => self.shared = shared,
|
||||
Message::ImportXpub(fg, res) => {
|
||||
if let Some(hw_xpubs) = self.hw_xpubs.iter_mut().find(|x| x.fingerprint == fg) {
|
||||
hw_xpubs.processing = false;
|
||||
match res {
|
||||
Err(e) => {
|
||||
hw_xpubs.error = e.into();
|
||||
}
|
||||
Ok(xpub) => {
|
||||
hw_xpubs.error = None;
|
||||
// We keep only one for the moment.
|
||||
hw_xpubs.xpubs = vec![xpub.to_string()];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::UseHotSigner => {
|
||||
self.xpubs_signer.select(self.network);
|
||||
}
|
||||
Message::Select(i) => {
|
||||
if let Some(HardwareWallet::Supported {
|
||||
device,
|
||||
fingerprint,
|
||||
..
|
||||
}) = hws.list.get(i)
|
||||
{
|
||||
let device = device.clone();
|
||||
let fingerprint = *fingerprint;
|
||||
let network = self.network;
|
||||
if let Some(hw_xpubs) = self
|
||||
.hw_xpubs
|
||||
.iter_mut()
|
||||
.find(|x| x.fingerprint == fingerprint)
|
||||
{
|
||||
hw_xpubs.processing = true;
|
||||
hw_xpubs.error = None;
|
||||
} else {
|
||||
self.hw_xpubs.push(HardwareWalletXpubs {
|
||||
fingerprint,
|
||||
xpubs: Vec::new(),
|
||||
processing: true,
|
||||
error: None,
|
||||
});
|
||||
}
|
||||
return Command::perform(
|
||||
async move {
|
||||
(
|
||||
fingerprint,
|
||||
get_extended_pubkey(device, fingerprint, network).await,
|
||||
)
|
||||
},
|
||||
|(fingerprint, res)| Message::ImportXpub(fingerprint, res),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn subscription(&self, hws: &HardwareWallets) -> Subscription<Message> {
|
||||
hws.refresh().map(Message::HardwareWallets)
|
||||
}
|
||||
|
||||
fn apply(&mut self, ctx: &mut Context) -> bool {
|
||||
ctx.bitcoin_config.network = self.network;
|
||||
// Drop connections to hardware wallets.
|
||||
self.hw_xpubs = Vec::new();
|
||||
true
|
||||
}
|
||||
|
||||
fn view<'a>(&'a self, hws: &'a HardwareWallets, progress: (usize, usize)) -> Element<Message> {
|
||||
view::participate_xpub(
|
||||
progress,
|
||||
hws.list
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, hw)| {
|
||||
if let Some(hw_xpubs) = self
|
||||
.hw_xpubs
|
||||
.iter()
|
||||
.find(|h| hw.fingerprint() == Some(h.fingerprint))
|
||||
{
|
||||
view::hardware_wallet_xpubs(
|
||||
i,
|
||||
hw,
|
||||
Some(&hw_xpubs.xpubs),
|
||||
hw_xpubs.processing,
|
||||
hw_xpubs.error.as_ref(),
|
||||
)
|
||||
} else {
|
||||
view::hardware_wallet_xpubs(i, hw, None, false, None)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
self.xpubs_signer.view(),
|
||||
self.shared,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParticipateXpub> for Box<dyn Step> {
|
||||
fn from(s: ParticipateXpub) -> Box<dyn Step> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ImportDescriptor {
|
||||
network: Network,
|
||||
imported_descriptor: form::Value<String>,
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
mod bitcoind;
|
||||
mod descriptor;
|
||||
mod mnemonic;
|
||||
mod share_xpubs;
|
||||
|
||||
pub use bitcoind::{
|
||||
DefineBitcoind, DownloadState, InstallState, InternalBitcoindStep, SelectBitcoindTypeStep,
|
||||
};
|
||||
|
||||
pub use descriptor::{
|
||||
BackupDescriptor, DefineDescriptor, ImportDescriptor, ParticipateXpub, RegisterDescriptor,
|
||||
};
|
||||
pub use descriptor::{BackupDescriptor, DefineDescriptor, ImportDescriptor, RegisterDescriptor};
|
||||
|
||||
pub use mnemonic::{BackupMnemonic, RecoverMnemonic};
|
||||
pub use share_xpubs::ShareXpubs;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
192
gui/src/installer/step/share_xpubs.rs
Normal file
192
gui/src/installer/step/share_xpubs.rs
Normal file
@ -0,0 +1,192 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use iced::{Command, Subscription};
|
||||
use liana::miniscript::bitcoin::{
|
||||
bip32::{ChildNumber, Fingerprint},
|
||||
Network,
|
||||
};
|
||||
|
||||
use liana_ui::widget::Element;
|
||||
|
||||
use crate::{
|
||||
hw::{HardwareWallet, HardwareWallets},
|
||||
installer::{
|
||||
message::Message,
|
||||
step::{
|
||||
descriptor::{default_derivation_path, get_extended_pubkey},
|
||||
Context, Step,
|
||||
},
|
||||
view, Error,
|
||||
},
|
||||
signer::Signer,
|
||||
};
|
||||
|
||||
pub struct HardwareWalletXpubs {
|
||||
fingerprint: Fingerprint,
|
||||
xpubs: Vec<String>,
|
||||
processing: bool,
|
||||
error: Option<Error>,
|
||||
}
|
||||
|
||||
pub struct SignerXpubs {
|
||||
signer: Arc<Mutex<Signer>>,
|
||||
xpubs: Vec<String>,
|
||||
next_account: ChildNumber,
|
||||
}
|
||||
|
||||
impl SignerXpubs {
|
||||
fn new(signer: Arc<Mutex<Signer>>) -> Self {
|
||||
Self {
|
||||
signer,
|
||||
xpubs: Vec::new(),
|
||||
next_account: ChildNumber::from_hardened_idx(0).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn select(&mut self, network: Network) {
|
||||
self.next_account = self.next_account.increment().unwrap();
|
||||
let signer = self.signer.lock().unwrap();
|
||||
let derivation_path = default_derivation_path(network);
|
||||
// We keep only one for the moment.
|
||||
self.xpubs = vec![format!(
|
||||
"[{}{}]{}",
|
||||
signer.fingerprint(),
|
||||
derivation_path.to_string().trim_start_matches('m'),
|
||||
signer.get_extended_pubkey(&derivation_path)
|
||||
)];
|
||||
}
|
||||
|
||||
pub fn view(&self) -> Element<Message> {
|
||||
view::signer_xpubs(&self.xpubs)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ShareXpubs {
|
||||
network: Network,
|
||||
|
||||
shared: bool,
|
||||
|
||||
hw_xpubs: Vec<HardwareWalletXpubs>,
|
||||
xpubs_signer: SignerXpubs,
|
||||
}
|
||||
|
||||
impl ShareXpubs {
|
||||
pub fn new(network: Network, signer: Arc<Mutex<Signer>>) -> Self {
|
||||
Self {
|
||||
network,
|
||||
hw_xpubs: Vec::new(),
|
||||
shared: false,
|
||||
xpubs_signer: SignerXpubs::new(signer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Step for ShareXpubs {
|
||||
// form value is set as valid each time it is edited.
|
||||
// Verification of the values is happening when the user click on Next button.
|
||||
fn update(&mut self, hws: &mut HardwareWallets, message: Message) -> Command<Message> {
|
||||
match message {
|
||||
Message::UserActionDone(shared) => self.shared = shared,
|
||||
Message::ImportXpub(fg, res) => {
|
||||
if let Some(hw_xpubs) = self.hw_xpubs.iter_mut().find(|x| x.fingerprint == fg) {
|
||||
hw_xpubs.processing = false;
|
||||
match res {
|
||||
Err(e) => {
|
||||
hw_xpubs.error = e.into();
|
||||
}
|
||||
Ok(xpub) => {
|
||||
hw_xpubs.error = None;
|
||||
// We keep only one for the moment.
|
||||
hw_xpubs.xpubs = vec![xpub.to_string()];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::UseHotSigner => {
|
||||
self.xpubs_signer.select(self.network);
|
||||
}
|
||||
Message::Select(i) => {
|
||||
if let Some(HardwareWallet::Supported {
|
||||
device,
|
||||
fingerprint,
|
||||
..
|
||||
}) = hws.list.get(i)
|
||||
{
|
||||
let device = device.clone();
|
||||
let fingerprint = *fingerprint;
|
||||
let network = self.network;
|
||||
if let Some(hw_xpubs) = self
|
||||
.hw_xpubs
|
||||
.iter_mut()
|
||||
.find(|x| x.fingerprint == fingerprint)
|
||||
{
|
||||
hw_xpubs.processing = true;
|
||||
hw_xpubs.error = None;
|
||||
} else {
|
||||
self.hw_xpubs.push(HardwareWalletXpubs {
|
||||
fingerprint,
|
||||
xpubs: Vec::new(),
|
||||
processing: true,
|
||||
error: None,
|
||||
});
|
||||
}
|
||||
return Command::perform(
|
||||
async move {
|
||||
(
|
||||
fingerprint,
|
||||
get_extended_pubkey(device, fingerprint, network).await,
|
||||
)
|
||||
},
|
||||
|(fingerprint, res)| Message::ImportXpub(fingerprint, res),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn subscription(&self, hws: &HardwareWallets) -> Subscription<Message> {
|
||||
hws.refresh().map(Message::HardwareWallets)
|
||||
}
|
||||
|
||||
fn apply(&mut self, ctx: &mut Context) -> bool {
|
||||
ctx.bitcoin_config.network = self.network;
|
||||
// Drop connections to hardware wallets.
|
||||
self.hw_xpubs = Vec::new();
|
||||
true
|
||||
}
|
||||
|
||||
fn view<'a>(&'a self, hws: &'a HardwareWallets, _progress: (usize, usize)) -> Element<Message> {
|
||||
view::share_xpubs(
|
||||
hws.list
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, hw)| {
|
||||
if let Some(hw_xpubs) = self
|
||||
.hw_xpubs
|
||||
.iter()
|
||||
.find(|h| hw.fingerprint() == Some(h.fingerprint))
|
||||
{
|
||||
view::hardware_wallet_xpubs(
|
||||
i,
|
||||
hw,
|
||||
Some(&hw_xpubs.xpubs),
|
||||
hw_xpubs.processing,
|
||||
hw_xpubs.error.as_ref(),
|
||||
)
|
||||
} else {
|
||||
view::hardware_wallet_xpubs(i, hw, None, false, None)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
self.xpubs_signer.view(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ShareXpubs> for Box<dyn Step> {
|
||||
fn from(s: ShareXpubs) -> Box<dyn Step> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,32 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
Container::new(
|
||||
Column::new()
|
||||
.push(
|
||||
Container::new(image::liana_brand_grey().width(Length::Fixed(200.0))).padding(100),
|
||||
Container::new(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(image::liana_brand_grey().width(Length::Fixed(200.0)))
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
Row::new()
|
||||
.push(
|
||||
button::secondary(
|
||||
Some(icon::previous_icon()),
|
||||
"Change network",
|
||||
)
|
||||
.width(Length::Fixed(200.0))
|
||||
.on_press(Message::BackToLauncher),
|
||||
)
|
||||
.push(
|
||||
button::secondary(None, "Share Xpubs")
|
||||
.width(Length::Fixed(200.0))
|
||||
.on_press(Message::ShareXpubs),
|
||||
)
|
||||
.spacing(20),
|
||||
),
|
||||
)
|
||||
.padding(100),
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
@ -69,28 +94,6 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
)
|
||||
.padding(20),
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
image::participate_in_new_wallet_icon()
|
||||
.width(Length::Fixed(200.0)),
|
||||
)
|
||||
.push(
|
||||
p1_regular("Participate in new wallet")
|
||||
.style(color::GREY_3),
|
||||
)
|
||||
.push(
|
||||
button::secondary(None, "Select")
|
||||
.width(Length::Fixed(200.0))
|
||||
.on_press(Message::ParticipateWallet),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.padding(20),
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
Column::new()
|
||||
@ -101,7 +104,8 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
.width(Length::Fixed(100.0)),
|
||||
)
|
||||
.push(
|
||||
p1_regular("Restore a wallet").style(color::GREY_3),
|
||||
p1_regular("Add an existing wallet")
|
||||
.style(color::GREY_3),
|
||||
)
|
||||
.push(
|
||||
button::secondary(None, "Select")
|
||||
@ -113,11 +117,6 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
.padding(20),
|
||||
),
|
||||
)
|
||||
.push(
|
||||
button::secondary(Some(icon::previous_icon()), "Change network")
|
||||
.width(Length::Fixed(200.0))
|
||||
.on_press(Message::BackToLauncher),
|
||||
)
|
||||
.push(Space::with_height(Length::Fixed(100.0)))
|
||||
.spacing(50)
|
||||
.align_items(Alignment::Center),
|
||||
@ -566,42 +565,24 @@ pub fn hardware_wallet_xpubs<'a>(
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn participate_xpub<'a>(
|
||||
progress: (usize, usize),
|
||||
pub fn share_xpubs<'a>(
|
||||
hws: Vec<Element<'a, Message>>,
|
||||
signer: Element<'a, Message>,
|
||||
shared: bool,
|
||||
) -> Element<'a, Message> {
|
||||
layout(
|
||||
progress,
|
||||
(0, 0),
|
||||
"Share your public keys",
|
||||
Column::new()
|
||||
.push(
|
||||
Column::new()
|
||||
.push(
|
||||
Container::new(
|
||||
text("Generate an extended public key by selecting a signing device:")
|
||||
.bold(),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.spacing(10)
|
||||
.push(Column::with_children(hws).spacing(10))
|
||||
.push(signer)
|
||||
.width(Length::Fill),
|
||||
Container::new(
|
||||
text("Generate an extended public key by selecting a signing device:").bold(),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
checkbox("I have shared my extended public key", shared)
|
||||
.on_toggle(Message::UserActionDone),
|
||||
)
|
||||
.push(if shared {
|
||||
button::primary(None, "Next")
|
||||
.width(Length::Fixed(200.0))
|
||||
.on_press(Message::Next)
|
||||
} else {
|
||||
button::primary(None, "Next").width(Length::Fixed(200.0))
|
||||
})
|
||||
.spacing(50),
|
||||
.spacing(10)
|
||||
.push(Column::with_children(hws).spacing(10))
|
||||
.push(signer)
|
||||
.width(Length::Fill),
|
||||
true,
|
||||
Some(Message::Previous),
|
||||
)
|
||||
@ -1951,11 +1932,15 @@ fn layout<'a>(
|
||||
.center_x(),
|
||||
)
|
||||
.push(Container::new(h3(title)).width(Length::FillPortion(8)))
|
||||
.push(
|
||||
Container::new(text(format!("{} | {}", progress.0, progress.1)))
|
||||
.width(Length::FillPortion(2))
|
||||
.center_x(),
|
||||
),
|
||||
.push_maybe(if progress.1 > 0 {
|
||||
Some(
|
||||
Container::new(text(format!("{} | {}", progress.0, progress.1)))
|
||||
.width(Length::FillPortion(2))
|
||||
.center_x(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}),
|
||||
)
|
||||
.push(
|
||||
Row::new()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user