diff --git a/liana-gui/src/app/state/export.rs b/liana-gui/src/app/state/export.rs index 422a835d..e607c9f2 100644 --- a/liana-gui/src/app/state/export.rs +++ b/liana-gui/src/app/state/export.rs @@ -45,7 +45,9 @@ impl ExportModal { ImportExportType::ExportPsbt(_) => "Export PSBT", ImportExportType::ExportBackup(_) => "Export Backup", ImportExportType::Descriptor(_) => "Export Descriptor", - ImportExportType::ExportLabels => "Export Labels", + ImportExportType::ExportProcessBackup(..) | ImportExportType::ExportLabels => { + "Export Labels" + } ImportExportType::ImportPsbt => "Import PSBT", ImportExportType::ImportDescriptor => "Import Descriptor", ImportExportType::ImportBackup(..) => "Restore Backup", @@ -72,7 +74,7 @@ impl ExportModal { ImportExportType::ImportPsbt => "psbt.psbt".into(), ImportExportType::ImportDescriptor => "descriptor.descriptor".into(), ImportExportType::ExportLabels => format!("liana-labels-{date}.jsonl"), - ImportExportType::ExportBackup(_) => { + ImportExportType::ExportBackup(_) | ImportExportType::ExportProcessBackup(..) => { format!("liana-backup-{date}.json") } ImportExportType::WalletFromBackup | ImportExportType::ImportBackup(_, _) => { diff --git a/liana-gui/src/app/state/settings/mod.rs b/liana-gui/src/app/state/settings/mod.rs index e8f625e4..cefb712d 100644 --- a/liana-gui/src/app/state/settings/mod.rs +++ b/liana-gui/src/app/state/settings/mod.rs @@ -10,7 +10,7 @@ use iced::Task; use liana_ui::{component::form, widget::Element}; use bitcoind::BitcoindSettingsState; -use wallet::{app_backup, WalletSettingsState}; +use wallet::WalletSettingsState; use crate::{ app::{ @@ -23,7 +23,7 @@ use crate::{ Config, }, daemon::{Daemon, DaemonBackend}, - export::{self, ImportExportMessage, ImportExportType}, + export::{ImportExportMessage, ImportExportType}, }; use super::export::ExportModal; @@ -260,27 +260,13 @@ impl State for ImportExportSettingsState { let config = self.config.clone(); let wallet = self.wallet.clone(); let daemon = daemon.clone(); - return Task::perform( - async move { app_backup(datadir, network, config, wallet, daemon).await }, - |s| { - Message::View(view::Message::Settings( - view::SettingsMessage::ExportBackup(s), - )) - }, + let modal = ExportModal::new( + Some(daemon), + ImportExportType::ExportProcessBackup(datadir, network, config, wallet), ); + launch!(self, modal, true); } } - Message::View(view::Message::Settings(view::SettingsMessage::ExportBackup(backup))) => { - let backup = match backup { - Ok(b) => b, - Err(e) => { - self.warning = Some(Error::ImportExport(export::Error::Backup(e))); - return Task::none(); - } - }; - let modal = ExportModal::new(Some(daemon), ImportExportType::ExportBackup(backup)); - launch!(self, modal, true); - } Message::View(view::Message::Settings(view::SettingsMessage::ImportWallet)) => { if self.modal.is_none() { let modal = diff --git a/liana-gui/src/app/state/settings/wallet.rs b/liana-gui/src/app/state/settings/wallet.rs index 1bf7c387..d8b24434 100644 --- a/liana-gui/src/app/state/settings/wallet.rs +++ b/liana-gui/src/app/state/settings/wallet.rs @@ -26,9 +26,8 @@ use crate::{ wallet::Wallet, Config, }, - backup::{self, Backup}, daemon::{Daemon, DaemonBackend}, - export::{self, ImportExportMessage, ImportExportType}, + export::{ImportExportMessage, ImportExportType}, hw::{HardwareWallet, HardwareWalletConfig, HardwareWallets}, }; @@ -246,29 +245,10 @@ impl State for WalletSettingsState { let config = self.config.clone(); let wallet = self.wallet.clone(); let daemon = daemon.clone(); - Task::perform( - async move { app_backup(datadir, network, config, wallet, daemon).await }, - |s| { - Message::View(view::Message::Settings( - view::SettingsMessage::ExportBackup(s), - )) - }, - ) - } else { - Task::none() - } - } - Message::View(view::Message::Settings(view::SettingsMessage::ExportBackup(backup))) => { - if self.modal.is_none() { - let backup = match backup { - Ok(b) => b, - Err(e) => { - self.warning = Some(Error::ImportExport(export::Error::Backup(e))); - return Task::none(); - } - }; - let modal = - ExportModal::new(Some(daemon), ImportExportType::ExportBackup(backup)); + let modal = ExportModal::new( + Some(daemon), + ImportExportType::ExportProcessBackup(datadir, network, config, wallet), + ); let launch = modal.launch(true); self.modal = Modal::ImportExport(modal); launch @@ -525,14 +505,3 @@ pub async fn update_keys_aliases( Ok(Arc::new(wallet)) } - -pub async fn app_backup( - datadir: PathBuf, - network: Network, - config: Arc, - wallet: Arc, - daemon: Arc, -) -> Result { - let backup = Backup::from_app(datadir, network, config, wallet, daemon).await?; - serde_json::to_string_pretty(&backup).map_err(|_| backup::Error::Json) -} diff --git a/liana-gui/src/app/view/message.rs b/liana-gui/src/app/view/message.rs index e5c46436..315d5018 100644 --- a/liana-gui/src/app/view/message.rs +++ b/liana-gui/src/app/view/message.rs @@ -1,4 +1,4 @@ -use crate::{app::menu::Menu, backup, export::ImportExportMessage, node::bitcoind::RpcAuthType}; +use crate::{app::menu::Menu, export::ImportExportMessage, node::bitcoind::RpcAuthType}; use liana::miniscript::bitcoin::{bip32::Fingerprint, OutPoint}; pub trait Close { @@ -89,7 +89,6 @@ pub enum SettingsMessage { ExportTransactions, ExportLabels, ExportWallet, - ExportBackup(Result), ImportWallet, AboutSection, RegisterWallet, diff --git a/liana-gui/src/backup.rs b/liana-gui/src/backup.rs index cab64de3..4a272ab0 100644 --- a/liana-gui/src/backup.rs +++ b/liana-gui/src/backup.rs @@ -16,10 +16,12 @@ use std::{ sync::Arc, time::{SystemTime, UNIX_EPOCH}, }; +use tokio::sync::mpsc::UnboundedSender; use crate::{ app::{settings::Settings, wallet::Wallet, Config}, daemon::{model::HistoryTransaction, Daemon, DaemonBackend, DaemonError}, + export::Progress, installer::{ extract_daemon_config, extract_local_gui_settings, extract_remote_gui_settings, Context, RemoteBackend, @@ -183,6 +185,7 @@ impl Backup { config: Arc, wallet: Arc, daemon: Arc, + sender: &UnboundedSender, ) -> Result { let mut proprietary = serde_json::Map::new(); proprietary.insert(LIANA_VERSION_KEY.to_string(), liana_version().into()); @@ -205,6 +208,8 @@ impl Backup { let info = daemon.get_info().await?; + let _ = sender.send(Progress::Progress(20.0)); + let mut account = Account::new(descriptor); account.chain_tip = Some(ChainTip { @@ -239,12 +244,17 @@ impl Backup { bip329::Labels::new(buff) }; + let _ = sender.send(Progress::Progress(30.0)); + account.labels = Some(labels); account.transactions = get_transactions(&daemon) .await? .into_iter() .map(|tx| miniscript::bitcoin::consensus::encode::serialize_hex(&tx.tx)) .collect(); + + let _ = sender.send(Progress::Progress(40.0)); + account.psbts = daemon .list_spend_transactions(None) .await? @@ -252,6 +262,8 @@ impl Backup { .map(|tx| tx.psbt.to_string()) .collect(); + let _ = sender.send(Progress::Progress(50.0)); + let statuses = [ CoinStatus::Unconfirmed, CoinStatus::Confirmed, @@ -265,6 +277,8 @@ impl Backup { .map(|c| (c.outpoint.clone().to_string(), Coin::from(c))) .collect(); + let _ = sender.send(Progress::Progress(60.0)); + Ok(Backup { name: Some(name), accounts: vec![account], diff --git a/liana-gui/src/export.rs b/liana-gui/src/export.rs index b9a48608..0848a7d1 100644 --- a/liana-gui/src/export.rs +++ b/liana-gui/src/export.rs @@ -145,6 +145,7 @@ pub enum ImportExportType { Transactions, ExportPsbt(String), ExportBackup(String), + ExportProcessBackup(PathBuf, Network, Arc, Arc), ImportBackup( Option>, /*overwrite_labels*/ Option>, /*overwrite_aliases*/ @@ -163,6 +164,7 @@ impl ImportExportType { | ImportExportType::ExportPsbt(_) | ImportExportType::ExportBackup(_) | ImportExportType::Descriptor(_) + | ImportExportType::ExportProcessBackup(..) | ImportExportType::ExportLabels => "Export successful!", ImportExportType::ImportBackup(_, _) | ImportExportType::ImportPsbt @@ -282,6 +284,18 @@ impl Export { ImportExportType::ImportPsbt => import_psbt(&sender, path).await, ImportExportType::ImportDescriptor => import_descriptor(&sender, path).await, ImportExportType::ExportBackup(str) => export_string(&sender, path, str).await, + ImportExportType::ExportProcessBackup(datadir, network, config, wallet) => { + app_backup_export( + datadir, + network, + config, + wallet, + daemon.clone().expect("cannot fail"), + path, + &sender, + ) + .await + } ImportExportType::ImportBackup(..) => import_backup(&sender, path, daemon).await, ImportExportType::WalletFromBackup => wallet_from_backup(&sender, path).await, } { @@ -1127,3 +1141,30 @@ pub async fn get_path(filename: String, write: bool) -> Option { .map(|fh| fh.path().to_path_buf()) } } + +pub async fn app_backup( + datadir: PathBuf, + network: Network, + config: Arc, + wallet: Arc, + daemon: Arc, + sender: &UnboundedSender, +) -> Result { + let backup = Backup::from_app(datadir, network, config, wallet, daemon, sender).await?; + serde_json::to_string_pretty(&backup).map_err(|_| backup::Error::Json) +} + +pub async fn app_backup_export( + datadir: PathBuf, + network: Network, + config: Arc, + wallet: Arc, + daemon: Arc, + path: PathBuf, + sender: &UnboundedSender, +) -> Result<(), Error> { + let backup = app_backup(datadir.clone(), network, config, wallet, daemon, sender) + .await + .map_err(Error::Backup)?; + export_string(sender, path, backup).await +}