Merge #1593: gui: move the backup processing in export thread

abf360f567379f61963d3b258b124ed347529c43 gui: move the backup processing in export thread (pythcoiner)

Pull request description:

  this PR move the processing of the backup in the export thread

ACKs for top commit:
  edouardparis:
    ACK abf360f567379f61963d3b258b124ed347529c43

Tree-SHA512: 80349d18c1c4b6b86d6640fd1b5f7090eee72114255abe5acff4a49e70169ce48d712a3d954c6a6e126f2b470ff49654b4a9882a0b6e549c75aaed882191c813
This commit is contained in:
edouardparis 2025-03-21 10:54:48 +01:00
commit 756adc32db
No known key found for this signature in database
GPG Key ID: E65F7A089C20DC8F
6 changed files with 71 additions and 60 deletions

View File

@ -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(_, _) => {

View File

@ -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 =

View File

@ -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<Config>,
wallet: Arc<Wallet>,
daemon: Arc<dyn Daemon + Sync + Send>,
) -> Result<String, backup::Error> {
let backup = Backup::from_app(datadir, network, config, wallet, daemon).await?;
serde_json::to_string_pretty(&backup).map_err(|_| backup::Error::Json)
}

View File

@ -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<String, backup::Error>),
ImportWallet,
AboutSection,
RegisterWallet,

View File

@ -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<Config>,
wallet: Arc<Wallet>,
daemon: Arc<dyn Daemon + Sync + Send>,
sender: &UnboundedSender<Progress>,
) -> Result<Self, Error> {
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],

View File

@ -145,6 +145,7 @@ pub enum ImportExportType {
Transactions,
ExportPsbt(String),
ExportBackup(String),
ExportProcessBackup(PathBuf, Network, Arc<Config>, Arc<Wallet>),
ImportBackup(
Option<Sender<bool>>, /*overwrite_labels*/
Option<Sender<bool>>, /*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<PathBuf> {
.map(|fh| fh.path().to_path_buf())
}
}
pub async fn app_backup(
datadir: PathBuf,
network: Network,
config: Arc<Config>,
wallet: Arc<Wallet>,
daemon: Arc<dyn Daemon + Sync + Send>,
sender: &UnboundedSender<Progress>,
) -> Result<String, backup::Error> {
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<Config>,
wallet: Arc<Wallet>,
daemon: Arc<dyn Daemon + Sync + Send>,
path: PathBuf,
sender: &UnboundedSender<Progress>,
) -> Result<(), Error> {
let backup = app_backup(datadir.clone(), network, config, wallet, daemon, sender)
.await
.map_err(Error::Backup)?;
export_string(sender, path, backup).await
}