export: implement export labels using BIP-0329
This commit is contained in:
parent
38eed1b881
commit
86313f5282
@ -40,9 +40,9 @@ impl ExportModal {
|
||||
}
|
||||
|
||||
pub fn default_filename(&self) -> String {
|
||||
let date = chrono::Local::now().format("%Y-%m-%dT%H-%M-%S");
|
||||
match &self.import_export_type {
|
||||
ImportExportType::Transactions => {
|
||||
let date = chrono::Local::now().format("%Y-%m-%dT%H-%M-%S");
|
||||
format!("liana-txs-{date}.csv")
|
||||
}
|
||||
ImportExportType::ExportPsbt(_) => "psbt.psbt".into(),
|
||||
@ -57,6 +57,7 @@ impl ExportModal {
|
||||
}
|
||||
ImportExportType::ImportPsbt => "psbt.psbt".into(),
|
||||
ImportExportType::ImportDescriptor => "descriptor.descriptor".into(),
|
||||
ImportExportType::ExportLabels => format!("liana-labels-{date}.csv"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ use std::path::Path;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use lianad::bip329::Labels;
|
||||
use lianad::commands::GetLabelsBip329Result;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
@ -207,8 +208,10 @@ impl<C: Client + Send + Sync + Debug> Daemon for Lianad<C> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_labels_bip329(&self, _offset: u32, _limit: u32) -> Result<Labels, DaemonError> {
|
||||
todo!()
|
||||
async fn get_labels_bip329(&self, offset: u32, limit: u32) -> Result<Labels, DaemonError> {
|
||||
let res: GetLabelsBip329Result =
|
||||
self.call("getlabelsbip329", Some(vec![json!(offset), json!(limit)]))?;
|
||||
Ok(res.labels)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ use liana::{
|
||||
descriptors::LianaDescriptor,
|
||||
miniscript::bitcoin::{Amount, Psbt, Txid},
|
||||
};
|
||||
use lianad::bip329::{error::ExportError, Labels};
|
||||
use tokio::{
|
||||
task::{JoinError, JoinHandle},
|
||||
time::sleep,
|
||||
@ -32,6 +33,8 @@ use crate::{
|
||||
lianalite::client::backend::api::DEFAULT_LIMIT,
|
||||
};
|
||||
|
||||
const DUMP_LABELS_LIMIT: u32 = 100;
|
||||
|
||||
macro_rules! send_error {
|
||||
($sender:ident, $error:ident) => {
|
||||
if let Err(e) = $sender.send(Progress::Error(Error::$error)) {
|
||||
@ -125,6 +128,7 @@ pub enum Error {
|
||||
DaemonMissing,
|
||||
ParsePsbt,
|
||||
ParseDescriptor,
|
||||
Bip329Export(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
@ -132,6 +136,7 @@ pub enum ImportExportType {
|
||||
Transactions,
|
||||
ExportPsbt(String),
|
||||
Descriptor(LianaDescriptor),
|
||||
ExportLabels,
|
||||
ImportPsbt,
|
||||
ImportDescriptor,
|
||||
}
|
||||
@ -154,6 +159,12 @@ impl From<DaemonError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExportError> for Error {
|
||||
fn from(value: ExportError) -> Self {
|
||||
Error::Bip329Export(format!("{:?}", value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Status {
|
||||
Init,
|
||||
@ -209,6 +220,7 @@ impl Export {
|
||||
ImportExportType::Transactions => export_transactions(sender, daemon, path).await,
|
||||
ImportExportType::ExportPsbt(psbt) => export_psbt(sender, path, psbt),
|
||||
ImportExportType::Descriptor(descriptor) => export_descriptor(sender, path, descriptor),
|
||||
ImportExportType::ExportLabels => export_labels(sender, daemon, path).await,
|
||||
ImportExportType::ImportPsbt => import_psbt(sender, path),
|
||||
ImportExportType::ImportDescriptor => import_descriptor(sender, path),
|
||||
};
|
||||
@ -538,6 +550,54 @@ pub fn import_descriptor(sender: Sender<Progress>, path: PathBuf) {
|
||||
send_progress!(sender, Descriptor(descriptor));
|
||||
}
|
||||
|
||||
pub async fn export_labels(
|
||||
sender: Sender<Progress>,
|
||||
daemon: Option<Arc<dyn Daemon + Sync + Send>>,
|
||||
path: PathBuf,
|
||||
) {
|
||||
let daemon = match daemon {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
send_error!(sender, Error::DaemonMissing);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut labels = Labels::new(Vec::new());
|
||||
let mut offset = 0u32;
|
||||
loop {
|
||||
let mut fetched = match daemon.get_labels_bip329(offset, DUMP_LABELS_LIMIT).await {
|
||||
Ok(l) => l,
|
||||
Err(e) => {
|
||||
send_error!(sender, e.into());
|
||||
return;
|
||||
}
|
||||
}
|
||||
.into_vec();
|
||||
let fetch_len = fetched.len() as u32;
|
||||
labels.append(&mut fetched);
|
||||
if fetch_len < DUMP_LABELS_LIMIT {
|
||||
break;
|
||||
} else {
|
||||
offset += DUMP_LABELS_LIMIT;
|
||||
}
|
||||
}
|
||||
let json = match labels.export() {
|
||||
Ok(j) => j,
|
||||
Err(e) => {
|
||||
send_error!(sender, e.into());
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut file = open_file!(path, sender);
|
||||
|
||||
if let Err(e) = file.write_all(json.as_bytes()) {
|
||||
send_error!(sender, e.into());
|
||||
return;
|
||||
}
|
||||
send_progress!(sender, Progress(100.0));
|
||||
send_progress!(sender, Ended);
|
||||
}
|
||||
|
||||
pub async fn get_path(filename: String) -> Option<PathBuf> {
|
||||
rfd::AsyncFileDialog::new()
|
||||
.set_title("Choose a location to export...")
|
||||
|
||||
@ -333,6 +333,11 @@ pub struct ListPsbts {
|
||||
pub psbts: Vec<Psbt>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Labels {
|
||||
pub labels: lianad::bip329::Labels,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Address {
|
||||
#[serde(deserialize_with = "deser_addr_assume_checked")]
|
||||
|
||||
@ -1117,9 +1117,22 @@ impl Daemon for BackendWalletClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_labels_bip329(&self, _offset: u32, _limit: u32) -> Result<Labels, DaemonError> {
|
||||
// TODO: add an endpoint on backend
|
||||
todo!()
|
||||
async fn get_labels_bip329(&self, offset: u32, limit: u32) -> Result<Labels, DaemonError> {
|
||||
let response: Response = self
|
||||
.inner
|
||||
.request(
|
||||
Method::GET,
|
||||
&format!(
|
||||
"{}/v1/wallets/{}/labels/bip329?offset={}&limit={}",
|
||||
self.inner.url, self.wallet_uuid, offset, limit
|
||||
),
|
||||
)
|
||||
.await
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let res: api::Labels = response.json().await?;
|
||||
Ok(res.labels)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user