From 708a3526c70470da2121f32ca5bd557a1d1fd386 Mon Sep 17 00:00:00 2001 From: ok300 <106775972+ok300@users.noreply.github.com> Date: Fri, 3 May 2024 08:48:03 +0000 Subject: [PATCH] Add request, response to API methods (#153) * Add request, response to get_info() * Add request, response to prepare_send_payment() * Add request, response to restore() * Add request, response to connect() * Update lib/bindings/src/breez_liquid_sdk.udl Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com> * Update lib/bindings/src/breez_liquid_sdk.udl Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com> * Update lib/core/src/bindings.rs Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com> * Fix bindings.rs call * Update connect to handle ConnectRequest --------- Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com> Co-authored-by: Ross Savage --- cli/src/commands.rs | 10 +- cli/src/main.rs | 8 +- .../src/gen_kotlin/templates/module.kt | 8 +- .../src/gen_swift/templates/extern.m | 4 +- .../src/gen_swift/templates/module.swift | 10 +- .../src/gen_typescript/templates/Helpers.ts | 4 +- lib/bindings/src/breez_liquid_sdk.udl | 28 ++- lib/bindings/src/lib.rs | 29 +-- .../tests/bindings/test_breez_liquid_sdk.kts | 9 +- .../tests/bindings/test_breez_liquid_sdk.py | 9 +- .../bindings/test_breez_liquid_sdk.swift | 9 +- lib/core/src/bindings.rs | 21 +- lib/core/src/model.rs | 26 +- lib/core/src/wallet.rs | 72 +++--- .../breezliquidsdk/BreezLiquidSDKMapper.kt | 211 ++++++++++++++--- .../breezliquidsdk/BreezLiquidSDKModule.kt | 40 +++- .../ios/BreezLiquidSDKMapper.swift | 224 +++++++++++++++--- packages/react-native/ios/RNBreezLiquidSDK.m | 10 +- .../react-native/ios/RNBreezLiquidSDK.swift | 28 ++- packages/react-native/src/index.ts | 44 +++- 20 files changed, 581 insertions(+), 223 deletions(-) diff --git a/cli/src/commands.rs b/cli/src/commands.rs index aad4fe8..3c8a1f4 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -5,7 +5,8 @@ use std::thread; use std::time::Duration; use anyhow::Result; -use breez_liquid_sdk::{model::PrepareReceiveRequest, wallet::Wallet}; +use breez_liquid_sdk::model::*; +use breez_liquid_sdk::wallet::Wallet; use clap::{arg, Parser}; use qrcode_rs::render::unicode; use qrcode_rs::{EcLevel, QrCode}; @@ -115,7 +116,8 @@ pub(crate) fn handle_command( result } Command::SendPayment { bolt11, delay } => { - let prepare_response = wallet.prepare_send_payment(&bolt11)?; + let prepare_response = + wallet.prepare_send_payment(PrepareSendRequest { invoice: bolt11 })?; wait_confirmation!( format!( @@ -140,7 +142,7 @@ pub(crate) fn handle_command( } } Command::GetInfo => { - command_result!(wallet.get_info(true)?) + command_result!(wallet.get_info(GetInfoRequest { with_scan: true })?) } Command::ListPayments => { let mut payments = wallet.list_payments(true, true)?; @@ -156,7 +158,7 @@ pub(crate) fn handle_command( command_result!("Backup created successfully!") } Command::Restore { backup_path } => { - wallet.restore(backup_path)?; + wallet.restore(RestoreRequest { backup_path })?; command_result!("Backup restored successfully!") } }) diff --git a/cli/src/main.rs b/cli/src/main.rs index 10256d4..c9d8eeb 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -8,7 +8,7 @@ use std::{ use anyhow::{anyhow, Result}; use breez_liquid_sdk::{ - model::Network, + model::*, wallet::{Wallet, DEFAULT_DATA_DIR}, }; use clap::Parser; @@ -82,7 +82,11 @@ fn main() -> Result<()> { let mnemonic = persistence.get_or_create_mnemonic()?; let network = args.network.unwrap_or(Network::LiquidTestnet); - let wallet = Wallet::connect(&mnemonic.to_string(), Some(data_dir_str), network)?; + let wallet = Wallet::connect(ConnectRequest { + mnemonic: mnemonic.to_string(), + data_dir: Some(data_dir_str), + network, + })?; let cli_prompt = match network { Network::Liquid => "breez-liquid-cli [mainnet]> ", diff --git a/lib/bindings/bindings-react-native/src/gen_kotlin/templates/module.kt b/lib/bindings/bindings-react-native/src/gen_kotlin/templates/module.kt index 255284f..dd80993 100644 --- a/lib/bindings/bindings-react-native/src/gen_kotlin/templates/module.kt +++ b/lib/bindings/bindings-react-native/src/gen_kotlin/templates/module.kt @@ -50,7 +50,7 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext {%- endfor %} @ReactMethod - fun connect(mnemonic: String, dataDir: String, network: String, promise: Promise) { + fun connect(req: ReadableMap, promise: Promise) { if (bindingWallet != null) { promise.reject("Generic", "Already initialized") return @@ -58,9 +58,9 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext executor.execute { try { - val dataDirTmp = dataDir.takeUnless { it.isEmpty() } ?: run { reactApplicationContext.filesDir.toString() + "/breezLiquidSdk" } - val networkTmp = asNetwork(network) - bindingWallet = connect(mnemonic, dataDirTmp, networkTmp) + var connectRequest = asConnectRequest(req) ?: run { throw LsSdkException.Generic(errMissingMandatoryField("req", "ConnectRequest")) } + connectRequest.dataDir = connectRequest.dataDir.takeUnless { it.isEmpty() } ?: run { reactApplicationContext.filesDir.toString() + "/breezLiquidSdk" } + bindingWallet = connect(connectRequest) promise.resolve(readableMapOf("status" to "ok")) } catch (e: Exception) { promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e) diff --git a/lib/bindings/bindings-react-native/src/gen_swift/templates/extern.m b/lib/bindings/bindings-react-native/src/gen_swift/templates/extern.m index 57878f3..691f204 100644 --- a/lib/bindings/bindings-react-native/src/gen_swift/templates/extern.m +++ b/lib/bindings/bindings-react-native/src/gen_swift/templates/extern.m @@ -8,9 +8,7 @@ {% endif %} {%- endfor %} RCT_EXTERN_METHOD( - connect: (NSString*)mnemonic - dataDir: (NSString*)dataDir - network: (NSString*)network + connect: (NSDictionary*)req resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) diff --git a/lib/bindings/bindings-react-native/src/gen_swift/templates/module.swift b/lib/bindings/bindings-react-native/src/gen_swift/templates/module.swift index 09dc2e6..013999c 100644 --- a/lib/bindings/bindings-react-native/src/gen_swift/templates/module.swift +++ b/lib/bindings/bindings-react-native/src/gen_swift/templates/module.swift @@ -57,17 +57,17 @@ class RNBreezLiquidSDK: RCTEventEmitter { {% include "TopLevelFunctionTemplate.swift" %} {% endif -%} {%- endfor %} - @objc(connect:dataDir:network:resolve:reject:) - func connect(_ mnemonic: String, dataDir: String, network: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { + @objc(connect:resolve:reject:) + func connect(_ req:[String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { if bindingWallet != nil { reject("Generic", "Already initialized", nil) return } do { - let dataDirTmp = dataDir.isEmpty ? RNBreezLiquidSDK.defaultDataDir.path : dataDir - let networkTmp = try BreezLiquidSDKMapper.asNetwork(network: network) - bindingWallet = try BreezLiquidSDK.connect(mnemonic: mnemonic, dataDir: dataDirTmp, network: networkTmp) + var connectRequest = try BreezLiquidSDKMapper.asConnectRequest(connectRequest: req) + connectRequest.dataDir = connectRequest.dataDir.isEmpty ? RNBreezLiquidSDK.defaultDataDir.path : connectRequest.dataDir + bindingWallet = try BreezLiquidSDK.connect(req: connectRequest) resolve(["status": "ok"]) } catch let err { rejectErr(err: err, reject: reject) diff --git a/lib/bindings/bindings-react-native/src/gen_typescript/templates/Helpers.ts b/lib/bindings/bindings-react-native/src/gen_typescript/templates/Helpers.ts index 49d13dd..939f580 100644 --- a/lib/bindings/bindings-react-native/src/gen_typescript/templates/Helpers.ts +++ b/lib/bindings/bindings-react-native/src/gen_typescript/templates/Helpers.ts @@ -1,5 +1,5 @@ -export const connect = async (mnemonic: string, dataDir: string = "", network: Network): Promise => { - const response = await BreezLiquidSDK.connect(mnemonic, dataDir, network) +export const connect = async (req: ConnectRequest): Promise => { + const response = await BreezLiquidSDK.connect(req) return response } diff --git a/lib/bindings/src/breez_liquid_sdk.udl b/lib/bindings/src/breez_liquid_sdk.udl index de24773..1803bf4 100644 --- a/lib/bindings/src/breez_liquid_sdk.udl +++ b/lib/bindings/src/breez_liquid_sdk.udl @@ -22,11 +22,25 @@ enum Network { "LiquidTestnet", }; -dictionary WalletInfo { +dictionary ConnectRequest { + string mnemonic; + string? data_dir = null; + Network network; +}; + +dictionary GetInfoRequest { + boolean with_scan; +}; + +dictionary GetInfoResponse { u64 balance_sat; string pubkey; }; +dictionary PrepareSendRequest { + string invoice; +}; + dictionary PrepareSendResponse { string id; u64 payer_amount_sat; @@ -55,17 +69,21 @@ dictionary ReceivePaymentResponse { string invoice; }; +dictionary RestoreRequest { + string? backup_path = null; +}; + namespace breez_liquid_sdk { [Throws=LsSdkError] - BindingWallet connect(string mnemonic, string? data_dir, Network network); + BindingWallet connect(ConnectRequest req); }; interface BindingWallet { [Throws=LsSdkError] - WalletInfo get_info(boolean with_scan); + GetInfoResponse get_info(GetInfoRequest req); [Throws=PaymentError] - PrepareSendResponse prepare_send_payment(string invoice); + PrepareSendResponse prepare_send_payment(PrepareSendRequest req); [Throws=PaymentError] SendPaymentResponse send_payment(PrepareSendResponse req); @@ -80,5 +98,5 @@ interface BindingWallet { void backup(); [Throws=LsSdkError] - void restore(string? backup_path); + void restore(RestoreRequest req); }; diff --git a/lib/bindings/src/lib.rs b/lib/bindings/src/lib.rs index 5bdd08e..f25a952 100644 --- a/lib/bindings/src/lib.rs +++ b/lib/bindings/src/lib.rs @@ -1,14 +1,7 @@ use std::sync::Arc; use anyhow::{Error, Result}; -use breez_liquid_sdk::{ - error::PaymentError, - model::{ - Network, PrepareReceiveRequest, PrepareReceiveResponse, PrepareSendResponse, - ReceivePaymentResponse, SendPaymentResponse, WalletInfo, - }, - wallet::Wallet, -}; +use breez_liquid_sdk::{error::PaymentError, model::*, wallet::Wallet}; // TODO Unify error enum #[derive(Debug, thiserror::Error)] @@ -23,12 +16,8 @@ impl From for LsSdkError { } } -pub fn connect( - mnemonic: String, - data_dir: Option, - network: Network, -) -> Result, LsSdkError> { - let ln_sdk = Wallet::connect(&mnemonic, data_dir, network)?; +pub fn connect(req: ConnectRequest) -> Result, LsSdkError> { + let ln_sdk = Wallet::connect(req)?; Ok(Arc::from(BindingWallet { ln_sdk })) } @@ -37,15 +26,15 @@ pub struct BindingWallet { } impl BindingWallet { - pub fn get_info(&self, with_scan: bool) -> Result { - self.ln_sdk.get_info(with_scan).map_err(Into::into) + pub fn get_info(&self, req: GetInfoRequest) -> Result { + self.ln_sdk.get_info(req).map_err(Into::into) } pub fn prepare_send_payment( &self, - invoice: String, + req: PrepareSendRequest, ) -> Result { - self.ln_sdk.prepare_send_payment(&invoice) + self.ln_sdk.prepare_send_payment(req) } pub fn send_payment( @@ -73,8 +62,8 @@ impl BindingWallet { self.ln_sdk.backup().map_err(Into::into) } - pub fn restore(&self, backup_path: Option) -> Result<(), LsSdkError> { - self.ln_sdk.restore(backup_path).map_err(Into::into) + pub fn restore(&self, req: RestoreRequest) -> Result<(), LsSdkError> { + self.ln_sdk.restore(req).map_err(Into::into) } } diff --git a/lib/bindings/tests/bindings/test_breez_liquid_sdk.kts b/lib/bindings/tests/bindings/test_breez_liquid_sdk.kts index 1aaee3f..8b41d09 100644 --- a/lib/bindings/tests/bindings/test_breez_liquid_sdk.kts +++ b/lib/bindings/tests/bindings/test_breez_liquid_sdk.kts @@ -1,7 +1,12 @@ try { var mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" - var sdk = breez_liquid_sdk.connect(mnemonic, null, breez_liquid_sdk.Network.LIQUID_TESTNET) - var nodeInfo = sdk.getInfo(false) + + var connectReq = breez_liquid_sdk.ConnectRequest(mnemonic, null, breez_liquid_sdk.Network.LIQUID_TESTNET) + var sdk = breez_liquid_sdk.connect(connectReq) + + var getInfoReq = breez_liquid_sdk.GetInfoRequest(false) + var nodeInfo = sdk.getInfo(getInfoReq) + println("$nodeInfo") assert(nodeInfo.pubkey.equals("03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494")) } catch (ex: Exception) { diff --git a/lib/bindings/tests/bindings/test_breez_liquid_sdk.py b/lib/bindings/tests/bindings/test_breez_liquid_sdk.py index 2367783..7b87fe7 100644 --- a/lib/bindings/tests/bindings/test_breez_liquid_sdk.py +++ b/lib/bindings/tests/bindings/test_breez_liquid_sdk.py @@ -2,8 +2,13 @@ import breez_liquid_sdk def test(): mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" - sdk = breez_liquid_sdk.connect(mnemonic, None, breez_liquid_sdk.Network.LIQUID_TESTNET) - node_info = sdk.get_info(False) + + connect_req = breez_liquid_sdk.ConnectRequest(mnemonic = mnemonic, data_dir = None, network = breez_liquid_sdk.Network.LIQUID_TESTNET) + sdk = breez_liquid_sdk.connect(connect_req) + + get_info_req = breez_liquid_sdk.GetInfoRequest(with_scan = False) + node_info = sdk.get_info(get_info_req) + print(node_info) assert node_info.pubkey == "03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494" diff --git a/lib/bindings/tests/bindings/test_breez_liquid_sdk.swift b/lib/bindings/tests/bindings/test_breez_liquid_sdk.swift index 9ee4bfa..fa8022d 100644 --- a/lib/bindings/tests/bindings/test_breez_liquid_sdk.swift +++ b/lib/bindings/tests/bindings/test_breez_liquid_sdk.swift @@ -1,7 +1,12 @@ import breez_liquid_sdk let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; -let sdk = try breez_liquid_sdk.connect(mnemonic: mnemonic, dataDir: nil, network: .liquidTestnet); -let nodeInfo = try sdk.getInfo(withScan: false); + +let connectReq = breez_liquid_sdk.ConnectRequest(mnemonic: mnemonic, dataDir: nil, network: .liquidTestnet); +let sdk = try breez_liquid_sdk.connect(req: connectReq); + +let getInfoReq = breez_liquid_sdk.GetInfoRequest(withScan: false); +let nodeInfo = try sdk.getInfo(req: getInfoReq); + print(nodeInfo); assert(nodeInfo.pubkey == "03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494", "nodeInfo.pubkey"); \ No newline at end of file diff --git a/lib/core/src/bindings.rs b/lib/core/src/bindings.rs index 8cc8c23..278217b 100644 --- a/lib/core/src/bindings.rs +++ b/lib/core/src/bindings.rs @@ -4,10 +4,7 @@ use std::sync::{Arc, OnceLock}; use crate::{ error::{LsSdkError, PaymentError}, - model::{ - Network, PrepareReceiveRequest, PrepareReceiveResponse, PrepareSendResponse, - ReceivePaymentResponse, SendPaymentResponse, WalletInfo, - }, + model::*, wallet::Wallet, }; @@ -15,25 +12,25 @@ use super::model::Payment; static WALLET_INSTANCE: OnceLock> = OnceLock::new(); -pub fn connect(mnemonic: String, data_dir: Option, network: Network) -> Result<()> { - let wallet = Wallet::connect(&mnemonic, data_dir, network)?; +pub fn connect(req: ConnectRequest) -> Result<()> { + let wallet = Wallet::connect(req)?; WALLET_INSTANCE.get_or_init(|| wallet); Ok(()) } -pub fn get_info(with_scan: bool) -> Result { +pub fn get_info(req: GetInfoRequest) -> Result { WALLET_INSTANCE .get() .ok_or(anyhow!("Not initialized"))? - .get_info(with_scan) + .get_info(req) } -pub fn prepare_send_payment(invoice: String) -> Result { +pub fn prepare_send_payment(req: PrepareSendRequest) -> Result { WALLET_INSTANCE .get() .ok_or(anyhow!("Not initialized")) .map_err(|e| LsSdkError::Generic { err: e.to_string() })? - .prepare_send_payment(&invoice) + .prepare_send_payment(req) } pub fn send_payment(req: PrepareSendResponse) -> Result { @@ -96,10 +93,10 @@ pub fn backup() -> Result<()> { .backup() } -pub fn restore(backup_path: Option) -> Result<()> { +pub fn restore(req: RestoreRequest) -> Result<()> { WALLET_INSTANCE .get() .ok_or(anyhow!("Not initialized")) .map_err(|e| LsSdkError::Generic { err: e.to_string() })? - .restore(backup_path) + .restore(req) } diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs index 229ade2..d07f77c 100644 --- a/lib/core/src/model.rs +++ b/lib/core/src/model.rs @@ -7,7 +7,7 @@ use serde::Serialize; use crate::get_invoice_amount; -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize)] pub enum Network { Liquid, LiquidTestnet, @@ -72,6 +72,13 @@ impl WalletOptions { } } +#[derive(Debug, Serialize)] +pub struct ConnectRequest { + pub mnemonic: String, + pub data_dir: Option, + pub network: Network, +} + #[derive(Debug, Serialize)] pub struct PrepareReceiveRequest { pub payer_amount_sat: u64, @@ -90,6 +97,11 @@ pub struct ReceivePaymentResponse { pub invoice: String, } +#[derive(Debug, Serialize, Clone)] +pub struct PrepareSendRequest { + pub invoice: String, +} + #[derive(Debug, Serialize, Clone)] pub struct PrepareSendResponse { pub id: String, @@ -106,11 +118,21 @@ pub struct SendPaymentResponse { } #[derive(Debug, Serialize)] -pub struct WalletInfo { +pub struct GetInfoRequest { + pub with_scan: bool, +} + +#[derive(Debug, Serialize)] +pub struct GetInfoResponse { pub balance_sat: u64, pub pubkey: String, } +#[derive(Debug, Serialize)] +pub struct RestoreRequest { + pub backup_path: Option, +} + #[derive(Debug)] pub(crate) enum OngoingSwap { Send { diff --git a/lib/core/src/wallet.rs b/lib/core/src/wallet.rs index 80e8d30..0684554 100644 --- a/lib/core/src/wallet.rs +++ b/lib/core/src/wallet.rs @@ -29,17 +29,7 @@ use lwk_wollet::{ ElementsNetwork, FsPersister, Wollet as LwkWollet, WolletDescriptor, }; -use crate::{ - ensure_sdk, - error::PaymentError, - get_invoice_amount, - model::{ - Network, OngoingSwap, Payment, PaymentData, PaymentType, PrepareReceiveRequest, - PrepareReceiveResponse, PrepareSendResponse, ReceivePaymentResponse, SendPaymentResponse, - WalletInfo, WalletOptions, - }, - persist::Persister, -}; +use crate::{ensure_sdk, error::PaymentError, get_invoice_amount, model::*, persist::Persister}; /// Claim tx feerate for Receive, in sats per vbyte. /// Since the Liquid blocks are consistently empty for now, we hardcode the minimum feerate. @@ -58,21 +48,17 @@ pub struct Wallet { } impl Wallet { - pub fn connect( - mnemonic: &str, - data_dir: Option, - network: Network, - ) -> Result> { - let is_mainnet = network == Network::Liquid; - let signer = SwSigner::new(mnemonic, is_mainnet)?; - let descriptor = Wallet::get_descriptor(&signer, network)?; + pub fn connect(req: ConnectRequest) -> Result> { + let is_mainnet = req.network == Network::Liquid; + let signer = SwSigner::new(&req.mnemonic, is_mainnet)?; + let descriptor = Wallet::get_descriptor(&signer, req.network)?; Wallet::new(WalletOptions { signer, descriptor, electrum_url: None, - data_dir_path: data_dir, - network, + data_dir_path: req.data_dir, + network: req.network, }) } @@ -268,11 +254,11 @@ impl Wallet { Ok(balance.values().sum()) } - pub fn get_info(&self, with_scan: bool) -> Result { + pub fn get_info(&self, req: GetInfoRequest) -> Result { debug!("active_address: {}", self.address()?); - Ok(WalletInfo { - balance_sat: self.total_balance_sat(with_scan)?, + Ok(GetInfoResponse { + balance_sat: self.total_balance_sat(req.with_scan)?, pubkey: self.signer.xpub().public_key.to_string(), }) } @@ -313,9 +299,13 @@ impl Wallet { Ok(wallet.finalize(&mut pset)?) } - pub fn prepare_send_payment(&self, invoice: &str) -> Result { + pub fn prepare_send_payment( + &self, + req: PrepareSendRequest, + ) -> Result { let client = self.boltz_client(); - let invoice = invoice + let invoice = req + .invoice .trim() .parse::() .map_err(|_| PaymentError::InvalidInvoice)?; @@ -588,8 +578,8 @@ impl Wallet { Ok(()) } - pub fn restore(&self, backup_path: Option) -> Result<()> { - let backup_path = match backup_path { + 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(), }; @@ -606,7 +596,8 @@ mod tests { use anyhow::Result; use tempdir::TempDir; - use crate::{wallet::Wallet, Network, Payment, PaymentType, PrepareReceiveRequest, Wallet}; + use crate::model::*; + use crate::wallet::{Network, Wallet}; const TEST_MNEMONIC: &str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; @@ -629,18 +620,21 @@ mod tests { .filter(|p| { [PaymentType::PendingSend, PaymentType::PendingReceive].contains(&p.payment_type) }) - .map(|p| p.clone()) + .cloned() .collect()) } #[test] fn normal_submarine_swap() -> Result<()> { let (_data_dir, data_dir_str) = create_temp_dir()?; - let breez_wallet = - Wallet::connect(TEST_MNEMONIC, Some(data_dir_str), Network::LiquidTestnet)?; + let breez_wallet = Wallet::connect(ConnectRequest { + mnemonic: TEST_MNEMONIC.to_string(), + data_dir: Some(data_dir_str), + network: Network::LiquidTestnet, + })?; - let invoice = "lntb10u1pnqwkjrpp5j8ucv9mgww0ajk95yfpvuq0gg5825s207clrzl5thvtuzfn68h0sdqqcqzzsxqr23srzjqv8clnrfs9keq3zlg589jvzpw87cqh6rjks0f9g2t9tvuvcqgcl45f6pqqqqqfcqqyqqqqlgqqqqqqgq2qsp5jnuprlxrargr6hgnnahl28nvutj3gkmxmmssu8ztfhmmey3gq2ss9qyyssq9ejvcp6frwklf73xvskzdcuhnnw8dmxag6v44pffwqrxznsly4nqedem3p3zhn6u4ln7k79vk6zv55jjljhnac4gnvr677fyhfgn07qp4x6wrq"; - breez_wallet.prepare_send_payment(&invoice)?; + let invoice = "lntb10u1pnqwkjrpp5j8ucv9mgww0ajk95yfpvuq0gg5825s207clrzl5thvtuzfn68h0sdqqcqzzsxqr23srzjqv8clnrfs9keq3zlg589jvzpw87cqh6rjks0f9g2t9tvuvcqgcl45f6pqqqqqfcqqyqqqqlgqqqqqqgq2qsp5jnuprlxrargr6hgnnahl28nvutj3gkmxmmssu8ztfhmmey3gq2ss9qyyssq9ejvcp6frwklf73xvskzdcuhnnw8dmxag6v44pffwqrxznsly4nqedem3p3zhn6u4ln7k79vk6zv55jjljhnac4gnvr677fyhfgn07qp4x6wrq".to_string(); + breez_wallet.prepare_send_payment(PrepareSendRequest { invoice })?; assert!(!list_pending(&breez_wallet)?.is_empty()); Ok(()) @@ -649,12 +643,14 @@ mod tests { #[test] fn reverse_submarine_swap() -> Result<()> { let (_data_dir, data_dir_str) = create_temp_dir()?; - let breez_wallet = - Wallet::connect(TEST_MNEMONIC, Some(data_dir_str), Network::LiquidTestnet)?; + let breez_wallet = Wallet::connect(ConnectRequest { + mnemonic: TEST_MNEMONIC.to_string(), + data_dir: Some(data_dir_str), + network: Network::LiquidTestnet, + })?; let prepare_response = breez_wallet.prepare_receive_payment(&PrepareReceiveRequest { - receiver_amount_sat: Some(1000), - payer_amount_sat: None, + payer_amount_sat: 1_000, })?; breez_wallet.receive_payment(&prepare_response)?; assert!(!list_pending(&breez_wallet)?.is_empty()); diff --git a/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKMapper.kt b/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKMapper.kt index d9fc547..1653464 100644 --- a/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKMapper.kt +++ b/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKMapper.kt @@ -3,6 +3,116 @@ import breez_liquid_sdk.* import com.facebook.react.bridge.* import java.util.* +fun asConnectRequest(connectRequest: ReadableMap): ConnectRequest? { + if (!validateMandatoryFields( + connectRequest, + arrayOf( + "mnemonic", + "network", + ), + ) + ) { + return null + } + val mnemonic = connectRequest.getString("mnemonic")!! + val dataDir = if (hasNonNullKey(connectRequest, "dataDir")) connectRequest.getString("dataDir") else null + val network = connectRequest.getString("network")?.let { asNetwork(it) }!! + return ConnectRequest( + mnemonic, + dataDir, + network, + ) +} + +fun readableMapOf(connectRequest: ConnectRequest): ReadableMap { + return readableMapOf( + "mnemonic" to connectRequest.mnemonic, + "dataDir" to connectRequest.dataDir, + "network" to connectRequest.network.name.lowercase(), + ) +} + +fun asConnectRequestList(arr: ReadableArray): List { + val list = ArrayList() + for (value in arr.toArrayList()) { + when (value) { + is ReadableMap -> list.add(asConnectRequest(value)!!) + else -> throw LsSdkException.Generic(errUnexpectedType("${value::class.java.name}")) + } + } + return list +} + +fun asGetInfoRequest(getInfoRequest: ReadableMap): GetInfoRequest? { + if (!validateMandatoryFields( + getInfoRequest, + arrayOf( + "withScan", + ), + ) + ) { + return null + } + val withScan = getInfoRequest.getBoolean("withScan") + return GetInfoRequest( + withScan, + ) +} + +fun readableMapOf(getInfoRequest: GetInfoRequest): ReadableMap { + return readableMapOf( + "withScan" to getInfoRequest.withScan, + ) +} + +fun asGetInfoRequestList(arr: ReadableArray): List { + val list = ArrayList() + for (value in arr.toArrayList()) { + when (value) { + is ReadableMap -> list.add(asGetInfoRequest(value)!!) + else -> throw LsSdkException.Generic(errUnexpectedType("${value::class.java.name}")) + } + } + return list +} + +fun asGetInfoResponse(getInfoResponse: ReadableMap): GetInfoResponse? { + if (!validateMandatoryFields( + getInfoResponse, + arrayOf( + "balanceSat", + "pubkey", + ), + ) + ) { + return null + } + val balanceSat = getInfoResponse.getDouble("balanceSat").toULong() + val pubkey = getInfoResponse.getString("pubkey")!! + return GetInfoResponse( + balanceSat, + pubkey, + ) +} + +fun readableMapOf(getInfoResponse: GetInfoResponse): ReadableMap { + return readableMapOf( + "balanceSat" to getInfoResponse.balanceSat, + "pubkey" to getInfoResponse.pubkey, + ) +} + +fun asGetInfoResponseList(arr: ReadableArray): List { + val list = ArrayList() + for (value in arr.toArrayList()) { + when (value) { + is ReadableMap -> list.add(asGetInfoResponse(value)!!) + else -> throw LsSdkException.Generic(errUnexpectedType("${value::class.java.name}")) + } + } + return list +} + fun asPrepareReceiveRequest(prepareReceiveRequest: ReadableMap): PrepareReceiveRequest? { if (!validateMandatoryFields( prepareReceiveRequest, @@ -77,6 +187,39 @@ fun asPrepareReceiveResponseList(arr: ReadableArray): List { + val list = ArrayList() + for (value in arr.toArrayList()) { + when (value) { + is ReadableMap -> list.add(asPrepareSendRequest(value)!!) + else -> throw LsSdkException.Generic(errUnexpectedType("${value::class.java.name}")) + } + } + return list +} + fun asPrepareSendResponse(prepareSendResponse: ReadableMap): PrepareSendResponse? { if (!validateMandatoryFields( prepareSendResponse, @@ -167,6 +310,37 @@ fun asReceivePaymentResponseList(arr: ReadableArray): List { + val list = ArrayList() + for (value in arr.toArrayList()) { + when (value) { + is ReadableMap -> list.add(asRestoreRequest(value)!!) + else -> throw LsSdkException.Generic(errUnexpectedType("${value::class.java.name}")) + } + } + return list +} + fun asSendPaymentResponse(sendPaymentResponse: ReadableMap): SendPaymentResponse? { if (!validateMandatoryFields( sendPaymentResponse, @@ -200,43 +374,6 @@ fun asSendPaymentResponseList(arr: ReadableArray): List { return list } -fun asWalletInfo(walletInfo: ReadableMap): WalletInfo? { - if (!validateMandatoryFields( - walletInfo, - arrayOf( - "balanceSat", - "pubkey", - ), - ) - ) { - return null - } - val balanceSat = walletInfo.getDouble("balanceSat").toULong() - val pubkey = walletInfo.getString("pubkey")!! - return WalletInfo( - balanceSat, - pubkey, - ) -} - -fun readableMapOf(walletInfo: WalletInfo): ReadableMap { - return readableMapOf( - "balanceSat" to walletInfo.balanceSat, - "pubkey" to walletInfo.pubkey, - ) -} - -fun asWalletInfoList(arr: ReadableArray): List { - val list = ArrayList() - for (value in arr.toArrayList()) { - when (value) { - is ReadableMap -> list.add(asWalletInfo(value)!!) - else -> throw LsSdkException.Generic(errUnexpectedType("${value::class.java.name}")) - } - } - return list -} - fun asNetwork(type: String): Network { return Network.valueOf(type.uppercase()) } diff --git a/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKModule.kt b/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKModule.kt index 7a43f15..7b14e8d 100644 --- a/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKModule.kt +++ b/packages/react-native/android/src/main/java/com/breezliquidsdk/BreezLiquidSDKModule.kt @@ -41,9 +41,7 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext @ReactMethod fun connect( - mnemonic: String, - dataDir: String, - network: String, + req: ReadableMap, promise: Promise, ) { if (bindingWallet != null) { @@ -53,9 +51,14 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext executor.execute { try { - val dataDirTmp = dataDir.takeUnless { it.isEmpty() } ?: run { reactApplicationContext.filesDir.toString() + "/breezLiquidSdk" } - val networkTmp = asNetwork(network) - bindingWallet = connect(mnemonic, dataDirTmp, networkTmp) + var connectRequest = + asConnectRequest( + req, + ) ?: run { throw LsSdkException.Generic(errMissingMandatoryField("req", "ConnectRequest")) } + connectRequest.dataDir = connectRequest.dataDir.takeUnless { + it.isEmpty() + } ?: run { reactApplicationContext.filesDir.toString() + "/breezLiquidSdk" } + bindingWallet = connect(connectRequest) promise.resolve(readableMapOf("status" to "ok")) } catch (e: Exception) { promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e) @@ -65,12 +68,16 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext @ReactMethod fun getInfo( - withScan: Boolean, + req: ReadableMap, promise: Promise, ) { executor.execute { try { - val res = getBindingWallet().getInfo(withScan) + val getInfoRequest = + asGetInfoRequest( + req, + ) ?: run { throw LsSdkException.Generic(errMissingMandatoryField("req", "GetInfoRequest")) } + val res = getBindingWallet().getInfo(getInfoRequest) promise.resolve(readableMapOf(res)) } catch (e: Exception) { promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e) @@ -80,12 +87,16 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext @ReactMethod fun prepareSendPayment( - invoice: String, + req: ReadableMap, promise: Promise, ) { executor.execute { try { - val res = getBindingWallet().prepareSendPayment(invoice) + val prepareSendRequest = + asPrepareSendRequest(req) ?: run { + throw LsSdkException.Generic(errMissingMandatoryField("req", "PrepareSendRequest")) + } + val res = getBindingWallet().prepareSendPayment(prepareSendRequest) promise.resolve(readableMapOf(res)) } catch (e: Exception) { promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e) @@ -164,13 +175,16 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext @ReactMethod fun restore( - backupPath: String, + req: ReadableMap, promise: Promise, ) { executor.execute { try { - val backupPathTmp = backupPath.takeUnless { it.isEmpty() } - getBindingWallet().restore(backupPathTmp) + val restoreRequest = + asRestoreRequest( + req, + ) ?: run { throw LsSdkException.Generic(errMissingMandatoryField("req", "RestoreRequest")) } + getBindingWallet().restore(restoreRequest) promise.resolve(readableMapOf("status" to "ok")) } catch (e: Exception) { promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e) diff --git a/packages/react-native/ios/BreezLiquidSDKMapper.swift b/packages/react-native/ios/BreezLiquidSDKMapper.swift index 92155a0..3763254 100644 --- a/packages/react-native/ios/BreezLiquidSDKMapper.swift +++ b/packages/react-native/ios/BreezLiquidSDKMapper.swift @@ -2,6 +2,124 @@ import BreezLiquidSDK import Foundation enum BreezLiquidSDKMapper { + static func asConnectRequest(connectRequest: [String: Any?]) throws -> ConnectRequest { + guard let mnemonic = connectRequest["mnemonic"] as? String else { + throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "mnemonic", typeName: "ConnectRequest")) + } + var dataDir: String? + if hasNonNilKey(data: connectRequest, key: "dataDir") { + guard let dataDirTmp = connectRequest["dataDir"] as? String else { + throw LsSdkError.Generic(message: errUnexpectedValue(fieldName: "dataDir")) + } + dataDir = dataDirTmp + } + guard let networkTmp = connectRequest["network"] as? String else { + throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "network", typeName: "ConnectRequest")) + } + let network = try asNetwork(network: networkTmp) + + return ConnectRequest( + mnemonic: mnemonic, + dataDir: dataDir, + network: network + ) + } + + static func dictionaryOf(connectRequest: ConnectRequest) -> [String: Any?] { + return [ + "mnemonic": connectRequest.mnemonic, + "dataDir": connectRequest.dataDir == nil ? nil : connectRequest.dataDir, + "network": valueOf(network: connectRequest.network), + ] + } + + static func asConnectRequestList(arr: [Any]) throws -> [ConnectRequest] { + var list = [ConnectRequest]() + for value in arr { + if let val = value as? [String: Any?] { + var connectRequest = try asConnectRequest(connectRequest: val) + list.append(connectRequest) + } else { + throw LsSdkError.Generic(message: errUnexpectedType(typeName: "ConnectRequest")) + } + } + return list + } + + static func arrayOf(connectRequestList: [ConnectRequest]) -> [Any] { + return connectRequestList.map { v -> [String: Any?] in dictionaryOf(connectRequest: v) } + } + + static func asGetInfoRequest(getInfoRequest: [String: Any?]) throws -> GetInfoRequest { + guard let withScan = getInfoRequest["withScan"] as? Bool else { + throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "withScan", typeName: "GetInfoRequest")) + } + + return GetInfoRequest( + withScan: withScan) + } + + static func dictionaryOf(getInfoRequest: GetInfoRequest) -> [String: Any?] { + return [ + "withScan": getInfoRequest.withScan, + ] + } + + static func asGetInfoRequestList(arr: [Any]) throws -> [GetInfoRequest] { + var list = [GetInfoRequest]() + for value in arr { + if let val = value as? [String: Any?] { + var getInfoRequest = try asGetInfoRequest(getInfoRequest: val) + list.append(getInfoRequest) + } else { + throw LsSdkError.Generic(message: errUnexpectedType(typeName: "GetInfoRequest")) + } + } + return list + } + + static func arrayOf(getInfoRequestList: [GetInfoRequest]) -> [Any] { + return getInfoRequestList.map { v -> [String: Any?] in dictionaryOf(getInfoRequest: v) } + } + + static func asGetInfoResponse(getInfoResponse: [String: Any?]) throws -> GetInfoResponse { + guard let balanceSat = getInfoResponse["balanceSat"] as? UInt64 else { + throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "balanceSat", typeName: "GetInfoResponse")) + } + guard let pubkey = getInfoResponse["pubkey"] as? String else { + throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "pubkey", typeName: "GetInfoResponse")) + } + + return GetInfoResponse( + balanceSat: balanceSat, + pubkey: pubkey + ) + } + + static func dictionaryOf(getInfoResponse: GetInfoResponse) -> [String: Any?] { + return [ + "balanceSat": getInfoResponse.balanceSat, + "pubkey": getInfoResponse.pubkey, + ] + } + + static func asGetInfoResponseList(arr: [Any]) throws -> [GetInfoResponse] { + var list = [GetInfoResponse]() + for value in arr { + if let val = value as? [String: Any?] { + var getInfoResponse = try asGetInfoResponse(getInfoResponse: val) + list.append(getInfoResponse) + } else { + throw LsSdkError.Generic(message: errUnexpectedType(typeName: "GetInfoResponse")) + } + } + return list + } + + static func arrayOf(getInfoResponseList: [GetInfoResponse]) -> [Any] { + return getInfoResponseList.map { v -> [String: Any?] in dictionaryOf(getInfoResponse: v) } + } + static func asPrepareReceiveRequest(prepareReceiveRequest: [String: Any?]) throws -> PrepareReceiveRequest { guard let payerAmountSat = prepareReceiveRequest["payerAmountSat"] as? UInt64 else { throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "payerAmountSat", typeName: "PrepareReceiveRequest")) @@ -77,6 +195,38 @@ enum BreezLiquidSDKMapper { return prepareReceiveResponseList.map { v -> [String: Any?] in dictionaryOf(prepareReceiveResponse: v) } } + static func asPrepareSendRequest(prepareSendRequest: [String: Any?]) throws -> PrepareSendRequest { + guard let invoice = prepareSendRequest["invoice"] as? String else { + throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "invoice", typeName: "PrepareSendRequest")) + } + + return PrepareSendRequest( + invoice: invoice) + } + + static func dictionaryOf(prepareSendRequest: PrepareSendRequest) -> [String: Any?] { + return [ + "invoice": prepareSendRequest.invoice, + ] + } + + static func asPrepareSendRequestList(arr: [Any]) throws -> [PrepareSendRequest] { + var list = [PrepareSendRequest]() + for value in arr { + if let val = value as? [String: Any?] { + var prepareSendRequest = try asPrepareSendRequest(prepareSendRequest: val) + list.append(prepareSendRequest) + } else { + throw LsSdkError.Generic(message: errUnexpectedType(typeName: "PrepareSendRequest")) + } + } + return list + } + + static func arrayOf(prepareSendRequestList: [PrepareSendRequest]) -> [Any] { + return prepareSendRequestList.map { v -> [String: Any?] in dictionaryOf(prepareSendRequest: v) } + } + static func asPrepareSendResponse(prepareSendResponse: [String: Any?]) throws -> PrepareSendResponse { guard let id = prepareSendResponse["id"] as? String else { throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "id", typeName: "PrepareSendResponse")) @@ -173,6 +323,42 @@ enum BreezLiquidSDKMapper { return receivePaymentResponseList.map { v -> [String: Any?] in dictionaryOf(receivePaymentResponse: v) } } + static func asRestoreRequest(restoreRequest: [String: Any?]) throws -> RestoreRequest { + var backupPath: String? + if hasNonNilKey(data: restoreRequest, key: "backupPath") { + guard let backupPathTmp = restoreRequest["backupPath"] as? String else { + throw LsSdkError.Generic(message: errUnexpectedValue(fieldName: "backupPath")) + } + backupPath = backupPathTmp + } + + return RestoreRequest( + backupPath: backupPath) + } + + static func dictionaryOf(restoreRequest: RestoreRequest) -> [String: Any?] { + return [ + "backupPath": restoreRequest.backupPath == nil ? nil : restoreRequest.backupPath, + ] + } + + static func asRestoreRequestList(arr: [Any]) throws -> [RestoreRequest] { + var list = [RestoreRequest]() + for value in arr { + if let val = value as? [String: Any?] { + var restoreRequest = try asRestoreRequest(restoreRequest: val) + list.append(restoreRequest) + } else { + throw LsSdkError.Generic(message: errUnexpectedType(typeName: "RestoreRequest")) + } + } + return list + } + + static func arrayOf(restoreRequestList: [RestoreRequest]) -> [Any] { + return restoreRequestList.map { v -> [String: Any?] in dictionaryOf(restoreRequest: v) } + } + static func asSendPaymentResponse(sendPaymentResponse: [String: Any?]) throws -> SendPaymentResponse { guard let txid = sendPaymentResponse["txid"] as? String else { throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "txid", typeName: "SendPaymentResponse")) @@ -205,44 +391,6 @@ enum BreezLiquidSDKMapper { return sendPaymentResponseList.map { v -> [String: Any?] in dictionaryOf(sendPaymentResponse: v) } } - static func asWalletInfo(walletInfo: [String: Any?]) throws -> WalletInfo { - guard let balanceSat = walletInfo["balanceSat"] as? UInt64 else { - throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "balanceSat", typeName: "WalletInfo")) - } - guard let pubkey = walletInfo["pubkey"] as? String else { - throw LsSdkError.Generic(message: errMissingMandatoryField(fieldName: "pubkey", typeName: "WalletInfo")) - } - - return WalletInfo( - balanceSat: balanceSat, - pubkey: pubkey - ) - } - - static func dictionaryOf(walletInfo: WalletInfo) -> [String: Any?] { - return [ - "balanceSat": walletInfo.balanceSat, - "pubkey": walletInfo.pubkey, - ] - } - - static func asWalletInfoList(arr: [Any]) throws -> [WalletInfo] { - var list = [WalletInfo]() - for value in arr { - if let val = value as? [String: Any?] { - var walletInfo = try asWalletInfo(walletInfo: val) - list.append(walletInfo) - } else { - throw LsSdkError.Generic(message: errUnexpectedType(typeName: "WalletInfo")) - } - } - return list - } - - static func arrayOf(walletInfoList: [WalletInfo]) -> [Any] { - return walletInfoList.map { v -> [String: Any?] in dictionaryOf(walletInfo: v) } - } - static func asNetwork(network: String) throws -> Network { switch network { case "liquid": diff --git a/packages/react-native/ios/RNBreezLiquidSDK.m b/packages/react-native/ios/RNBreezLiquidSDK.m index 58d4581..15b2745 100644 --- a/packages/react-native/ios/RNBreezLiquidSDK.m +++ b/packages/react-native/ios/RNBreezLiquidSDK.m @@ -4,21 +4,19 @@ @interface RCT_EXTERN_MODULE(RNBreezLiquidSDK, RCTEventEmitter) RCT_EXTERN_METHOD( - connect: (NSString*)mnemonic - dataDir: (NSString*)dataDir - network: (NSString*)network + connect: (NSDictionary*)req resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) RCT_EXTERN_METHOD( - getInfo: (BOOL)withScan + getInfo: (NSDictionary*)req resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) RCT_EXTERN_METHOD( - prepareSendPayment: (NSString*)invoice + prepareSendPayment: (NSDictionary*)req resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) @@ -47,7 +45,7 @@ RCT_EXTERN_METHOD( ) RCT_EXTERN_METHOD( - restore: (NSString*)backupPath + restore: (NSDictionary*)req resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) diff --git a/packages/react-native/ios/RNBreezLiquidSDK.swift b/packages/react-native/ios/RNBreezLiquidSDK.swift index 62c1463..5bfcf89 100644 --- a/packages/react-native/ios/RNBreezLiquidSDK.swift +++ b/packages/react-native/ios/RNBreezLiquidSDK.swift @@ -51,17 +51,17 @@ class RNBreezLiquidSDK: RCTEventEmitter { throw LsSdkError.Generic(message: "Not initialized") } - @objc(connect:dataDir:network:resolve:reject:) - func connect(_ mnemonic: String, dataDir: String, network: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + @objc(connect:resolve:reject:) + func connect(_ req: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { if bindingWallet != nil { reject("Generic", "Already initialized", nil) return } do { - let dataDirTmp = dataDir.isEmpty ? RNBreezLiquidSDK.defaultDataDir.path : dataDir - let networkTmp = try BreezLiquidSDKMapper.asNetwork(network: network) - bindingWallet = try BreezLiquidSDK.connect(mnemonic: mnemonic, dataDir: dataDirTmp, network: networkTmp) + var connectRequest = try BreezLiquidSDKMapper.asConnectRequest(connectRequest: req) + connectRequest.dataDir = connectRequest.dataDir.isEmpty ? RNBreezLiquidSDK.defaultDataDir.path : connectRequest.dataDir + bindingWallet = try BreezLiquidSDK.connect(req: connectRequest) resolve(["status": "ok"]) } catch let err { rejectErr(err: err, reject: reject) @@ -69,19 +69,21 @@ class RNBreezLiquidSDK: RCTEventEmitter { } @objc(getInfo:resolve:reject:) - func getInfo(_ withScan: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + func getInfo(_ req: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { do { - var res = try getBindingWallet().getInfo(withScan: withScan) - resolve(BreezLiquidSDKMapper.dictionaryOf(walletInfo: res)) + let getInfoRequest = try BreezLiquidSDKMapper.asGetInfoRequest(getInfoRequest: req) + var res = try getBindingWallet().getInfo(req: getInfoRequest) + resolve(BreezLiquidSDKMapper.dictionaryOf(getInfoResponse: res)) } catch let err { rejectErr(err: err, reject: reject) } } @objc(prepareSendPayment:resolve:reject:) - func prepareSendPayment(_ invoice: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + func prepareSendPayment(_ req: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { do { - var res = try getBindingWallet().prepareSendPayment(invoice: invoice) + let prepareSendRequest = try BreezLiquidSDKMapper.asPrepareSendRequest(prepareSendRequest: req) + var res = try getBindingWallet().prepareSendPayment(req: prepareSendRequest) resolve(BreezLiquidSDKMapper.dictionaryOf(prepareSendResponse: res)) } catch let err { rejectErr(err: err, reject: reject) @@ -132,10 +134,10 @@ class RNBreezLiquidSDK: RCTEventEmitter { } @objc(restore:resolve:reject:) - func restore(_ backupPath: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + func restore(_ req: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { do { - let backupPathTmp = backupPath.isEmpty ? nil : backupPath - try getBindingWallet().restore(backupPath: backupPathTmp) + let restoreRequest = try BreezLiquidSDKMapper.asRestoreRequest(restoreRequest: req) + try getBindingWallet().restore(req: restoreRequest) resolve(["status": "ok"]) } catch let err { rejectErr(err: err, reject: reject) diff --git a/packages/react-native/src/index.ts b/packages/react-native/src/index.ts index 97af3dd..95e47e3 100644 --- a/packages/react-native/src/index.ts +++ b/packages/react-native/src/index.ts @@ -17,6 +17,21 @@ const BreezLiquidSDK = NativeModules.RNBreezLiquidSDK } ) +export interface ConnectRequest { + mnemonic: string + dataDir?: string + network: Network +} + +export interface GetInfoRequest { + withScan: boolean +} + +export interface GetInfoResponse { + balanceSat: number + pubkey: string +} + export interface PrepareReceiveRequest { payerAmountSat: number } @@ -27,6 +42,10 @@ export interface PrepareReceiveResponse { feesSat: number } +export interface PrepareSendRequest { + invoice: string +} + export interface PrepareSendResponse { id: string payerAmountSat: number @@ -41,13 +60,12 @@ export interface ReceivePaymentResponse { invoice: string } -export interface SendPaymentResponse { - txid: string +export interface RestoreRequest { + backupPath?: string } -export interface WalletInfo { - balanceSat: number - pubkey: string +export interface SendPaymentResponse { + txid: string } export enum Network { @@ -55,18 +73,18 @@ export enum Network { LIQUID_TESTNET = "liquidTestnet" } -export const connect = async (mnemonic: string, dataDir: string = "", network: Network): Promise => { - const response = await BreezLiquidSDK.connect(mnemonic, dataDir, network) +export const connect = async (req: ConnectRequest): Promise => { + const response = await BreezLiquidSDK.connect(req) return response } -export const getInfo = async (withScan: boolean): Promise => { - const response = await BreezLiquidSDK.getInfo(withScan) +export const getInfo = async (req: GetInfoRequest): Promise => { + const response = await BreezLiquidSDK.getInfo(req) return response } -export const prepareSendPayment = async (invoice: string): Promise => { - const response = await BreezLiquidSDK.prepareSendPayment(invoice) +export const prepareSendPayment = async (req: PrepareSendRequest): Promise => { + const response = await BreezLiquidSDK.prepareSendPayment(req) return response } @@ -89,6 +107,6 @@ export const backup = async (): Promise => { await BreezLiquidSDK.backup() } -export const restore = async (backupPath: string = ""): Promise => { - await BreezLiquidSDK.restore(backupPath) +export const restore = async (req: RestoreRequest): Promise => { + await BreezLiquidSDK.restore(req) }