Add option to specify backup path (#228)

* feat: add backup_path to backup method

* Re-generate bindings with flutter_rust_bridge`@ 2.0.0-dev.35

* Rebased on main

* Update backup path description

---------

Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com>
This commit is contained in:
yse
2024-05-27 21:01:49 +02:00
committed by GitHub
parent 6ef5701660
commit 2fcefee45e
21 changed files with 366 additions and 58 deletions

View File

@@ -43,7 +43,10 @@ pub(crate) enum Command {
/// Empties the encrypted transaction cache /// Empties the encrypted transaction cache
EmptyCache, EmptyCache,
/// Backs up the current pending swaps /// Backs up the current pending swaps
Backup, Backup {
#[arg(short, long)]
backup_path: Option<String>,
},
/// Retrieve a list of backups /// Retrieve a list of backups
Restore { Restore {
#[arg(short, long)] #[arg(short, long)]
@@ -159,8 +162,8 @@ pub(crate) async fn handle_command(
sdk.empty_wallet_cache()?; sdk.empty_wallet_cache()?;
command_result!("Cache emptied successfully") command_result!("Cache emptied successfully")
} }
Command::Backup => { Command::Backup { backup_path } => {
sdk.backup()?; sdk.backup(BackupRequest { backup_path })?;
command_result!("Backup created successfully!") command_result!("Backup created successfully!")
} }
Command::Restore { backup_path } => { Command::Restore { backup_path } => {

View File

@@ -25,6 +25,10 @@ typedef struct wire_cst_list_prim_u_8_strict {
int32_t len; int32_t len;
} wire_cst_list_prim_u_8_strict; } wire_cst_list_prim_u_8_strict;
typedef struct wire_cst_backup_request {
struct wire_cst_list_prim_u_8_strict *backup_path;
} wire_cst_backup_request;
typedef struct wire_cst_get_info_request { typedef struct wire_cst_get_info_request {
bool with_scan; bool with_scan;
} wire_cst_get_info_request; } wire_cst_get_info_request;
@@ -179,7 +183,8 @@ void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_add_event_liste
struct wire_cst_list_prim_u_8_strict *listener); struct wire_cst_list_prim_u_8_strict *listener);
void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup(int64_t port_, void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup(int64_t port_,
uintptr_t that); uintptr_t that,
struct wire_cst_backup_request *req);
void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache(int64_t port_, void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache(int64_t port_,
uintptr_t that); uintptr_t that);
@@ -221,6 +226,8 @@ void frbgen_breez_liquid_rust_arc_increment_strong_count_RustOpaque_flutter_rust
void frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(const void *ptr); void frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(const void *ptr);
struct wire_cst_backup_request *frbgen_breez_liquid_cst_new_box_autoadd_backup_request(void);
struct wire_cst_connect_request *frbgen_breez_liquid_cst_new_box_autoadd_connect_request(void); struct wire_cst_connect_request *frbgen_breez_liquid_cst_new_box_autoadd_connect_request(void);
struct wire_cst_get_info_request *frbgen_breez_liquid_cst_new_box_autoadd_get_info_request(void); struct wire_cst_get_info_request *frbgen_breez_liquid_cst_new_box_autoadd_get_info_request(void);
@@ -244,6 +251,7 @@ struct wire_cst_list_payment *frbgen_breez_liquid_cst_new_list_payment(int32_t l
struct wire_cst_list_prim_u_8_strict *frbgen_breez_liquid_cst_new_list_prim_u_8_strict(int32_t len); struct wire_cst_list_prim_u_8_strict *frbgen_breez_liquid_cst_new_list_prim_u_8_strict(int32_t len);
static int64_t dummy_method_to_enforce_bundling(void) { static int64_t dummy_method_to_enforce_bundling(void) {
int64_t dummy_var = 0; int64_t dummy_var = 0;
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_backup_request);
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_connect_request); dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_connect_request);
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_get_info_request); dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_get_info_request);
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_payment); dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_payment);

View File

@@ -69,6 +69,10 @@ dictionary ReceivePaymentResponse {
string invoice; string invoice;
}; };
dictionary BackupRequest {
string? backup_path = null;
};
dictionary RestoreRequest { dictionary RestoreRequest {
string? backup_path = null; string? backup_path = null;
}; };
@@ -145,7 +149,7 @@ interface BindingLiquidSdk {
void sync(); void sync();
[Throws=LiquidSdkError] [Throws=LiquidSdkError]
void backup(); void backup(BackupRequest req);
[Throws=LiquidSdkError] [Throws=LiquidSdkError]
void restore(RestoreRequest req); void restore(RestoreRequest req);

View File

@@ -75,8 +75,8 @@ impl BindingLiquidSdk {
self.sdk.empty_wallet_cache().map_err(Into::into) self.sdk.empty_wallet_cache().map_err(Into::into)
} }
pub fn backup(&self) -> LiquidSdkResult<()> { pub fn backup(&self, req: BackupRequest) -> LiquidSdkResult<()> {
self.sdk.backup().map_err(Into::into) self.sdk.backup(req).map_err(Into::into)
} }
pub fn restore(&self, req: RestoreRequest) -> LiquidSdkResult<()> { pub fn restore(&self, req: RestoreRequest) -> LiquidSdkResult<()> {

View File

@@ -86,8 +86,8 @@ impl BindingLiquidSdk {
self.sdk.empty_wallet_cache().map_err(Into::into) self.sdk.empty_wallet_cache().map_err(Into::into)
} }
pub fn backup(&self) -> Result<(), LiquidSdkError> { pub fn backup(&self, req: BackupRequest) -> Result<(), LiquidSdkError> {
self.sdk.backup().map_err(Into::into) self.sdk.backup(req).map_err(Into::into)
} }
pub fn restore(&self, req: RestoreRequest) -> Result<(), LiquidSdkError> { pub fn restore(&self, req: RestoreRequest) -> Result<(), LiquidSdkError> {

View File

@@ -60,6 +60,21 @@ impl CstDecode<String> for *mut wire_cst_list_prim_u_8_strict {
String::from_utf8(vec).unwrap() String::from_utf8(vec).unwrap()
} }
} }
impl CstDecode<crate::model::BackupRequest> for wire_cst_backup_request {
// Codec=Cst (C-struct based), see doc to use other codecs
fn cst_decode(self) -> crate::model::BackupRequest {
crate::model::BackupRequest {
backup_path: self.backup_path.cst_decode(),
}
}
}
impl CstDecode<crate::model::BackupRequest> for *mut wire_cst_backup_request {
// Codec=Cst (C-struct based), see doc to use other codecs
fn cst_decode(self) -> crate::model::BackupRequest {
let wrap = unsafe { flutter_rust_bridge::for_generated::box_from_leak_ptr(self) };
CstDecode::<crate::model::BackupRequest>::cst_decode(*wrap).into()
}
}
impl CstDecode<crate::model::ConnectRequest> for *mut wire_cst_connect_request { impl CstDecode<crate::model::ConnectRequest> for *mut wire_cst_connect_request {
// Codec=Cst (C-struct based), see doc to use other codecs // Codec=Cst (C-struct based), see doc to use other codecs
fn cst_decode(self) -> crate::model::ConnectRequest { fn cst_decode(self) -> crate::model::ConnectRequest {
@@ -350,6 +365,18 @@ impl CstDecode<crate::model::SendPaymentResponse> for wire_cst_send_payment_resp
} }
} }
} }
impl NewWithNullPtr for wire_cst_backup_request {
fn new_with_null_ptr() -> Self {
Self {
backup_path: core::ptr::null_mut(),
}
}
}
impl Default for wire_cst_backup_request {
fn default() -> Self {
Self::new_with_null_ptr()
}
}
impl NewWithNullPtr for wire_cst_connect_request { impl NewWithNullPtr for wire_cst_connect_request {
fn new_with_null_ptr() -> Self { fn new_with_null_ptr() -> Self {
Self { Self {
@@ -550,8 +577,9 @@ pub extern "C" fn frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_ad
pub extern "C" fn frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup( pub extern "C" fn frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup(
port_: i64, port_: i64,
that: usize, that: usize,
req: *mut wire_cst_backup_request,
) { ) {
wire__crate__bindings__BindingLiquidSdk_backup_impl(port_, that) wire__crate__bindings__BindingLiquidSdk_backup_impl(port_, that, req)
} }
#[no_mangle] #[no_mangle]
@@ -658,6 +686,14 @@ pub extern "C" fn frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque
} }
} }
#[no_mangle]
pub extern "C" fn frbgen_breez_liquid_cst_new_box_autoadd_backup_request(
) -> *mut wire_cst_backup_request {
flutter_rust_bridge::for_generated::new_leak_box_ptr(
wire_cst_backup_request::new_with_null_ptr(),
)
}
#[no_mangle] #[no_mangle]
pub extern "C" fn frbgen_breez_liquid_cst_new_box_autoadd_connect_request( pub extern "C" fn frbgen_breez_liquid_cst_new_box_autoadd_connect_request(
) -> *mut wire_cst_connect_request { ) -> *mut wire_cst_connect_request {
@@ -747,6 +783,11 @@ pub extern "C" fn frbgen_breez_liquid_cst_new_list_prim_u_8_strict(
flutter_rust_bridge::for_generated::new_leak_box_ptr(ans) flutter_rust_bridge::for_generated::new_leak_box_ptr(ans)
} }
#[repr(C)]
#[derive(Clone, Copy)]
pub struct wire_cst_backup_request {
backup_path: *mut wire_cst_list_prim_u_8_strict,
}
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct wire_cst_connect_request { pub struct wire_cst_connect_request {

View File

@@ -86,6 +86,7 @@ fn wire__crate__bindings__BindingLiquidSdk_backup_impl(
that: impl CstDecode< that: impl CstDecode<
RustOpaqueNom<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<BindingLiquidSdk>>, RustOpaqueNom<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<BindingLiquidSdk>>,
>, >,
req: impl CstDecode<crate::model::BackupRequest>,
) { ) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>( FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo { flutter_rust_bridge::for_generated::TaskInfo {
@@ -95,6 +96,7 @@ fn wire__crate__bindings__BindingLiquidSdk_backup_impl(
}, },
move || { move || {
let api_that = that.cst_decode(); let api_that = that.cst_decode();
let api_req = req.cst_decode();
move |context| { move |context| {
transform_result_dco((move || { transform_result_dco((move || {
let mut api_that_decoded = None; let mut api_that_decoded = None;
@@ -111,7 +113,7 @@ fn wire__crate__bindings__BindingLiquidSdk_backup_impl(
} }
} }
let api_that = api_that_decoded.unwrap(); let api_that = api_that_decoded.unwrap();
crate::bindings::BindingLiquidSdk::backup(&api_that) crate::bindings::BindingLiquidSdk::backup(&api_that, api_req)
})()) })())
} }
}, },
@@ -578,6 +580,16 @@ impl SseDecode for String {
} }
} }
impl SseDecode for crate::model::BackupRequest {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut var_backupPath = <Option<String>>::sse_decode(deserializer);
return crate::model::BackupRequest {
backup_path: var_backupPath,
};
}
}
impl SseDecode for bool { impl SseDecode for bool {
// Codec=Sse (Serialization based), see doc to use other codecs // Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@@ -1016,6 +1028,20 @@ impl flutter_rust_bridge::IntoIntoDart<FrbWrapper<BindingLiquidSdk>> for Binding
} }
} }
// Codec=Dco (DartCObject based), see doc to use other codecs
impl flutter_rust_bridge::IntoDart for crate::model::BackupRequest {
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
[self.backup_path.into_into_dart().into_dart()].into_dart()
}
}
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::model::BackupRequest {}
impl flutter_rust_bridge::IntoIntoDart<crate::model::BackupRequest>
for crate::model::BackupRequest
{
fn into_into_dart(self) -> crate::model::BackupRequest {
self
}
}
// Codec=Dco (DartCObject based), see doc to use other codecs // Codec=Dco (DartCObject based), see doc to use other codecs
impl flutter_rust_bridge::IntoDart for crate::model::ConnectRequest { impl flutter_rust_bridge::IntoDart for crate::model::ConnectRequest {
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
@@ -1392,6 +1418,13 @@ impl SseEncode for String {
} }
} }
impl SseEncode for crate::model::BackupRequest {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<Option<String>>::sse_encode(self.backup_path, serializer);
}
}
impl SseEncode for bool { impl SseEncode for bool {
// Codec=Sse (Serialization based), see doc to use other codecs // Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {

View File

@@ -152,6 +152,15 @@ pub struct GetInfoResponse {
pub pubkey: String, pub pubkey: String,
} }
#[derive(Debug, Serialize)]
pub struct BackupRequest {
/// Path to the backup.
///
/// If not set, it defaults to `backup.sql` for mainnet and `backup-testnet.sql` for testnet.
/// The file will be saved in [ConnectRequest]'s `data_dir`.
pub backup_path: Option<String>,
}
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct RestoreRequest { pub struct RestoreRequest {
pub backup_path: Option<String>, pub backup_path: Option<String>,

View File

@@ -6,27 +6,16 @@ use super::Persister;
use crate::model::Network; use crate::model::Network;
impl Persister { impl Persister {
pub(crate) fn get_backup_path(&self) -> PathBuf { pub(crate) fn get_default_backup_path(&self) -> PathBuf {
self.main_db_dir.join(match self.network { self.main_db_dir.join(match self.network {
Network::Liquid => "backup.sql", Network::Liquid => "backup.sql",
Network::LiquidTestnet => "backup-testnet.sql", Network::LiquidTestnet => "backup-testnet.sql",
}) })
} }
pub(crate) fn backup(&self) -> Result<()> { pub(crate) fn backup(&self, backup_path: PathBuf) -> Result<()> {
let con = self.get_connection()?; let con = self.get_connection()?;
con.backup(rusqlite::DatabaseName::Main, backup_path, None)?;
let backup_file = match self.network {
Network::Liquid => "backup.sql",
Network::LiquidTestnet => "backup-testnet.sql",
};
con.backup(
rusqlite::DatabaseName::Main,
self.main_db_dir.join(backup_file),
None,
)?;
Ok(()) Ok(())
} }

View File

@@ -1234,14 +1234,6 @@ impl LiquidSdk {
Ok(()) Ok(())
} }
pub fn restore(&self, req: RestoreRequest) -> Result<()> {
let backup_path = match req.backup_path {
Some(p) => PathBuf::from_str(&p)?,
None => self.persister.get_backup_path(),
};
self.persister.restore_from_backup(backup_path)
}
/// Synchronize the DB with mempool and onchain data /// Synchronize the DB with mempool and onchain data
pub async fn sync(&self) -> Result<()> { pub async fn sync(&self) -> Result<()> {
let t0 = Instant::now(); let t0 = Instant::now();
@@ -1253,8 +1245,20 @@ impl LiquidSdk {
Ok(()) Ok(())
} }
pub fn backup(&self) -> Result<()> { pub fn backup(&self, req: BackupRequest) -> Result<()> {
self.persister.backup() let backup_path = req
.backup_path
.map(PathBuf::from)
.unwrap_or(self.persister.get_default_backup_path());
self.persister.backup(backup_path)
}
pub fn restore(&self, req: RestoreRequest) -> Result<()> {
let backup_path = req
.backup_path
.map(PathBuf::from)
.unwrap_or(self.persister.get_default_backup_path());
self.persister.restore_from_backup(backup_path)
} }
fn get_liquid_swap_key(&self) -> Result<LiquidSwapKey, PaymentError> { fn get_liquid_swap_key(&self) -> Result<LiquidSwapKey, PaymentError> {

View File

@@ -30,8 +30,8 @@ class BindingLiquidSdk extends RustOpaque {
Stream<LiquidSdkEvent> addEventListener({dynamic hint}) => Stream<LiquidSdkEvent> addEventListener({dynamic hint}) =>
RustLib.instance.api.crateBindingsBindingLiquidSdkAddEventListener(that: this, hint: hint); RustLib.instance.api.crateBindingsBindingLiquidSdkAddEventListener(that: this, hint: hint);
Future<void> backup({dynamic hint}) => Future<void> backup({required BackupRequest req, dynamic hint}) =>
RustLib.instance.api.crateBindingsBindingLiquidSdkBackup(that: this, hint: hint); RustLib.instance.api.crateBindingsBindingLiquidSdkBackup(that: this, req: req, hint: hint);
Future<void> emptyWalletCache({dynamic hint}) => Future<void> emptyWalletCache({dynamic hint}) =>
RustLib.instance.api.crateBindingsBindingLiquidSdkEmptyWalletCache(that: this, hint: hint); RustLib.instance.api.crateBindingsBindingLiquidSdkEmptyWalletCache(that: this, hint: hint);

View File

@@ -66,7 +66,8 @@ abstract class RustLibApi extends BaseApi {
Stream<LiquidSdkEvent> crateBindingsBindingLiquidSdkAddEventListener( Stream<LiquidSdkEvent> crateBindingsBindingLiquidSdkAddEventListener(
{required BindingLiquidSdk that, dynamic hint}); {required BindingLiquidSdk that, dynamic hint});
Future<void> crateBindingsBindingLiquidSdkBackup({required BindingLiquidSdk that, dynamic hint}); Future<void> crateBindingsBindingLiquidSdkBackup(
{required BindingLiquidSdk that, required BackupRequest req, dynamic hint});
Future<void> crateBindingsBindingLiquidSdkEmptyWalletCache({required BindingLiquidSdk that, dynamic hint}); Future<void> crateBindingsBindingLiquidSdkEmptyWalletCache({required BindingLiquidSdk that, dynamic hint});
@@ -140,20 +141,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
); );
@override @override
Future<void> crateBindingsBindingLiquidSdkBackup({required BindingLiquidSdk that, dynamic hint}) { Future<void> crateBindingsBindingLiquidSdkBackup(
{required BindingLiquidSdk that, required BackupRequest req, dynamic hint}) {
return handler.executeNormal(NormalTask( return handler.executeNormal(NormalTask(
callFfi: (port_) { callFfi: (port_) {
var arg0 = var arg0 =
cst_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk( cst_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(
that); that);
return wire.wire__crate__bindings__BindingLiquidSdk_backup(port_, arg0); var arg1 = cst_encode_box_autoadd_backup_request(req);
return wire.wire__crate__bindings__BindingLiquidSdk_backup(port_, arg0, arg1);
}, },
codec: DcoCodec( codec: DcoCodec(
decodeSuccessData: dco_decode_unit, decodeSuccessData: dco_decode_unit,
decodeErrorData: dco_decode_liquid_sdk_error, decodeErrorData: dco_decode_liquid_sdk_error,
), ),
constMeta: kCrateBindingsBindingLiquidSdkBackupConstMeta, constMeta: kCrateBindingsBindingLiquidSdkBackupConstMeta,
argValues: [that], argValues: [that, req],
apiImpl: this, apiImpl: this,
hint: hint, hint: hint,
)); ));
@@ -161,7 +164,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
TaskConstMeta get kCrateBindingsBindingLiquidSdkBackupConstMeta => const TaskConstMeta( TaskConstMeta get kCrateBindingsBindingLiquidSdkBackupConstMeta => const TaskConstMeta(
debugName: "BindingLiquidSdk_backup", debugName: "BindingLiquidSdk_backup",
argNames: ["that"], argNames: ["that", "req"],
); );
@override @override
@@ -467,12 +470,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return raw as String; return raw as String;
} }
@protected
BackupRequest dco_decode_backup_request(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
final arr = raw as List<dynamic>;
if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}');
return BackupRequest(
backupPath: dco_decode_opt_String(arr[0]),
);
}
@protected @protected
bool dco_decode_bool(dynamic raw) { bool dco_decode_bool(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs // Codec=Dco (DartCObject based), see doc to use other codecs
return raw as bool; return raw as bool;
} }
@protected
BackupRequest dco_decode_box_autoadd_backup_request(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return dco_decode_backup_request(raw);
}
@protected @protected
ConnectRequest dco_decode_box_autoadd_connect_request(dynamic raw) { ConnectRequest dco_decode_box_autoadd_connect_request(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs // Codec=Dco (DartCObject based), see doc to use other codecs
@@ -860,12 +879,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return utf8.decoder.convert(inner); return utf8.decoder.convert(inner);
} }
@protected
BackupRequest sse_decode_backup_request(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var var_backupPath = sse_decode_opt_String(deserializer);
return BackupRequest(backupPath: var_backupPath);
}
@protected @protected
bool sse_decode_bool(SseDeserializer deserializer) { bool sse_decode_bool(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs // Codec=Sse (Serialization based), see doc to use other codecs
return deserializer.buffer.getUint8() != 0; return deserializer.buffer.getUint8() != 0;
} }
@protected
BackupRequest sse_decode_box_autoadd_backup_request(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
return (sse_decode_backup_request(deserializer));
}
@protected @protected
ConnectRequest sse_decode_box_autoadd_connect_request(SseDeserializer deserializer) { ConnectRequest sse_decode_box_autoadd_connect_request(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs // Codec=Sse (Serialization based), see doc to use other codecs
@@ -1324,12 +1356,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer);
} }
@protected
void sse_encode_backup_request(BackupRequest self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_opt_String(self.backupPath, serializer);
}
@protected @protected
void sse_encode_bool(bool self, SseSerializer serializer) { void sse_encode_bool(bool self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs // Codec=Sse (Serialization based), see doc to use other codecs
serializer.buffer.putUint8(self ? 1 : 0); serializer.buffer.putUint8(self ? 1 : 0);
} }
@protected
void sse_encode_box_autoadd_backup_request(BackupRequest self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_backup_request(self, serializer);
}
@protected @protected
void sse_encode_box_autoadd_connect_request(ConnectRequest self, SseSerializer serializer) { void sse_encode_box_autoadd_connect_request(ConnectRequest self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs // Codec=Sse (Serialization based), see doc to use other codecs

View File

@@ -43,9 +43,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected @protected
String dco_decode_String(dynamic raw); String dco_decode_String(dynamic raw);
@protected
BackupRequest dco_decode_backup_request(dynamic raw);
@protected @protected
bool dco_decode_bool(dynamic raw); bool dco_decode_bool(dynamic raw);
@protected
BackupRequest dco_decode_box_autoadd_backup_request(dynamic raw);
@protected @protected
ConnectRequest dco_decode_box_autoadd_connect_request(dynamic raw); ConnectRequest dco_decode_box_autoadd_connect_request(dynamic raw);
@@ -174,9 +180,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected @protected
String sse_decode_String(SseDeserializer deserializer); String sse_decode_String(SseDeserializer deserializer);
@protected
BackupRequest sse_decode_backup_request(SseDeserializer deserializer);
@protected @protected
bool sse_decode_bool(SseDeserializer deserializer); bool sse_decode_bool(SseDeserializer deserializer);
@protected
BackupRequest sse_decode_box_autoadd_backup_request(SseDeserializer deserializer);
@protected @protected
ConnectRequest sse_decode_box_autoadd_connect_request(SseDeserializer deserializer); ConnectRequest sse_decode_box_autoadd_connect_request(SseDeserializer deserializer);
@@ -299,6 +311,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
return cst_encode_list_prim_u_8_strict(utf8.encoder.convert(raw)); return cst_encode_list_prim_u_8_strict(utf8.encoder.convert(raw));
} }
@protected
ffi.Pointer<wire_cst_backup_request> cst_encode_box_autoadd_backup_request(BackupRequest raw) {
// Codec=Cst (C-struct based), see doc to use other codecs
final ptr = wire.cst_new_box_autoadd_backup_request();
cst_api_fill_to_wire_backup_request(raw, ptr.ref);
return ptr;
}
@protected @protected
ffi.Pointer<wire_cst_connect_request> cst_encode_box_autoadd_connect_request(ConnectRequest raw) { ffi.Pointer<wire_cst_connect_request> cst_encode_box_autoadd_connect_request(ConnectRequest raw) {
// Codec=Cst (C-struct based), see doc to use other codecs // Codec=Cst (C-struct based), see doc to use other codecs
@@ -409,6 +429,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
return raw.toInt(); return raw.toInt();
} }
@protected
void cst_api_fill_to_wire_backup_request(BackupRequest apiObj, wire_cst_backup_request wireObj) {
wireObj.backup_path = cst_encode_opt_String(apiObj.backupPath);
}
@protected
void cst_api_fill_to_wire_box_autoadd_backup_request(
BackupRequest apiObj, ffi.Pointer<wire_cst_backup_request> wireObj) {
cst_api_fill_to_wire_backup_request(apiObj, wireObj.ref);
}
@protected @protected
void cst_api_fill_to_wire_box_autoadd_connect_request( void cst_api_fill_to_wire_box_autoadd_connect_request(
ConnectRequest apiObj, ffi.Pointer<wire_cst_connect_request> wireObj) { ConnectRequest apiObj, ffi.Pointer<wire_cst_connect_request> wireObj) {
@@ -712,9 +743,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected @protected
void sse_encode_String(String self, SseSerializer serializer); void sse_encode_String(String self, SseSerializer serializer);
@protected
void sse_encode_backup_request(BackupRequest self, SseSerializer serializer);
@protected @protected
void sse_encode_bool(bool self, SseSerializer serializer); void sse_encode_bool(bool self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_backup_request(BackupRequest self, SseSerializer serializer);
@protected @protected
void sse_encode_box_autoadd_connect_request(ConnectRequest self, SseSerializer serializer); void sse_encode_box_autoadd_connect_request(ConnectRequest self, SseSerializer serializer);
@@ -882,18 +919,22 @@ class RustLibWire implements BaseWire {
void wire__crate__bindings__BindingLiquidSdk_backup( void wire__crate__bindings__BindingLiquidSdk_backup(
int port_, int port_,
int that, int that,
ffi.Pointer<wire_cst_backup_request> req,
) { ) {
return _wire__crate__bindings__BindingLiquidSdk_backup( return _wire__crate__bindings__BindingLiquidSdk_backup(
port_, port_,
that, that,
req,
); );
} }
late final _wire__crate__bindings__BindingLiquidSdk_backupPtr = late final _wire__crate__bindings__BindingLiquidSdk_backupPtr = _lookup<
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64, ffi.UintPtr)>>( ffi
'frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup'); .NativeFunction<ffi.Void Function(ffi.Int64, ffi.UintPtr, ffi.Pointer<wire_cst_backup_request>)>>(
'frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup');
late final _wire__crate__bindings__BindingLiquidSdk_backup = late final _wire__crate__bindings__BindingLiquidSdk_backup =
_wire__crate__bindings__BindingLiquidSdk_backupPtr.asFunction<void Function(int, int)>(); _wire__crate__bindings__BindingLiquidSdk_backupPtr
.asFunction<void Function(int, int, ffi.Pointer<wire_cst_backup_request>)>();
void wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache( void wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache(
int port_, int port_,
@@ -1111,6 +1152,16 @@ class RustLibWire implements BaseWire {
_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdkPtr _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdkPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>(); .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
ffi.Pointer<wire_cst_backup_request> cst_new_box_autoadd_backup_request() {
return _cst_new_box_autoadd_backup_request();
}
late final _cst_new_box_autoadd_backup_requestPtr =
_lookup<ffi.NativeFunction<ffi.Pointer<wire_cst_backup_request> Function()>>(
'frbgen_breez_liquid_cst_new_box_autoadd_backup_request');
late final _cst_new_box_autoadd_backup_request =
_cst_new_box_autoadd_backup_requestPtr.asFunction<ffi.Pointer<wire_cst_backup_request> Function()>();
ffi.Pointer<wire_cst_connect_request> cst_new_box_autoadd_connect_request() { ffi.Pointer<wire_cst_connect_request> cst_new_box_autoadd_connect_request() {
return _cst_new_box_autoadd_connect_request(); return _cst_new_box_autoadd_connect_request();
} }
@@ -1257,6 +1308,10 @@ final class wire_cst_list_prim_u_8_strict extends ffi.Struct {
external int len; external int len;
} }
final class wire_cst_backup_request extends ffi.Struct {
external ffi.Pointer<wire_cst_list_prim_u_8_strict> backup_path;
}
final class wire_cst_get_info_request extends ffi.Struct { final class wire_cst_get_info_request extends ffi.Struct {
@ffi.Bool() @ffi.Bool()
external bool with_scan; external bool with_scan;

View File

@@ -8,6 +8,26 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
import 'package:freezed_annotation/freezed_annotation.dart' hide protected; import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
part 'model.freezed.dart'; part 'model.freezed.dart';
class BackupRequest {
/// Path to the backup.
///
/// If not set, it defaults to `backup.sql` for mainnet and `backup-testnet.sql` for testnet.
/// The file will be saved in [ConnectRequest]'s `data_dir`.
final String? backupPath;
const BackupRequest({
this.backupPath,
});
@override
int get hashCode => backupPath.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is BackupRequest && runtimeType == other.runtimeType && backupPath == other.backupPath;
}
class ConnectRequest { class ConnectRequest {
final String mnemonic; final String mnemonic;
final String? dataDir; final String? dataDir;

View File

@@ -60,19 +60,22 @@ class FlutterBreezLiquidBindings {
void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup( void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup(
int port_, int port_,
int that, int that,
ffi.Pointer<wire_cst_backup_request> req,
) { ) {
return _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup( return _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup(
port_, port_,
that, that,
req,
); );
} }
late final _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backupPtr = late final _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backupPtr = _lookup<
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64, ffi.UintPtr)>>( ffi
'frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup'); .NativeFunction<ffi.Void Function(ffi.Int64, ffi.UintPtr, ffi.Pointer<wire_cst_backup_request>)>>(
'frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup');
late final _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup = late final _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backup =
_frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backupPtr _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backupPtr
.asFunction<void Function(int, int)>(); .asFunction<void Function(int, int, ffi.Pointer<wire_cst_backup_request>)>();
void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache( void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache(
int port_, int port_,
@@ -295,6 +298,17 @@ class FlutterBreezLiquidBindings {
_frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdkPtr _frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdkPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>(); .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
ffi.Pointer<wire_cst_backup_request> frbgen_breez_liquid_cst_new_box_autoadd_backup_request() {
return _frbgen_breez_liquid_cst_new_box_autoadd_backup_request();
}
late final _frbgen_breez_liquid_cst_new_box_autoadd_backup_requestPtr =
_lookup<ffi.NativeFunction<ffi.Pointer<wire_cst_backup_request> Function()>>(
'frbgen_breez_liquid_cst_new_box_autoadd_backup_request');
late final _frbgen_breez_liquid_cst_new_box_autoadd_backup_request =
_frbgen_breez_liquid_cst_new_box_autoadd_backup_requestPtr
.asFunction<ffi.Pointer<wire_cst_backup_request> Function()>();
ffi.Pointer<wire_cst_connect_request> frbgen_breez_liquid_cst_new_box_autoadd_connect_request() { ffi.Pointer<wire_cst_connect_request> frbgen_breez_liquid_cst_new_box_autoadd_connect_request() {
return _frbgen_breez_liquid_cst_new_box_autoadd_connect_request(); return _frbgen_breez_liquid_cst_new_box_autoadd_connect_request();
} }
@@ -464,6 +478,10 @@ final class wire_cst_list_prim_u_8_strict extends ffi.Struct {
external int len; external int len;
} }
final class wire_cst_backup_request extends ffi.Struct {
external ffi.Pointer<wire_cst_list_prim_u_8_strict> backup_path;
}
final class wire_cst_get_info_request extends ffi.Struct { final class wire_cst_get_info_request extends ffi.Struct {
@ffi.Bool() @ffi.Bool()
external bool with_scan; external bool with_scan;

View File

@@ -3,6 +3,37 @@ import breez_liquid_sdk.*
import com.facebook.react.bridge.* import com.facebook.react.bridge.*
import java.util.* import java.util.*
fun asBackupRequest(backupRequest: ReadableMap): BackupRequest? {
if (!validateMandatoryFields(
backupRequest,
arrayOf(),
)
) {
return null
}
val backupPath = if (hasNonNullKey(backupRequest, "backupPath")) backupRequest.getString("backupPath") else null
return BackupRequest(
backupPath,
)
}
fun readableMapOf(backupRequest: BackupRequest): ReadableMap {
return readableMapOf(
"backupPath" to backupRequest.backupPath,
)
}
fun asBackupRequestList(arr: ReadableArray): List<BackupRequest> {
val list = ArrayList<BackupRequest>()
for (value in arr.toArrayList()) {
when (value) {
is ReadableMap -> list.add(asBackupRequest(value)!!)
else -> throw LiquidSdkException.Generic(errUnexpectedType("${value::class.java.name}"))
}
}
return list
}
fun asConnectRequest(connectRequest: ReadableMap): ConnectRequest? { fun asConnectRequest(connectRequest: ReadableMap): ConnectRequest? {
if (!validateMandatoryFields( if (!validateMandatoryFields(
connectRequest, connectRequest,

View File

@@ -218,10 +218,17 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext
} }
@ReactMethod @ReactMethod
fun backup(promise: Promise) { fun backup(
req: ReadableMap,
promise: Promise,
) {
executor.execute { executor.execute {
try { try {
getBindingLiquidSdk().backup() val backupRequest =
asBackupRequest(
req,
) ?: run { throw LiquidSdkException.Generic(errMissingMandatoryField("req", "BackupRequest")) }
getBindingLiquidSdk().backup(backupRequest)
promise.resolve(readableMapOf("status" to "ok")) promise.resolve(readableMapOf("status" to "ok"))
} catch (e: Exception) { } catch (e: Exception) {
promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e) promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e)

View File

@@ -2,6 +2,42 @@ import BreezLiquidSDK
import Foundation import Foundation
enum BreezLiquidSDKMapper { enum BreezLiquidSDKMapper {
static func asBackupRequest(backupRequest: [String: Any?]) throws -> BackupRequest {
var backupPath: String?
if hasNonNilKey(data: backupRequest, key: "backupPath") {
guard let backupPathTmp = backupRequest["backupPath"] as? String else {
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "backupPath"))
}
backupPath = backupPathTmp
}
return BackupRequest(
backupPath: backupPath)
}
static func dictionaryOf(backupRequest: BackupRequest) -> [String: Any?] {
return [
"backupPath": backupRequest.backupPath == nil ? nil : backupRequest.backupPath,
]
}
static func asBackupRequestList(arr: [Any]) throws -> [BackupRequest] {
var list = [BackupRequest]()
for value in arr {
if let val = value as? [String: Any?] {
var backupRequest = try asBackupRequest(backupRequest: val)
list.append(backupRequest)
} else {
throw LiquidSdkError.Generic(message: errUnexpectedType(typeName: "BackupRequest"))
}
}
return list
}
static func arrayOf(backupRequestList: [BackupRequest]) -> [Any] {
return backupRequestList.map { v -> [String: Any?] in dictionaryOf(backupRequest: v) }
}
static func asConnectRequest(connectRequest: [String: Any?]) throws -> ConnectRequest { static func asConnectRequest(connectRequest: [String: Any?]) throws -> ConnectRequest {
guard let mnemonic = connectRequest["mnemonic"] as? String else { guard let mnemonic = connectRequest["mnemonic"] as? String else {
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "mnemonic", typeName: "ConnectRequest")) throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "mnemonic", typeName: "ConnectRequest"))

View File

@@ -61,7 +61,8 @@ RCT_EXTERN_METHOD(
) )
RCT_EXTERN_METHOD( RCT_EXTERN_METHOD(
backup: (RCTPromiseResolveBlock)resolve backup: (NSDictionary*)req
resolve: (RCTPromiseResolveBlock)resolve
reject: (RCTPromiseRejectBlock)reject reject: (RCTPromiseRejectBlock)reject
) )

View File

@@ -171,10 +171,11 @@ class RNBreezLiquidSDK: RCTEventEmitter {
} }
} }
@objc(backup:reject:) @objc(backup:resolve:reject:)
func backup(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { func backup(_ req: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
do { do {
try getBindingLiquidSdk().backup() let backupRequest = try BreezLiquidSDKMapper.asBackupRequest(backupRequest: req)
try getBindingLiquidSdk().backup(req: backupRequest)
resolve(["status": "ok"]) resolve(["status": "ok"])
} catch let err { } catch let err {
rejectErr(err: err, reject: reject) rejectErr(err: err, reject: reject)

View File

@@ -19,6 +19,10 @@ const BreezLiquidSDK = NativeModules.RNBreezLiquidSDK
const BreezLiquidSDKEmitter = new NativeEventEmitter(BreezLiquidSDK) const BreezLiquidSDKEmitter = new NativeEventEmitter(BreezLiquidSDK)
export interface BackupRequest {
backupPath?: string
}
export interface ConnectRequest { export interface ConnectRequest {
mnemonic: string mnemonic: string
network: Network network: Network
@@ -179,8 +183,8 @@ export const sync = async (): Promise<void> => {
await BreezLiquidSDK.sync() await BreezLiquidSDK.sync()
} }
export const backup = async (): Promise<void> => { export const backup = async (req: BackupRequest): Promise<void> => {
await BreezLiquidSDK.backup() await BreezLiquidSDK.backup(req)
} }
export const restore = async (req: RestoreRequest): Promise<void> => { export const restore = async (req: RestoreRequest): Promise<void> => {