installer: generate multiple xpubs in participate step
This commit is contained in:
parent
445ad733fb
commit
ca39b15edd
@ -25,7 +25,7 @@ pub enum Message {
|
||||
Network(Network),
|
||||
DefineBitcoind(DefineBitcoind),
|
||||
DefineDescriptor(DefineDescriptor),
|
||||
ImportXpub(Result<DescriptorPublicKey, Error>),
|
||||
ImportXpub(usize, Result<DescriptorPublicKey, Error>),
|
||||
ConnectedHardwareWallets(Vec<HardwareWallet>),
|
||||
WalletRegistered(Result<(Fingerprint, Option<[u8; 32]>), Error>),
|
||||
}
|
||||
|
||||
@ -746,18 +746,76 @@ async fn get_extended_pubkey(
|
||||
}))
|
||||
}
|
||||
|
||||
pub struct HardwareWalletXpubs {
|
||||
hw: HardwareWallet,
|
||||
xpubs: Vec<String>,
|
||||
processing: bool,
|
||||
error: Option<Error>,
|
||||
next_account: ChildNumber,
|
||||
}
|
||||
|
||||
impl HardwareWalletXpubs {
|
||||
fn new(hw: HardwareWallet) -> Self {
|
||||
Self {
|
||||
hw,
|
||||
xpubs: Vec::new(),
|
||||
processing: false,
|
||||
error: None,
|
||||
next_account: ChildNumber::from_hardened_idx(0).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, res: Result<DescriptorPublicKey, Error>) {
|
||||
self.processing = false;
|
||||
match res {
|
||||
Err(e) => {
|
||||
self.error = e.into();
|
||||
}
|
||||
Ok(xpub) => {
|
||||
self.error = None;
|
||||
self.next_account = self.next_account.increment().unwrap();
|
||||
self.xpubs
|
||||
.push(xpub.to_string().trim_end_matches("/<0;1>/*").to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn select(&mut self, i: usize, network: Network) -> Command<Message> {
|
||||
let device = self.hw.device.clone();
|
||||
self.processing = true;
|
||||
self.error = None;
|
||||
let fingerprint = self.hw.fingerprint;
|
||||
let next_account = self.next_account;
|
||||
Command::perform(
|
||||
async move {
|
||||
(
|
||||
i,
|
||||
get_extended_pubkey(device, fingerprint, network, next_account).await,
|
||||
)
|
||||
},
|
||||
|(i, res)| Message::ImportXpub(i, res),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn view(&self, i: usize) -> Element<Message> {
|
||||
view::hardware_wallet_xpubs(
|
||||
i,
|
||||
&self.xpubs,
|
||||
&self.hw,
|
||||
self.processing,
|
||||
self.error.as_ref(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParticipateXpub {
|
||||
network: Network,
|
||||
network_valid: bool,
|
||||
data_dir: Option<PathBuf>,
|
||||
|
||||
xpub: Option<String>,
|
||||
shared: bool,
|
||||
|
||||
processing: bool,
|
||||
chosen_hw: Option<usize>,
|
||||
hws: Vec<(HardwareWallet, bool)>,
|
||||
error: Option<Error>,
|
||||
xpubs_hw: Vec<HardwareWalletXpubs>,
|
||||
}
|
||||
|
||||
impl ParticipateXpub {
|
||||
@ -766,12 +824,8 @@ impl ParticipateXpub {
|
||||
network: Network::Bitcoin,
|
||||
network_valid: true,
|
||||
data_dir: None,
|
||||
processing: false,
|
||||
xpub: None,
|
||||
chosen_hw: None,
|
||||
hws: Vec::new(),
|
||||
xpubs_hw: Vec::new(),
|
||||
shared: false,
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -788,48 +842,26 @@ impl Step for ParticipateXpub {
|
||||
self.network_valid = !network_datadir.exists();
|
||||
}
|
||||
Message::UserActionDone(shared) => self.shared = shared,
|
||||
Message::ImportXpub(res) => {
|
||||
self.processing = false;
|
||||
match res {
|
||||
Err(e) => {
|
||||
self.error = e.into();
|
||||
self.chosen_hw = None;
|
||||
}
|
||||
Ok(xpub) => {
|
||||
self.error = None;
|
||||
self.xpub = Some(xpub.to_string().trim_end_matches("/<0;1>/*").to_string());
|
||||
for (i, (_, imported)) in self.hws.iter_mut().enumerate() {
|
||||
*imported = Some(i) == self.chosen_hw;
|
||||
}
|
||||
self.chosen_hw = None;
|
||||
}
|
||||
Message::ImportXpub(i, res) => {
|
||||
if let Some(hw) = self.xpubs_hw.get_mut(i) {
|
||||
hw.update(res);
|
||||
}
|
||||
}
|
||||
Message::Select(i) => {
|
||||
if let Some((hw, _)) = self.hws.get(i) {
|
||||
let device = hw.device.clone();
|
||||
self.chosen_hw = Some(i);
|
||||
self.processing = true;
|
||||
self.error = None;
|
||||
return Command::perform(
|
||||
get_extended_pubkey(
|
||||
device,
|
||||
hw.fingerprint,
|
||||
self.network,
|
||||
ChildNumber::from_hardened_idx(0).unwrap(),
|
||||
),
|
||||
Message::ImportXpub,
|
||||
);
|
||||
if let Some(hw) = self.xpubs_hw.get_mut(i) {
|
||||
return hw.select(i, self.network);
|
||||
}
|
||||
}
|
||||
Message::ConnectedHardwareWallets(hws) => {
|
||||
for hw in hws {
|
||||
if !self
|
||||
.hws
|
||||
.iter()
|
||||
.any(|(h, _)| h.fingerprint == hw.fingerprint)
|
||||
if let Some(xpub_hw) = self
|
||||
.xpubs_hw
|
||||
.iter_mut()
|
||||
.find(|h| h.hw.fingerprint == hw.fingerprint)
|
||||
{
|
||||
self.hws.push((hw, false));
|
||||
xpub_hw.hw = hw;
|
||||
} else {
|
||||
self.xpubs_hw.push(HardwareWalletXpubs::new(hw));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -866,12 +898,12 @@ impl Step for ParticipateXpub {
|
||||
progress,
|
||||
self.network,
|
||||
self.network_valid,
|
||||
&self.hws,
|
||||
self.processing,
|
||||
self.chosen_hw,
|
||||
self.xpub.as_ref(),
|
||||
self.xpubs_hw
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, hw)| hw.view(i))
|
||||
.collect(),
|
||||
self.shared,
|
||||
self.error.as_ref(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -409,18 +409,103 @@ pub fn import_descriptor<'a>(
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn participate_xpub<'a>(
|
||||
pub fn hardware_wallet_xpubs<'a>(
|
||||
i: usize,
|
||||
xpubs: &'a Vec<String>,
|
||||
hw: &HardwareWallet,
|
||||
processing: bool,
|
||||
error: Option<&Error>,
|
||||
) -> Element<'a, Message> {
|
||||
let mut bttn = Button::new(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Column::new()
|
||||
.push(text(format!("{}", hw.kind)).bold())
|
||||
.push(text(format!("fingerprint: {}", hw.fingerprint)).small())
|
||||
.spacing(5)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(error.map(|e| {
|
||||
iced::widget::tooltip(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::warning_icon().style(color::ALERT))
|
||||
.push(text("An error occured").style(color::ALERT)),
|
||||
e,
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::ErrorCardStyle)
|
||||
})),
|
||||
)
|
||||
.padding(10)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.width(Length::Fill);
|
||||
if !processing {
|
||||
bttn = bttn.on_press(Message::Select(i));
|
||||
}
|
||||
Container::new(
|
||||
Column::new()
|
||||
.push(bttn)
|
||||
.push_maybe(if xpubs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(separation().width(Length::Fill))
|
||||
})
|
||||
.push_maybe(if xpubs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(xpubs.iter().fold(Column::new().padding(15), |col, xpub| {
|
||||
col.push(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(
|
||||
Scrollable::new(Container::new(text(xpub).small()).padding(10))
|
||||
.horizontal_scroll(
|
||||
Properties::new().width(2).scroller_width(2),
|
||||
),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
button::border(Some(icon::clipboard_icon()), "Copy")
|
||||
.on_press(Message::Clibpboard(xpub.clone()))
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
.padding(10),
|
||||
),
|
||||
)
|
||||
}))
|
||||
})
|
||||
.push_maybe(if !xpubs.is_empty() {
|
||||
Some(
|
||||
Container::new(if !processing {
|
||||
button::border(Some(icon::plus_icon()), "New public key")
|
||||
.on_press(Message::Select(i))
|
||||
} else {
|
||||
button::border(Some(icon::plus_icon()), "New public key")
|
||||
})
|
||||
.padding(10),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn participate_xpub(
|
||||
progress: (usize, usize),
|
||||
network: bitcoin::Network,
|
||||
network_valid: bool,
|
||||
hws: &[(HardwareWallet, bool)],
|
||||
processing: bool,
|
||||
chosen_hw: Option<usize>,
|
||||
xpub: Option<&'a String>,
|
||||
hws: Vec<Element<Message>>,
|
||||
shared: bool,
|
||||
error: Option<&Error>,
|
||||
) -> Element<'a, Message> {
|
||||
) -> Element<Message> {
|
||||
let row_network = Row::new()
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
@ -442,7 +527,7 @@ pub fn participate_xpub<'a>(
|
||||
layout(
|
||||
progress,
|
||||
Column::new()
|
||||
.push(text("Share your public key").bold().size(50))
|
||||
.push(text("Share your public keys").bold().size(50))
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
@ -456,7 +541,7 @@ pub fn participate_xpub<'a>(
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(text("Select your hardware wallet:").bold())
|
||||
Container::new(text("Generate an extended public key by selecting a signing device:").bold())
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
@ -465,50 +550,11 @@ pub fn participate_xpub<'a>(
|
||||
),
|
||||
)
|
||||
.spacing(10)
|
||||
.push(
|
||||
hws.iter()
|
||||
.enumerate()
|
||||
.fold(Column::new().spacing(10), |col, (i, hw)| {
|
||||
col.push(hw_list_view(
|
||||
i,
|
||||
&hw.0,
|
||||
Some(i) == chosen_hw,
|
||||
processing,
|
||||
hw.1,
|
||||
))
|
||||
}),
|
||||
)
|
||||
.push(Column::with_children(hws).spacing(10))
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(xpub.map(|xpub| {
|
||||
Column::new()
|
||||
.spacing(5)
|
||||
.push(text("Your extended pubkey:").bold())
|
||||
.push(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(
|
||||
Scrollable::new(Container::new(text(xpub)).padding(10))
|
||||
.horizontal_scroll(
|
||||
Properties::new().width(2).scroller_width(2),
|
||||
),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
button::border(Some(icon::clipboard_icon()), "Copy")
|
||||
.on_press(Message::Clibpboard(xpub.clone()))
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
.padding(10),
|
||||
),
|
||||
)
|
||||
}))
|
||||
.push(Checkbox::new(
|
||||
"I have shared my xpub",
|
||||
"I have shared my public keys",
|
||||
shared,
|
||||
Message::UserActionDone,
|
||||
))
|
||||
@ -519,7 +565,6 @@ pub fn participate_xpub<'a>(
|
||||
} else {
|
||||
button::primary(None, "Next").width(Length::Units(200))
|
||||
})
|
||||
.push_maybe(error.map(|e| card::error("Hardware error", e.to_string())))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(100)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user