installer: add existing wallet from backup
This commit is contained in:
parent
aa53c3e44e
commit
091557a8df
@ -191,11 +191,11 @@ pub enum ImportExportType {
|
||||
Option<SyncSender<bool>>, /*overwrite_labels*/
|
||||
Option<SyncSender<bool>>, /*overwrite_aliases*/
|
||||
),
|
||||
WalletFromBackup,
|
||||
Descriptor(LianaDescriptor),
|
||||
ExportLabels,
|
||||
ImportPsbt,
|
||||
ImportDescriptor,
|
||||
WalletFromBackup,
|
||||
}
|
||||
|
||||
impl ImportExportType {
|
||||
@ -276,7 +276,7 @@ pub enum Progress {
|
||||
(
|
||||
LianaDescriptor,
|
||||
Network,
|
||||
HashMap<Fingerprint, String>,
|
||||
HashMap<Fingerprint, settings::KeySetting>,
|
||||
Backup,
|
||||
),
|
||||
),
|
||||
@ -315,7 +315,6 @@ impl Export {
|
||||
path: PathBuf,
|
||||
) {
|
||||
match export_type {
|
||||
ImportExportType::WalletFromBackup => wallet_from_backup(sender, path).await,
|
||||
ImportExportType::Transactions => export_transactions(sender, daemon, path).await,
|
||||
ImportExportType::ExportPsbt(str) => export_string(sender, path, str),
|
||||
ImportExportType::Descriptor(descriptor) => export_descriptor(sender, path, descriptor),
|
||||
@ -324,6 +323,7 @@ impl Export {
|
||||
ImportExportType::ImportDescriptor => import_descriptor(sender, path),
|
||||
ImportExportType::ExportBackup(str) => export_string(sender, path, str),
|
||||
ImportExportType::ImportBackup(..) => import_backup(sender, path, daemon).await,
|
||||
ImportExportType::WalletFromBackup => wallet_from_backup(sender, path).await,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1092,10 +1092,16 @@ pub async fn wallet_from_backup(sender: Sender<Progress>, path: PathBuf) {
|
||||
}
|
||||
};
|
||||
|
||||
let mut aliases: HashMap<Fingerprint, String> = HashMap::new();
|
||||
let mut aliases: HashMap<Fingerprint, settings::KeySetting> = HashMap::new();
|
||||
for (k, v) in &account.keys {
|
||||
if let Some(alias) = &v.alias {
|
||||
aliases.insert(*k, alias.clone());
|
||||
if let Some(ks) = KeySetting::from_backup(
|
||||
v.alias.clone().unwrap_or("".into()),
|
||||
*k,
|
||||
v.role,
|
||||
v.key_type,
|
||||
v.metadata.clone(),
|
||||
) {
|
||||
aliases.insert(*k, ks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,13 +2,15 @@ use liana::miniscript::{
|
||||
bitcoin::{bip32::Fingerprint, Network},
|
||||
DescriptorPublicKey,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use super::{context, Error};
|
||||
use crate::{
|
||||
app::settings::ProviderKey,
|
||||
app::view::Close,
|
||||
backup,
|
||||
app::{
|
||||
settings::{self, ProviderKey},
|
||||
view::Close,
|
||||
},
|
||||
backup::{self, Backup},
|
||||
download::{DownloadError, Progress},
|
||||
export::ImportExportMessage,
|
||||
hw::HardwareWalletMessage,
|
||||
@ -55,6 +57,8 @@ pub enum Message {
|
||||
BackupWallet,
|
||||
ExportWallet(Result<String, backup::Error>),
|
||||
ImportExport(ImportExportMessage),
|
||||
ImportBackup,
|
||||
WalletFromBackup((HashMap<Fingerprint, settings::KeySetting>, Backup)),
|
||||
}
|
||||
|
||||
impl Close for Message {
|
||||
|
||||
@ -292,6 +292,11 @@ impl Installer {
|
||||
.expect("There is always a step")
|
||||
.update(&mut self.hws, Message::Installed(Err(e)))
|
||||
}
|
||||
Message::WalletFromBackup((ks, backup)) => {
|
||||
self.context.keys = ks;
|
||||
self.context.backup = Some(backup);
|
||||
Task::none()
|
||||
}
|
||||
_ => self
|
||||
.steps
|
||||
.get_mut(self.current)
|
||||
|
||||
@ -18,7 +18,7 @@ use async_hwi::DeviceKind;
|
||||
use crate::{
|
||||
app::{settings::KeySetting, state::export::ExportModal, wallet::wallet_name},
|
||||
backup::{self, Backup},
|
||||
export::{ImportExportMessage, ImportExportType},
|
||||
export::{ImportExportMessage, ImportExportType, Progress},
|
||||
hw::{HardwareWallet, HardwareWallets},
|
||||
installer::{
|
||||
message::{self, Message},
|
||||
@ -32,6 +32,8 @@ pub struct ImportDescriptor {
|
||||
imported_descriptor: form::Value<String>,
|
||||
wrong_network: bool,
|
||||
error: Option<String>,
|
||||
modal: Option<ExportModal>,
|
||||
imported_backup: bool,
|
||||
}
|
||||
|
||||
impl ImportDescriptor {
|
||||
@ -41,6 +43,8 @@ impl ImportDescriptor {
|
||||
imported_descriptor: form::Value::default(),
|
||||
wrong_network: false,
|
||||
error: None,
|
||||
modal: None,
|
||||
imported_backup: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,14 +81,55 @@ impl Step for ImportDescriptor {
|
||||
fn skip(&self, ctx: &Context) -> bool {
|
||||
ctx.remote_backend.is_some()
|
||||
}
|
||||
// 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 subscription(&self, _hws: &HardwareWallets) -> Subscription<Message> {
|
||||
if let Some(modal) = &self.modal {
|
||||
if let Some(sub) = modal.subscription() {
|
||||
sub.map(|m| Message::ImportExport(ImportExportMessage::Progress(m)))
|
||||
} else {
|
||||
Subscription::none()
|
||||
}
|
||||
} else {
|
||||
Subscription::none()
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, _hws: &mut HardwareWallets, message: Message) -> Task<Message> {
|
||||
if let Message::DefineDescriptor(message::DefineDescriptor::ImportDescriptor(desc)) =
|
||||
message
|
||||
{
|
||||
self.imported_descriptor.value = desc;
|
||||
self.check_descriptor(self.network);
|
||||
match message {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::ImportDescriptor(desc)) => {
|
||||
self.imported_descriptor.value = desc;
|
||||
self.check_descriptor(self.network);
|
||||
}
|
||||
Message::ImportExport(ImportExportMessage::Close) => {
|
||||
self.modal = None;
|
||||
}
|
||||
Message::ImportBackup => {
|
||||
if !self.imported_backup {
|
||||
let modal = ExportModal::new(None, ImportExportType::WalletFromBackup);
|
||||
let launch = modal.launch(false);
|
||||
self.modal = Some(modal);
|
||||
return launch;
|
||||
}
|
||||
}
|
||||
Message::ImportExport(ImportExportMessage::Progress(Progress::WalletFromBackup(r))) => {
|
||||
let (descriptor, network, aliases, backup) = r;
|
||||
if self.network == network {
|
||||
self.imported_backup = true;
|
||||
self.imported_descriptor.value = descriptor.to_string();
|
||||
return Task::perform(async move { (aliases, backup) }, |(a, b)| {
|
||||
Message::WalletFromBackup((a, b))
|
||||
});
|
||||
} else {
|
||||
self.error = Some("Backup network do not match the selected network!".into());
|
||||
}
|
||||
}
|
||||
Message::ImportExport(m) => {
|
||||
if let Some(modal) = self.modal.as_mut() {
|
||||
let task: Task<Message> = modal.update(m);
|
||||
return task;
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
@ -108,13 +153,19 @@ impl Step for ImportDescriptor {
|
||||
progress: (usize, usize),
|
||||
email: Option<&'a str>,
|
||||
) -> Element<Message> {
|
||||
view::import_descriptor(
|
||||
let content = view::import_descriptor(
|
||||
progress,
|
||||
email,
|
||||
&self.imported_descriptor,
|
||||
self.imported_backup,
|
||||
self.wrong_network,
|
||||
self.error.as_ref(),
|
||||
)
|
||||
);
|
||||
if let Some(modal) = &self.modal {
|
||||
modal.view(content)
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -264,11 +264,15 @@ pub fn import_descriptor<'a>(
|
||||
progress: (usize, usize),
|
||||
email: Option<&'a str>,
|
||||
imported_descriptor: &form::Value<String>,
|
||||
imported_backup: bool,
|
||||
wrong_network: bool,
|
||||
error: Option<&String>,
|
||||
) -> Element<'a, Message> {
|
||||
let valid = !imported_descriptor.value.is_empty() && imported_descriptor.valid;
|
||||
|
||||
let col_descriptor = Column::new()
|
||||
.push(text("Descriptor:").bold())
|
||||
.push(Space::with_height(10))
|
||||
.push(
|
||||
form::Form::new_trimmed("Descriptor", imported_descriptor, |msg| {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::ImportDescriptor(msg))
|
||||
@ -280,21 +284,65 @@ pub fn import_descriptor<'a>(
|
||||
})
|
||||
.size(text::P1_SIZE)
|
||||
.padding(10),
|
||||
);
|
||||
|
||||
let descriptor = if imported_backup {
|
||||
None
|
||||
} else {
|
||||
Some(col_descriptor)
|
||||
};
|
||||
|
||||
let or = if !valid && !imported_backup {
|
||||
Some(
|
||||
Row::new()
|
||||
.push(text("or").bold())
|
||||
.push(Space::with_width(Length::Fill)),
|
||||
)
|
||||
.spacing(10);
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let import_backup = if !valid && !imported_backup {
|
||||
Some(
|
||||
Row::new()
|
||||
.push(button::secondary(None, "Import backup").on_press(Message::ImportBackup))
|
||||
.push(Space::with_width(Length::Fill)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let backup_imported = if imported_backup {
|
||||
Some(
|
||||
Row::new()
|
||||
.push(text("Backup successfuly imported!").bold())
|
||||
.push(Space::with_width(Length::Fill)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
layout(
|
||||
progress,
|
||||
email,
|
||||
"Import the wallet",
|
||||
Column::new()
|
||||
.push(Column::new().spacing(20).push(col_descriptor).push(text(
|
||||
"If you are using a Bitcoin Core node, \
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.push_maybe(descriptor)
|
||||
.push_maybe(or)
|
||||
.push_maybe(import_backup)
|
||||
.push_maybe(backup_imported)
|
||||
.push(text(
|
||||
"If you are using a Bitcoin Core node, \
|
||||
you will need to perform a rescan of \
|
||||
the blockchain after creating the wallet \
|
||||
in order to see your coins and past \
|
||||
transactions. This can be done in \
|
||||
Settings > Node.",
|
||||
)))
|
||||
)),
|
||||
)
|
||||
.push(
|
||||
if imported_descriptor.value.is_empty() || !imported_descriptor.valid {
|
||||
button::secondary(None, "Next").width(Length::Fixed(200.0))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user