From 4bb4269975e0469205c96751bcbf24311177d53d Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Mon, 23 Jun 2025 12:38:03 +0200 Subject: [PATCH 1/5] gui: add import descriptor from file feature in liana-connect flow --- liana-gui/src/installer/message.rs | 2 + liana-gui/src/installer/step/backend.rs | 59 +++++++++++++++++++++++-- liana-gui/src/installer/view/mod.rs | 6 +++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/liana-gui/src/installer/message.rs b/liana-gui/src/installer/message.rs index 693da779..c5453259 100644 --- a/liana-gui/src/installer/message.rs +++ b/liana-gui/src/installer/message.rs @@ -117,6 +117,8 @@ pub enum ImportRemoteWallet { InvitationFetched(Result), AcceptInvitation, InvitationAccepted(Result), + ImportDescriptorFromFile, + ImportExport(ImportExportMessage), } #[derive(Debug, Clone)] diff --git a/liana-gui/src/installer/step/backend.rs b/liana-gui/src/installer/step/backend.rs index c5379953..78153328 100644 --- a/liana-gui/src/installer/step/backend.rs +++ b/liana-gui/src/installer/step/backend.rs @@ -1,13 +1,15 @@ use std::str::FromStr; -use iced::Task; +use iced::{Subscription, Task}; use liana::{descriptors::LianaDescriptor, miniscript::bitcoin::Network}; use liana_ui::{component::form, widget::Element}; use crate::{ + app::state::export::ExportModal, daemon::DaemonError, dir::NetworkDirectory, + export::{ImportExportMessage, ImportExportType, Progress}, hw::HardwareWallets, installer::{ context::{self, Context, RemoteBackend}, @@ -448,6 +450,7 @@ pub struct ImportRemoteWallet { error: Option, backend: context::RemoteBackend, wallets: Vec, + modal: Option, // wallet alias is stored here to be applied to context // and be modified in a following step wallet_alias: Option, @@ -464,6 +467,7 @@ impl ImportRemoteWallet { error: None, backend: context::RemoteBackend::Undefined, wallets: Vec::new(), + modal: None, wallet_alias: None, } } @@ -502,6 +506,37 @@ impl Step for ImportRemoteWallet { // Verification of the values is happening when the user click on Next button. fn update(&mut self, _hws: &mut HardwareWallets, message: Message) -> Task { match message { + Message::ImportRemoteWallet(message::ImportRemoteWallet::ImportDescriptorFromFile) => { + let modal = ExportModal::new(None, ImportExportType::ImportDescriptor); + let launch = modal.launch(false); + self.modal = Some(modal); + return launch; + } + Message::ImportExport(ImportExportMessage::Path(p)) => { + if let Some(modal) = self.modal.as_mut() { + return modal.update(ImportExportMessage::Path(p)); + } + } + Message::ImportExport(ImportExportMessage::Close) => self.modal = None, + Message::ImportRemoteWallet(message::ImportRemoteWallet::ImportExport(m)) => match m { + ImportExportMessage::Close => self.modal = None, + ImportExportMessage::Progress(Progress::Descriptor(d)) => { + self.modal = None; + return Task::batch([ + Task::done(Message::ImportRemoteWallet( + message::ImportRemoteWallet::ImportDescriptor(d.to_string()), + )), + Task::done(Message::ImportRemoteWallet( + message::ImportRemoteWallet::ConfirmDescriptor, + )), + ]); + } + m => { + if let Some(modal) = self.modal.as_mut() { + return modal.update(m); + } + } + }, Message::ImportRemoteWallet(message::ImportRemoteWallet::ImportDescriptor(desc)) => { self.imported_descriptor.value = desc; if !self.imported_descriptor.value.is_empty() { @@ -643,6 +678,19 @@ impl Step for ImportRemoteWallet { Task::none() } + fn subscription(&self, _hws: &HardwareWallets) -> iced::Subscription { + if let Some(modal) = &self.modal { + if let Some(sub) = modal.subscription() { + return sub.map(|m| { + Message::ImportRemoteWallet(message::ImportRemoteWallet::ImportExport( + ImportExportMessage::Progress(m), + )) + }); + } + } + Subscription::none() + } + fn apply(&mut self, ctx: &mut Context) -> bool { // Set to true in order to force the registration process to be shown to user. ctx.hw_is_used = true; @@ -662,7 +710,7 @@ impl Step for ImportRemoteWallet { progress: (usize, usize), email: Option<&'a str>, ) -> Element { - view::import_wallet_or_descriptor( + let content = view::import_wallet_or_descriptor( progress, email, &self.invitation_token, @@ -675,7 +723,12 @@ impl Step for ImportRemoteWallet { .iter() .map(|w| (&w.name, w.metadata.wallet_alias.as_ref())) .collect(), - ) + ); + if let Some(modal) = &self.modal { + modal.view(content) + } else { + content + } } } diff --git a/liana-gui/src/installer/view/mod.rs b/liana-gui/src/installer/view/mod.rs index c325982a..86017ca3 100644 --- a/liana-gui/src/installer/view/mod.rs +++ b/liana-gui/src/installer/view/mod.rs @@ -233,6 +233,12 @@ pub fn import_wallet_or_descriptor<'a>( .size(text::P1_SIZE) .padding(10), ) + .push(text("or").bold()) + .push(button::primary(None, "Import descriptor").on_press( + Message::ImportRemoteWallet( + message::ImportRemoteWallet::ImportDescriptorFromFile, + ), + )) .spacing(10), ) .push( From 53839e92744b24e1365c3b57108b350c729b17b5 Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Mon, 23 Jun 2025 12:44:55 +0200 Subject: [PATCH 2/5] gui: add a spacer below the main column at Add wallet step in liana-connect flow --- liana-gui/src/installer/view/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/liana-gui/src/installer/view/mod.rs b/liana-gui/src/installer/view/mod.rs index 86017ca3..b17a596f 100644 --- a/liana-gui/src/installer/view/mod.rs +++ b/liana-gui/src/installer/view/mod.rs @@ -274,7 +274,8 @@ pub fn import_wallet_or_descriptor<'a>( .push_maybe(error.map(|e| card::error("Something wrong happened", e.to_string()))) .push(card_wallets) .push(card::simple(col_invitation_token).padding(0)) - .push(card::simple(col_descriptor).padding(0)), + .push(card::simple(col_descriptor).padding(0)) + .push(Space::with_height(10)), true, Some(Message::Previous), ) From d66b596cf930597254b1e48426c9488fd77d210d Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Mon, 23 Jun 2025 13:22:26 +0200 Subject: [PATCH 3/5] import: allow to import a descriptor from a backup in export::import_descriptor() --- liana-gui/src/export.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/liana-gui/src/export.rs b/liana-gui/src/export.rs index 88a910f9..74897a12 100644 --- a/liana-gui/src/export.rs +++ b/liana-gui/src/export.rs @@ -637,7 +637,19 @@ pub async fn import_descriptor( file.read_to_string(&mut descr_str)?; let descr_str = descr_str.trim(); - let descriptor = LianaDescriptor::from_str(descr_str).map_err(|_| Error::ParseDescriptor)?; + let descriptor = if let Ok(d) = LianaDescriptor::from_str(descr_str) { + Some(d) + } else { + let backup: Result = serde_json::from_str(descr_str); + backup.ok().and_then(|b| { + if b.accounts.len() == 1 { + LianaDescriptor::from_str(&b.accounts[0].descriptor).ok() + } else { + None + } + }) + }; + let descriptor = descriptor.ok_or(Error::ParseDescriptor)?; send_progress!(sender, Progress(100.0)); send_progress!(sender, Descriptor(descriptor)); From 54c83615b070a982ec99f3c58278ecabba8a264e Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Tue, 24 Jun 2025 12:22:50 +0200 Subject: [PATCH 4/5] export: add test cases for import_descriptor() --- liana-gui/src/export.rs | 36 ++++++++++ .../liana-backup-2025-06-23T13-23-54.json | 69 +++++++++++++++++++ liana-gui/test_assets/liana-jz5sm0xn.txt | 1 + 3 files changed, 106 insertions(+) create mode 100644 liana-gui/test_assets/liana-backup-2025-06-23T13-23-54.json create mode 100644 liana-gui/test_assets/liana-jz5sm0xn.txt diff --git a/liana-gui/src/export.rs b/liana-gui/src/export.rs index 74897a12..c4aee741 100644 --- a/liana-gui/src/export.rs +++ b/liana-gui/src/export.rs @@ -1286,8 +1286,44 @@ pub async fn app_backup_export( #[cfg(test)] mod tests { + use std::env; + use super::*; + #[tokio::test] + async fn test_import_descriptor_from_file() { + let (sender, mut receiver) = unbounded_channel(); + let path = env::current_dir() + .unwrap() + .join("test_assets") + .join("liana-jz5sm0xn.txt"); + println!("path: {}", path.display()); + import_descriptor(&sender, path).await.unwrap(); + let _msg = receiver.try_recv().unwrap(); + assert!(matches!(Progress::Progress(100.0), _msg)); + let raw_descriptor = "wsh(or_d(pk([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<0;1>/*),and_v(v:pkh([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<2;3>/*),older(52596))))#jz5sm0xn"; + let descr = LianaDescriptor::from_str(raw_descriptor).unwrap(); + let _msg = receiver.try_recv().unwrap(); + assert!(matches!(Progress::Descriptor(descr), _msg)); + } + + #[tokio::test] + async fn test_import_descriptor_from_backup_file() { + let (sender, mut receiver) = unbounded_channel(); + let path = env::current_dir() + .unwrap() + .join("test_assets") + .join("liana-backup-2025-06-23T13-23-54.json"); + println!("path: {}", path.display()); + import_descriptor(&sender, path).await.unwrap(); + let _msg = receiver.try_recv().unwrap(); + assert!(matches!(Progress::Progress(100.0), _msg)); + let raw_descriptor = "wsh(or_d(pk([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<0;1>/*),and_v(v:pkh([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<2;3>/*),older(52596))))#jz5sm0xn"; + let descr = LianaDescriptor::from_str(raw_descriptor).unwrap(); + let _msg = receiver.try_recv().unwrap(); + assert!(matches!(Progress::Descriptor(descr), _msg)); + } + #[test] fn test_parse_coldcard_xpub() { let raw = r#" diff --git a/liana-gui/test_assets/liana-backup-2025-06-23T13-23-54.json b/liana-gui/test_assets/liana-backup-2025-06-23T13-23-54.json new file mode 100644 index 00000000..e90e4c21 --- /dev/null +++ b/liana-gui/test_assets/liana-backup-2025-06-23T13-23-54.json @@ -0,0 +1,69 @@ +{ + "name": "Liana-jz5sm0xn", + "alias": "My Liana Regtest wallet", + "accounts": [ + { + "name": "Liana-jz5sm0xn", + "descriptor": "wsh(or_d(pk([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<0;1>/*),and_v(v:pkh([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<2;3>/*),older(52596))))#jz5sm0xn", + "receive_index": 1, + "change_index": 2, + "timestamp": 1748013169, + "keys": { + "8a550171": { + "key": "8a550171", + "alias": "a" + } + }, + "labels": [], + "transactions": [ + "020000000001042e410675d4d1b009e257ca11345502e5c1f00709590db95e2ac9fe1a11044d4d0000000000fdffffff2503d8712de399f674baab16b844a54870bd2142650c609edb3d1cd60bcbf77b0000000000fdffffff4e093e78a81157ebcb11780bfe010fc0752231015d0c2a8114630ac7c6c159c50000000000fdffffffb5e6c596c3659f7af56ebaa9e8ae618c5ac7f338033172e9475f1933f04e348a0000000000fdffffff02d263060000000000225120e49d1997805dbb7290369fb95f94451b0ca3e738119b9c6b6e5a70a33384913100e1f50500000000220020fd22758b64471a67371158c546ab5918732659085eb21c9af6591cb811e56c660247304402203c379630bf2b827abf013ef8ed6a37a18dfc98fef28199a208bc19bc68b441f40220248456a96302579d0739ce8dbc63550835961a811198859aaa250c8611e46466012103df49913c09de6d937101041d2e413a09e5991ba3ef31534d88054b319d2d74510247304402202a8e2ffcaa86fef2fc40caf21d0d59b4801ad553701b4466c2872e5ac3ffb23f02200f10f5493543f8c4fe37627a7ad6bfa93b01a22873983656003ababe9d6c4ca60121031337b42040d5f2700ba46ae7cf70dc172c2b4f695313a8ed0fe62ea843278e6c0247304402204ee9ae50ff1bbde05832236fdea9f3709a4d9fa87014cf86a63e9333641c737c02206394e7124539adf560f76ddbb87ec4614d9a9e70ac995c88d1b2b6e614ab4e430121034547cd6c5fe44edbc9af9193df5a9a7fc0055c3f47b968e92ae30d6630a6cd08024730440220135820533d687ed853e92f7e52ef73de755f13ace2db60f5f85a07681bd62e2a022015290d93eb8b0d53f17c2851f2fb53ba2859ee15aacb0a188041f46f249101100121029f4c9445023494227a966609268d0db59bf82eb21433188470bbdcdd63f5508caf5d0000" + ], + "psbts": [ + "cHNidP8BAF4CAAAAAcb4e2jUBqxxBTgMZFk6JUCes6Q3cvgpYJ2uJDUOBbudAQAAAAD9////AX3g9QUAAAAAIgAgCkktj1GAtl5qSGMFiltgrcw2ozjyaWF4XBktdHaUItuyXQAAAAEA/bICAgAAAAABBC5BBnXU0bAJ4lfKETRVAuXB8AcJWQ25XirJ/hoRBE1NAAAAAAD9////JQPYcS3jmfZ0uqsWuESlSHC9IUJlDGCe2z0c1gvL93sAAAAAAP3///9OCT54qBFX68sReAv+AQ/AdSIxAV0MKoEUYwrHxsFZxQAAAAAA/f///7XmxZbDZZ969W66qeiuYYxax/M4AzFy6UdfGTPwTjSKAAAAAAD9////AtJjBgAAAAAAIlEg5J0Zl4Bdu3KQNp+5X5RFGwyj5zgRm5xrblpwozOEkTEA4fUFAAAAACIAIP0idYtkRxpnNxFYxUarWRhzJlkIXrIcmvZZHLgR5WxmAkcwRAIgPDeWML8rgnq/AT747Wo3oY38mP7ygZmiCLwZvGi0QfQCICSEVqljAledBznOjbxjVQg1lhqBEZiFmqolDIYR5GRmASED30mRPAnebZNxAQQdLkE6CeWZG6PvMVNNiAVLMZ0tdFECRzBEAiAqji/8qob+8vxAyvIdDVm0gBrVU3AbRGbChy5aw/+yPwIgDxD1STVD+MT+N2J6eta/qTsBoihzmDZWADq6vp1sTKYBIQMTN7QgQNXycAukaufPcNwXLCtPaVMTqO0P5i6oQyeObAJHMEQCIE7prlD/G73gWDIjb96p83CaTZ+ocBTPhqY+kzNkHHN8AiBjlOcSRTmt9WD3bdu4fsRhTZqecKyZXIjRsrbmFKtOQwEhA0VHzWxf5E7bya+Rk99amn/ABVw/R7lo6SrjDWYwps0IAkcwRAIgE1ggUz1ofthT6S9+Uu9z3nVfE6zi22D1+FoHaBvWLioCIBUpDZPriw1T8XwoUfL7U7ooWe4VqssKGIBB9G8kkQEQASECn0yURQI0lCJ6lmYJJo0NtZv4LrIUMxiEcLvc3WP1UIyvXQAAAQErAOH1BQAAAAAiACD9InWLZEcaZzcRWMVGq1kYcyZZCF6yHJr2WRy4EeVsZiICA2vrvUCtFrmnsdsUyMDb2kT4uowEfiQ5D/1l+cWZ1vDWRzBEAiAaM9aLqBTG5C4tK9p9c28Jz439Emr7XPoxUYyJllYLMAIgFA6/yH55PAeZedfY2h6at7dB/k/wPf8M3+y0IEcQgKIBIgIDio+/H1qygPy0Phj9olT5VctStZGyB6qVDiVdlfiIWTpHMEQCIGUetlDH7qqci2rSxbHnvoqcs1pEJHgaLbRAnMPjffv1AiBHhT5DcOQhVhn0vtXO8Ij5ii3BafsK9VX2SN2l9H1/9QEBBUQhA2vrvUCtFrmnsdsUyMDb2kT4uowEfiQ5D/1l+cWZ1vDWrHNkdqkUXG6thIRwLnqHwJdmKl7XWxiKxDyIrQN0zQCyaCIGA2vrvUCtFrmnsdsUyMDb2kT4uowEfiQ5D/1l+cWZ1vDWHIpVAXEwAACAAQAAgAAAAIACAACAAAAAAAEAAAAiBgOKj78fWrKA/LQ+GP2iVPlVy1K1kbIHqpUOJV2V+IhZOhyKVQFxMAAAgAEAAIAAAACAAgAAgAIAAAABAAAAACICA1BIFqUUMoNtx4WVqTmwuL2iEpyL6ZLAflqiZpCHcVveHIpVAXEwAACAAQAAgAAAAIACAACAAwAAAAIAAAAiAgO+QA+pMN6tM8/CHiT8Rt32H2jEOY2nZpV2rV/QYKGJEhyKVQFxMAAAgAEAAIAAAACAAgAAgAEAAAACAAAAAA==" + ], + "coins": { + "9dbb050e3524ae9d6029f87237a4b39e40253a59640c380571ac06d4687bf8c6:1": { + "amount": 100000000, + "outpoint": "9dbb050e3524ae9d6029f87237a4b39e40253a59640c380571ac06d4687bf8c6:1", + "address": "bcrt1ql538tzmygudxwdc3trz5d26erpejvkggt6epexhktywtsy09d3nqzqf3d4", + "block_height": 23984, + "account": 0, + "derivation_index": 1, + "is_coinbase": null, + "is_from_self": false + } + }, + "chain_tip": { + "block_height": 24332, + "block_hash": null + }, + "proprietary": { + "config": { + "debug": null, + "log_level": null, + "start_internal_bitcoind": false + }, + "liana_version": "11.0", + "settings": { + "alias": "My Liana Regtest wallet", + "descriptor_checksum": "jz5sm0xn", + "hardware_wallets": [], + "keys": [ + { + "master_fingerprint": "8a550171", + "name": "a", + "provider_key": null + } + ], + "name": "Liana-jz5sm0xn", + "pinned_at": 1748013169, + "remote_backend_auth": null, + "start_internal_bitcoind": false + } + } + } + ], + "network": "regtest", + "date": 1750677837, + "version": 0 +} \ No newline at end of file diff --git a/liana-gui/test_assets/liana-jz5sm0xn.txt b/liana-gui/test_assets/liana-jz5sm0xn.txt new file mode 100644 index 00000000..2838db61 --- /dev/null +++ b/liana-gui/test_assets/liana-jz5sm0xn.txt @@ -0,0 +1 @@ +wsh(or_d(pk([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<0;1>/*),and_v(v:pkh([8a550171/48'/1'/0'/2']tpubDFnCs5ZaCqopaNhgLCiXAwbkaBdcnuMt1VFoPsRpUrpidyvzG67MYjkfxw6HnTBhHqeU3xw2ioNBVcWY3jXwGhSyppEQvtn38GsL7RH1eef/<2;3>/*),older(52596))))#jz5sm0xn \ No newline at end of file From 31798b7e4317125e671e2d52e28e9ddc16815bf0 Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Tue, 24 Jun 2025 12:35:12 +0200 Subject: [PATCH 5/5] export: allow to import a backup from a simple descriptor --- liana-gui/src/backup.rs | 26 +++++++++++++++-- liana-gui/src/export.rs | 28 ++++++++++++++++--- .../src/installer/step/descriptor/mod.rs | 24 ++++++++++++---- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/liana-gui/src/backup.rs b/liana-gui/src/backup.rs index cbfcb901..bb3b09d8 100644 --- a/liana-gui/src/backup.rs +++ b/liana-gui/src/backup.rs @@ -1,7 +1,10 @@ use chrono::{Duration, Utc}; -use liana::miniscript::{ - self, - bitcoin::{bip32::Fingerprint, Network, Txid}, +use liana::{ + descriptors::LianaDescriptor, + miniscript::{ + self, + bitcoin::{bip32::Fingerprint, Network, Txid}, + }, }; use lianad::{ bip329, @@ -111,6 +114,23 @@ impl Debug for Backup { } impl Backup { + /// Create a Backup from a descriptor + /// + /// # Arguments + /// * `descriptor` - the descriptor + /// * `network` - the network + pub fn from_descriptor(descriptor: LianaDescriptor, network: Network) -> Self { + let account = Account::new(descriptor.to_string()); + Backup { + name: None, + alias: None, + accounts: vec![account], + network, + date: None, + proprietary: Default::default(), + version: default_version(), + } + } /// Create a Backup from the Installer context /// /// # Arguments diff --git a/liana-gui/src/export.rs b/liana-gui/src/export.rs index c4aee741..fd4e74ee 100644 --- a/liana-gui/src/export.rs +++ b/liana-gui/src/export.rs @@ -246,7 +246,7 @@ pub enum Progress { WalletFromBackup( ( LianaDescriptor, - Network, + Option, HashMap, Backup, ), @@ -1045,13 +1045,33 @@ pub async fn wallet_from_backup( let backup: Result = serde_json::from_str(&backup_str); let backup = match backup { - Ok(psbt) => psbt, + Ok(b) => b, Err(e) => { - return Err(Error::BackupImport(format!("{:?}", e))); + // try to import as bare descriptor + let descr = LianaDescriptor::from_str(&backup_str); + match descr { + Ok(descr) => { + let network = if descr.all_xpubs_net_is(Network::Bitcoin) { + Network::Bitcoin + } else { + Network::Signet + }; + Backup::from_descriptor(descr, network) + } + Err(e2) => { + return Err(Error::BackupImport(format!( + "A backup or descriptor file is expected: {e}, {e2}" + ))); + } + } } }; - let network = backup.network; + let network = if backup.network == Network::Bitcoin { + Some(backup.network) + } else { + None + }; let account = match backup.accounts.len() { 0 => { diff --git a/liana-gui/src/installer/step/descriptor/mod.rs b/liana-gui/src/installer/step/descriptor/mod.rs index 223576a1..cea59a7b 100644 --- a/liana-gui/src/installer/step/descriptor/mod.rs +++ b/liana-gui/src/installer/step/descriptor/mod.rs @@ -120,12 +120,26 @@ impl Step for ImportDescriptor { } Message::ImportExport(ImportExportMessage::Progress(Progress::WalletFromBackup(r))) => { let (descriptor, network, aliases, backup) = r; - if self.network == network { - self.imported_backup = Some(backup); - self.imported_descriptor.value = descriptor.to_string(); - self.imported_aliases = Some(aliases); + if let Some(n) = network { + if self.network == n { + self.imported_backup = Some(backup); + self.imported_descriptor.value = descriptor.to_string(); + self.imported_aliases = Some(aliases); + } else { + self.error = + Some("Backup network do not match the selected network!".into()); + } } else { - self.error = Some("Backup network do not match the selected network!".into()); + // The backup have been inferred from a bare descriptor, we check whether + // the descriptor match any test network + if self.network != Network::Bitcoin { + self.imported_backup = Some(backup); + self.imported_descriptor.value = descriptor.to_string(); + self.imported_aliases = Some(aliases); + } else { + self.error = + Some("Backup network do not match the selected network!".into()); + } } } Message::ImportExport(m) => {