export: add import xpub feature

This commit is contained in:
pythcoiner 2025-04-07 09:55:27 +02:00
parent d7e388707b
commit 98bacb9f4c
No known key found for this signature in database
GPG Key ID: C1048AEEDF303B88
2 changed files with 53 additions and 2 deletions

View File

@ -44,6 +44,7 @@ impl ExportModal {
ImportExportType::Transactions => "Export Transactions",
ImportExportType::ExportPsbt(_) => "Export PSBT",
ImportExportType::ExportXpub(_) => "Export Xpub",
ImportExportType::ImportXpub(_) => "Import Xpub",
ImportExportType::ExportBackup(_) => "Export Backup",
ImportExportType::Descriptor(_) => "Export Descriptor",
ImportExportType::ExportProcessBackup(..) | ImportExportType::ExportLabels => {
@ -63,7 +64,7 @@ impl ExportModal {
format!("liana-txs-{date}.csv")
}
ImportExportType::ExportPsbt(_) => "psbt.psbt".into(),
ImportExportType::ExportXpub(_) => "liana.pub".into(),
ImportExportType::ExportXpub(_) | ImportExportType::ImportXpub(_) => "liana.pub".into(),
ImportExportType::Descriptor(descriptor) => {
let checksum = descriptor
.to_string()
@ -129,6 +130,14 @@ impl ExportModal {
}
// TODO: forward PSBT
}
Progress::Xpub(xpub_str) => {
if matches!(self.import_export_type, ImportExportType::ExportXpub(_)) {
self.state = ImportExportState::Ended;
}
return Task::perform(async {}, move |_| {
ImportExportMessage::Xpub(xpub_str.clone()).into()
});
}
Progress::Descriptor(_) => {
if self.import_export_type == ImportExportType::ImportDescriptor {
self.state = ImportExportState::Ended;
@ -216,6 +225,7 @@ impl ExportModal {
}
}
ImportExportMessage::UpdateAliases(_) => { /* unexpected */ }
ImportExportMessage::Xpub(_) => { /* unexpected */ }
}
Task::none()
}

View File

@ -15,7 +15,10 @@ use async_hwi::bitbox::api::btc::Fingerprint;
use chrono::{DateTime, Duration, Utc};
use liana::{
descriptors::LianaDescriptor,
miniscript::bitcoin::{Amount, Network, Psbt, Txid},
miniscript::{
bitcoin::{Amount, Network, Psbt, Txid},
DescriptorPublicKey,
},
};
use lianad::{
bip329::{error::ExportError, Labels},
@ -80,6 +83,7 @@ pub enum ImportExportMessage {
Overwrite,
Ignore,
UpdateAliases(HashMap<Fingerprint, settings::KeySetting>),
Xpub(String),
}
impl From<ImportExportMessage> for view::Message {
@ -117,6 +121,8 @@ pub enum Error {
Bip329Export(String),
BackupImport(String),
Backup(backup::Error),
ParseXpub,
XpubNetwork,
}
impl Display for Error {
@ -136,6 +142,8 @@ impl Display for Error {
Error::Bip329Export(e) => write!(f, "Bip329Export: {e}"),
Error::BackupImport(e) => write!(f, "BackupImport: {e}"),
Error::Backup(e) => write!(f, "Backup: {e}"),
Error::ParseXpub => write!(f, "Fail to parse Xpub from file"),
Error::XpubNetwork => write!(f, "Xpub is for another network"),
}
}
}
@ -155,6 +163,7 @@ pub enum ImportExportType {
Descriptor(LianaDescriptor),
ExportLabels,
ImportPsbt,
ImportXpub(Network),
ImportDescriptor,
}
@ -170,6 +179,7 @@ impl ImportExportType {
| ImportExportType::ExportLabels => "Export successful!",
ImportExportType::ImportBackup(_, _)
| ImportExportType::ImportPsbt
| ImportExportType::ImportXpub(_)
| ImportExportType::WalletFromBackup
| ImportExportType::ImportDescriptor => "Import successful",
}
@ -231,6 +241,7 @@ pub enum Progress {
None,
Psbt(Psbt),
Descriptor(LianaDescriptor),
Xpub(String),
LabelsConflict(Sender<bool>),
KeyAliasesConflict(Sender<bool>),
UpdateAliases(HashMap<Fingerprint, settings::KeySetting>),
@ -284,6 +295,7 @@ impl Export {
}
ImportExportType::ExportLabels => export_labels(&sender, daemon, path).await,
ImportExportType::ImportPsbt => import_psbt(&sender, path).await,
ImportExportType::ImportXpub(network) => import_xpub(&sender, path, network).await,
ImportExportType::ImportDescriptor => import_descriptor(&sender, path).await,
ImportExportType::ExportBackup(str) => export_string(&sender, path, str).await,
ImportExportType::ExportXpub(xpub_str) => export_string(&sender, path, xpub_str).await,
@ -596,6 +608,35 @@ pub async fn import_descriptor(
Ok(())
}
pub async fn import_xpub(
sender: &UnboundedSender<Progress>,
path: PathBuf,
network: Network,
) -> Result<(), Error> {
let mut file = File::open(path)?;
let mut xpub_str = String::new();
file.read_to_string(&mut xpub_str)?;
if let Ok(DescriptorPublicKey::XPub(key)) = DescriptorPublicKey::from_str(&xpub_str) {
let valid = if network == Network::Bitcoin {
key.xkey.network == Network::Bitcoin.into()
} else {
key.xkey.network == Network::Testnet.into()
};
if valid {
send_progress!(sender, Progress(100.0));
send_progress!(sender, Xpub(xpub_str));
} else {
return Err(Error::XpubNetwork);
}
} else {
return Err(Error::ParseXpub);
}
Ok(())
}
/// Import a backup in an already existing wallet:
/// - Load backup from file
/// - check if networks matches