diff --git a/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h b/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h index d02b1bd78..0204a230d 100644 --- a/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h +++ b/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h @@ -442,6 +442,7 @@ typedef struct wire_cst_config { int32_t network; uint64_t payment_timeout_sec; uint32_t zero_conf_min_fee_rate_msat; + struct wire_cst_list_prim_u_8_strict *sync_service_url; uint64_t *zero_conf_max_amount_sat; struct wire_cst_list_prim_u_8_strict *breez_api_key; } wire_cst_config; diff --git a/lib/bindings/src/breez_sdk_liquid.udl b/lib/bindings/src/breez_sdk_liquid.udl index 290267558..bbf6012bd 100644 --- a/lib/bindings/src/breez_sdk_liquid.udl +++ b/lib/bindings/src/breez_sdk_liquid.udl @@ -310,6 +310,7 @@ dictionary Config { LiquidNetwork network; u64 payment_timeout_sec; u32 zero_conf_min_fee_rate_msat; + string sync_service_url; string? breez_api_key; u64? zero_conf_max_amount_sat; }; diff --git a/lib/core/src/frb_generated.rs b/lib/core/src/frb_generated.rs index 54c3f65aa..0723f7bb3 100644 --- a/lib/core/src/frb_generated.rs +++ b/lib/core/src/frb_generated.rs @@ -2286,6 +2286,7 @@ impl SseDecode for crate::model::Config { let mut var_network = ::sse_decode(deserializer); let mut var_paymentTimeoutSec = ::sse_decode(deserializer); let mut var_zeroConfMinFeeRateMsat = ::sse_decode(deserializer); + let mut var_syncServiceUrl = ::sse_decode(deserializer); let mut var_zeroConfMaxAmountSat = >::sse_decode(deserializer); let mut var_breezApiKey = >::sse_decode(deserializer); return crate::model::Config { @@ -2296,6 +2297,7 @@ impl SseDecode for crate::model::Config { network: var_network, payment_timeout_sec: var_paymentTimeoutSec, zero_conf_min_fee_rate_msat: var_zeroConfMinFeeRateMsat, + sync_service_url: var_syncServiceUrl, zero_conf_max_amount_sat: var_zeroConfMaxAmountSat, breez_api_key: var_breezApiKey, }; @@ -4318,6 +4320,7 @@ impl flutter_rust_bridge::IntoDart for crate::model::Config { self.zero_conf_min_fee_rate_msat .into_into_dart() .into_dart(), + self.sync_service_url.into_into_dart().into_dart(), self.zero_conf_max_amount_sat.into_into_dart().into_dart(), self.breez_api_key.into_into_dart().into_dart(), ] @@ -6290,6 +6293,7 @@ impl SseEncode for crate::model::Config { ::sse_encode(self.network, serializer); ::sse_encode(self.payment_timeout_sec, serializer); ::sse_encode(self.zero_conf_min_fee_rate_msat, serializer); + ::sse_encode(self.sync_service_url, serializer); >::sse_encode(self.zero_conf_max_amount_sat, serializer); >::sse_encode(self.breez_api_key, serializer); } @@ -8216,6 +8220,7 @@ mod io { network: self.network.cst_decode(), payment_timeout_sec: self.payment_timeout_sec.cst_decode(), zero_conf_min_fee_rate_msat: self.zero_conf_min_fee_rate_msat.cst_decode(), + sync_service_url: self.sync_service_url.cst_decode(), zero_conf_max_amount_sat: self.zero_conf_max_amount_sat.cst_decode(), breez_api_key: self.breez_api_key.cst_decode(), } @@ -9573,6 +9578,7 @@ mod io { network: Default::default(), payment_timeout_sec: Default::default(), zero_conf_min_fee_rate_msat: Default::default(), + sync_service_url: core::ptr::null_mut(), zero_conf_max_amount_sat: core::ptr::null_mut(), breez_api_key: core::ptr::null_mut(), } @@ -11469,6 +11475,7 @@ mod io { network: i32, payment_timeout_sec: u64, zero_conf_min_fee_rate_msat: u32, + sync_service_url: *mut wire_cst_list_prim_u_8_strict, zero_conf_max_amount_sat: *mut u64, breez_api_key: *mut wire_cst_list_prim_u_8_strict, } diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs index f044b4d1a..cd8af9b74 100644 --- a/lib/core/src/model.rs +++ b/lib/core/src/model.rs @@ -28,6 +28,7 @@ use crate::utils; // Both use f64 for the maximum precision when converting between units pub const STANDARD_FEE_RATE_SAT_PER_VBYTE: f64 = 0.1; pub const LOWBALL_FEE_RATE_SAT_PER_VBYTE: f64 = 0.01; +const BREEZ_SYNC_SERVICE_URL: &str = "https://sync-service-wandering-morning-6267.fly.dev"; /// Configuration for the Liquid SDK #[derive(Clone, Debug, Serialize)] @@ -45,6 +46,8 @@ pub struct Config { pub payment_timeout_sec: u64, /// Zero-conf minimum accepted fee-rate in millisatoshis per vbyte pub zero_conf_min_fee_rate_msat: u32, + /// The url of the real-time sync service + pub sync_service_url: String, /// Maximum amount in satoshi to accept zero-conf payments with /// Defaults to [crate::receive_swap::DEFAULT_ZERO_CONF_MAX_SAT] pub zero_conf_max_amount_sat: Option, @@ -62,6 +65,7 @@ impl Config { network: LiquidNetwork::Mainnet, payment_timeout_sec: 15, zero_conf_min_fee_rate_msat: DEFAULT_ZERO_CONF_MIN_FEE_RATE_MAINNET, + sync_service_url: BREEZ_SYNC_SERVICE_URL.to_string(), zero_conf_max_amount_sat: None, breez_api_key: Some(breez_api_key), } @@ -76,6 +80,7 @@ impl Config { network: LiquidNetwork::Testnet, payment_timeout_sec: 15, zero_conf_min_fee_rate_msat: DEFAULT_ZERO_CONF_MIN_FEE_RATE_TESTNET, + sync_service_url: BREEZ_SYNC_SERVICE_URL.to_string(), zero_conf_max_amount_sat: None, breez_api_key, } diff --git a/lib/core/src/sdk.rs b/lib/core/src/sdk.rs index 5f43fe168..be413056a 100644 --- a/lib/core/src/sdk.rs +++ b/lib/core/src/sdk.rs @@ -45,6 +45,9 @@ use crate::{ utils, *, }; +use self::sync::client::BreezSyncerClient; +use self::sync::SyncService; + pub const DEFAULT_DATA_DIR: &str = ".data"; /// Number of blocks to monitor a swap after its timeout block height pub const CHAIN_SWAP_MONITORING_PERIOD_BITCOIN_BLOCKS: u32 = 4320; @@ -66,6 +69,7 @@ pub struct LiquidSdk { pub(crate) shutdown_sender: watch::Sender<()>, pub(crate) shutdown_receiver: watch::Receiver<()>, pub(crate) send_swap_handler: SendSwapHandler, + pub(crate) sync_service: Arc, pub(crate) receive_swap_handler: ReceiveSwapHandler, pub(crate) chain_swap_handler: Arc, pub(crate) buy_bitcoin_service: Arc, @@ -205,6 +209,14 @@ impl LiquidSdk { let buy_bitcoin_service = Arc::new(BuyBitcoinService::new(config.clone(), breez_server.clone())); + let syncer_client = Box::new(BreezSyncerClient::new()); + let sync_service = Arc::new(SyncService::new( + config.sync_service_url.clone(), + persister.clone(), + signer.clone(), + syncer_client, + )); + let sdk = Arc::new(LiquidSdk { config: config.clone(), onchain_wallet, @@ -221,6 +233,7 @@ impl LiquidSdk { shutdown_receiver, send_swap_handler, receive_swap_handler, + sync_service, chain_swap_handler, buy_bitcoin_service, }); @@ -278,6 +291,14 @@ impl LiquidSdk { .clone() .start(self.shutdown_receiver.clone()) .await; + if let Err(err) = self + .sync_service + .clone() + .run(self.shutdown_receiver.clone()) + .await + { + info!("Could not connect to real-time sync service: {err:?}"); + } self.track_swap_updates().await; self.track_pending_swaps().await; diff --git a/lib/core/src/sync/mod.rs b/lib/core/src/sync/mod.rs index 9835e38f9..0970e1511 100644 --- a/lib/core/src/sync/mod.rs +++ b/lib/core/src/sync/mod.rs @@ -4,6 +4,7 @@ use std::time::Duration; use anyhow::{anyhow, Result}; use futures_util::TryFutureExt; +use tokio::sync::watch; use crate::sync::model::sync::{Record, SetRecordRequest, SetRecordStatus}; use crate::utils; @@ -42,15 +43,27 @@ impl SyncService { } } - async fn run(self: Arc) -> Result<()> { - let cloned = self.clone(); + pub(crate) async fn run(self: Arc, mut shutdown: watch::Receiver<()>) -> Result<()> { + self.client.connect(self.remote_url.clone()).await?; tokio::spawn(async move { + let mut event_loop_interval = tokio::time::interval(Duration::from_secs(30)); + loop { - if let Err(err) = cloned.pull().and_then(|_| cloned.push()).await { - log::debug!("Could not run sync event loop: {err:?}"); + tokio::select! { + _ = event_loop_interval.tick() => { + if let Err(err) = self.pull().and_then(|_| self.push()).await { + log::debug!("Could not run sync event loop: {err:?}"); + } + } + _ = shutdown.changed() => { + log::info!("Received shutdown signal, exiting realtime sync service loop"); + if let Err(err) = self.client.disconnect().await { + log::debug!("Could not disconnect sync service client: {err:?}"); + }; + return; + } } - tokio::time::sleep(Duration::from_secs(30)).await; } }); diff --git a/lib/core/src/sync/model/sync.rs b/lib/core/src/sync/model/sync.rs index aee7f261c..2e707b828 100644 --- a/lib/core/src/sync/model/sync.rs +++ b/lib/core/src/sync/model/sync.rs @@ -80,10 +80,10 @@ pub mod syncer_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] - use tonic::codegen::*; use tonic::codegen::http::Uri; + use tonic::codegen::*; #[derive(Debug, Clone)] pub struct SyncerClient { inner: tonic::client::Grpc, @@ -127,9 +127,8 @@ pub mod syncer_client { >::ResponseBody, >, >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, + >>::Error: + Into + std::marker::Send + std::marker::Sync, { SyncerClient::new(InterceptedService::new(inner, interceptor)) } @@ -168,39 +167,28 @@ pub mod syncer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/sync.Syncer/SetRecord"); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("sync.Syncer", "SetRecord")); + req.extensions_mut() + .insert(GrpcMethod::new("sync.Syncer", "SetRecord")); self.inner.unary(req, path, codec).await } pub async fn list_changes( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/sync.Syncer/ListChanges"); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("sync.Syncer", "ListChanges")); + req.extensions_mut() + .insert(GrpcMethod::new("sync.Syncer", "ListChanges")); self.inner.unary(req, path, codec).await } pub async fn track_changes( @@ -210,18 +198,14 @@ pub mod syncer_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/sync.Syncer/TrackChanges"); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("sync.Syncer", "TrackChanges")); + req.extensions_mut() + .insert(GrpcMethod::new("sync.Syncer", "TrackChanges")); self.inner.server_streaming(req, path, codec).await } } diff --git a/lib/core/src/test_utils/sdk.rs b/lib/core/src/test_utils/sdk.rs index ae34026bb..69ac4c96f 100644 --- a/lib/core/src/test_utils/sdk.rs +++ b/lib/core/src/test_utils/sdk.rs @@ -4,7 +4,7 @@ use anyhow::{anyhow, Result}; use sdk_common::prelude::{BreezServer, STAGING_BREEZSERVER_URL}; use std::sync::Arc; -use tokio::sync::{watch, Mutex, RwLock}; +use tokio::sync::{mpsc, watch, Mutex, RwLock}; use crate::{ buy::BuyBitcoinService, @@ -15,12 +15,14 @@ use crate::{ receive_swap::ReceiveSwapHandler, sdk::LiquidSdk, send_swap::SendSwapHandler, + sync::{model::sync::Record, SyncService}, }; use super::{ chain::{MockBitcoinChainService, MockLiquidChainService}, status_stream::MockStatusStream, swapper::MockSwapper, + sync::MockSyncerClient, wallet::{MockSigner, MockWallet}, }; @@ -91,6 +93,15 @@ pub(crate) fn new_liquid_sdk_with_chain_services( let buy_bitcoin_service = Arc::new(BuyBitcoinService::new(config.clone(), breez_server.clone())); + let (_, incoming_rx) = mpsc::channel::(10); + let syncer_client = Box::new(MockSyncerClient::new(incoming_rx, Default::default())); + let sync_service = Arc::new(SyncService::new( + "".to_string(), + persister.clone(), + signer.clone(), + syncer_client, + )); + Ok(LiquidSdk { config, onchain_wallet, @@ -107,6 +118,7 @@ pub(crate) fn new_liquid_sdk_with_chain_services( shutdown_receiver, send_swap_handler, receive_swap_handler, + sync_service, chain_swap_handler, buy_bitcoin_service, }) diff --git a/packages/dart/lib/src/frb_generated.dart b/packages/dart/lib/src/frb_generated.dart index a382c9dbb..e3b444239 100644 --- a/packages/dart/lib/src/frb_generated.dart +++ b/packages/dart/lib/src/frb_generated.dart @@ -1646,7 +1646,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Config dco_decode_config(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 9) throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return Config( liquidElectrumUrl: dco_decode_String(arr[0]), bitcoinElectrumUrl: dco_decode_String(arr[1]), @@ -1655,8 +1655,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { network: dco_decode_liquid_network(arr[4]), paymentTimeoutSec: dco_decode_u_64(arr[5]), zeroConfMinFeeRateMsat: dco_decode_u_32(arr[6]), - zeroConfMaxAmountSat: dco_decode_opt_box_autoadd_u_64(arr[7]), - breezApiKey: dco_decode_opt_String(arr[8]), + syncServiceUrl: dco_decode_String(arr[7]), + zeroConfMaxAmountSat: dco_decode_opt_box_autoadd_u_64(arr[8]), + breezApiKey: dco_decode_opt_String(arr[9]), ); } @@ -3425,6 +3426,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_network = sse_decode_liquid_network(deserializer); var var_paymentTimeoutSec = sse_decode_u_64(deserializer); var var_zeroConfMinFeeRateMsat = sse_decode_u_32(deserializer); + var var_syncServiceUrl = sse_decode_String(deserializer); var var_zeroConfMaxAmountSat = sse_decode_opt_box_autoadd_u_64(deserializer); var var_breezApiKey = sse_decode_opt_String(deserializer); return Config( @@ -3435,6 +3437,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { network: var_network, paymentTimeoutSec: var_paymentTimeoutSec, zeroConfMinFeeRateMsat: var_zeroConfMinFeeRateMsat, + syncServiceUrl: var_syncServiceUrl, zeroConfMaxAmountSat: var_zeroConfMaxAmountSat, breezApiKey: var_breezApiKey); } @@ -5323,6 +5326,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_liquid_network(self.network, serializer); sse_encode_u_64(self.paymentTimeoutSec, serializer); sse_encode_u_32(self.zeroConfMinFeeRateMsat, serializer); + sse_encode_String(self.syncServiceUrl, serializer); sse_encode_opt_box_autoadd_u_64(self.zeroConfMaxAmountSat, serializer); sse_encode_opt_String(self.breezApiKey, serializer); } diff --git a/packages/dart/lib/src/frb_generated.io.dart b/packages/dart/lib/src/frb_generated.io.dart index d5f2bf4b6..bbea1ea1d 100644 --- a/packages/dart/lib/src/frb_generated.io.dart +++ b/packages/dart/lib/src/frb_generated.io.dart @@ -1997,6 +1997,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { wireObj.network = cst_encode_liquid_network(apiObj.network); wireObj.payment_timeout_sec = cst_encode_u_64(apiObj.paymentTimeoutSec); wireObj.zero_conf_min_fee_rate_msat = cst_encode_u_32(apiObj.zeroConfMinFeeRateMsat); + wireObj.sync_service_url = cst_encode_String(apiObj.syncServiceUrl); wireObj.zero_conf_max_amount_sat = cst_encode_opt_box_autoadd_u_64(apiObj.zeroConfMaxAmountSat); wireObj.breez_api_key = cst_encode_opt_String(apiObj.breezApiKey); } @@ -5574,6 +5575,8 @@ final class wire_cst_config extends ffi.Struct { @ffi.Uint32() external int zero_conf_min_fee_rate_msat; + external ffi.Pointer sync_service_url; + external ffi.Pointer zero_conf_max_amount_sat; external ffi.Pointer breez_api_key; diff --git a/packages/dart/lib/src/model.dart b/packages/dart/lib/src/model.dart index bc2ea5cb8..8190d5bef 100644 --- a/packages/dart/lib/src/model.dart +++ b/packages/dart/lib/src/model.dart @@ -131,6 +131,9 @@ class Config { /// Zero-conf minimum accepted fee-rate in millisatoshis per vbyte final int zeroConfMinFeeRateMsat; + /// The url of the real-time sync service + final String syncServiceUrl; + /// Maximum amount in satoshi to accept zero-conf payments with /// Defaults to [crate::receive_swap::DEFAULT_ZERO_CONF_MAX_SAT] final BigInt? zeroConfMaxAmountSat; @@ -146,6 +149,7 @@ class Config { required this.network, required this.paymentTimeoutSec, required this.zeroConfMinFeeRateMsat, + required this.syncServiceUrl, this.zeroConfMaxAmountSat, this.breezApiKey, }); @@ -159,6 +163,7 @@ class Config { network.hashCode ^ paymentTimeoutSec.hashCode ^ zeroConfMinFeeRateMsat.hashCode ^ + syncServiceUrl.hashCode ^ zeroConfMaxAmountSat.hashCode ^ breezApiKey.hashCode; @@ -174,6 +179,7 @@ class Config { network == other.network && paymentTimeoutSec == other.paymentTimeoutSec && zeroConfMinFeeRateMsat == other.zeroConfMinFeeRateMsat && + syncServiceUrl == other.syncServiceUrl && zeroConfMaxAmountSat == other.zeroConfMaxAmountSat && breezApiKey == other.breezApiKey; } diff --git a/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart b/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart index 46b986ea1..630084062 100644 --- a/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart +++ b/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart @@ -4370,6 +4370,8 @@ final class wire_cst_config extends ffi.Struct { @ffi.Uint32() external int zero_conf_min_fee_rate_msat; + external ffi.Pointer sync_service_url; + external ffi.Pointer zero_conf_max_amount_sat; external ffi.Pointer breez_api_key; diff --git a/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt b/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt index b9c340314..f24699c22 100644 --- a/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt +++ b/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt @@ -248,6 +248,7 @@ fun asConfig(config: ReadableMap): Config? { "network", "paymentTimeoutSec", "zeroConfMinFeeRateMsat", + "syncServiceUrl", ), ) ) { @@ -260,6 +261,7 @@ fun asConfig(config: ReadableMap): Config? { val network = config.getString("network")?.let { asLiquidNetwork(it) }!! val paymentTimeoutSec = config.getDouble("paymentTimeoutSec").toULong() val zeroConfMinFeeRateMsat = config.getInt("zeroConfMinFeeRateMsat").toUInt() + val syncServiceUrl = config.getString("syncServiceUrl")!! val breezApiKey = if (hasNonNullKey(config, "breezApiKey")) config.getString("breezApiKey") else null val zeroConfMaxAmountSat = if (hasNonNullKey( @@ -279,6 +281,7 @@ fun asConfig(config: ReadableMap): Config? { network, paymentTimeoutSec, zeroConfMinFeeRateMsat, + syncServiceUrl, breezApiKey, zeroConfMaxAmountSat, ) @@ -293,6 +296,7 @@ fun readableMapOf(config: Config): ReadableMap = "network" to config.network.name.lowercase(), "paymentTimeoutSec" to config.paymentTimeoutSec, "zeroConfMinFeeRateMsat" to config.zeroConfMinFeeRateMsat, + "syncServiceUrl" to config.syncServiceUrl, "breezApiKey" to config.breezApiKey, "zeroConfMaxAmountSat" to config.zeroConfMaxAmountSat, ) diff --git a/packages/react-native/ios/BreezSDKLiquidMapper.swift b/packages/react-native/ios/BreezSDKLiquidMapper.swift index 2efdbb4e7..470cc94a2 100644 --- a/packages/react-native/ios/BreezSDKLiquidMapper.swift +++ b/packages/react-native/ios/BreezSDKLiquidMapper.swift @@ -307,6 +307,9 @@ enum BreezSDKLiquidMapper { guard let zeroConfMinFeeRateMsat = config["zeroConfMinFeeRateMsat"] as? UInt32 else { throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "zeroConfMinFeeRateMsat", typeName: "Config")) } + guard let syncServiceUrl = config["syncServiceUrl"] as? String else { + throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "syncServiceUrl", typeName: "Config")) + } var breezApiKey: String? if hasNonNilKey(data: config, key: "breezApiKey") { guard let breezApiKeyTmp = config["breezApiKey"] as? String else { @@ -322,7 +325,7 @@ enum BreezSDKLiquidMapper { zeroConfMaxAmountSat = zeroConfMaxAmountSatTmp } - return Config(liquidElectrumUrl: liquidElectrumUrl, bitcoinElectrumUrl: bitcoinElectrumUrl, mempoolspaceUrl: mempoolspaceUrl, workingDir: workingDir, network: network, paymentTimeoutSec: paymentTimeoutSec, zeroConfMinFeeRateMsat: zeroConfMinFeeRateMsat, breezApiKey: breezApiKey, zeroConfMaxAmountSat: zeroConfMaxAmountSat) + return Config(liquidElectrumUrl: liquidElectrumUrl, bitcoinElectrumUrl: bitcoinElectrumUrl, mempoolspaceUrl: mempoolspaceUrl, workingDir: workingDir, network: network, paymentTimeoutSec: paymentTimeoutSec, zeroConfMinFeeRateMsat: zeroConfMinFeeRateMsat, syncServiceUrl: syncServiceUrl, breezApiKey: breezApiKey, zeroConfMaxAmountSat: zeroConfMaxAmountSat) } static func dictionaryOf(config: Config) -> [String: Any?] { @@ -334,6 +337,7 @@ enum BreezSDKLiquidMapper { "network": valueOf(liquidNetwork: config.network), "paymentTimeoutSec": config.paymentTimeoutSec, "zeroConfMinFeeRateMsat": config.zeroConfMinFeeRateMsat, + "syncServiceUrl": config.syncServiceUrl, "breezApiKey": config.breezApiKey == nil ? nil : config.breezApiKey, "zeroConfMaxAmountSat": config.zeroConfMaxAmountSat == nil ? nil : config.zeroConfMaxAmountSat, ] diff --git a/packages/react-native/src/index.ts b/packages/react-native/src/index.ts index dac70d1d1..557cf731d 100644 --- a/packages/react-native/src/index.ts +++ b/packages/react-native/src/index.ts @@ -19,22 +19,22 @@ const BreezSDKLiquid = NativeModules.RNBreezSDKLiquid const BreezSDKLiquidEmitter = new NativeEventEmitter(BreezSDKLiquid) -export interface AesSuccessActionData { +export type AesSuccessActionData = { description: string ciphertext: string iv: string } -export interface AesSuccessActionDataDecrypted { +export type AesSuccessActionDataDecrypted = { description: string plaintext: string } -export interface BackupRequest { +export type BackupRequest = { backupPath?: string } -export interface BitcoinAddressData { +export type BitcoinAddressData = { address: string network: Network amountSat?: number @@ -42,22 +42,22 @@ export interface BitcoinAddressData { message?: string } -export interface BuyBitcoinRequest { +export type BuyBitcoinRequest = { prepareResponse: PrepareBuyBitcoinResponse redirectUrl?: string } -export interface CheckMessageRequest { +export type CheckMessageRequest = { message: string pubkey: string signature: string } -export interface CheckMessageResponse { +export type CheckMessageResponse = { isValid: boolean } -export interface Config { +export type Config = { liquidElectrumUrl: string bitcoinElectrumUrl: string mempoolspaceUrl: string @@ -65,20 +65,21 @@ export interface Config { network: LiquidNetwork paymentTimeoutSec: number zeroConfMinFeeRateMsat: number + syncServiceUrl: string breezApiKey?: string zeroConfMaxAmountSat?: number } -export interface ConnectRequest { +export type ConnectRequest = { config: Config mnemonic: string } -export interface ConnectWithSignerRequest { +export type ConnectWithSignerRequest = { config: Config } -export interface CurrencyInfo { +export type CurrencyInfo = { name: string fractionSize: number spacing?: number @@ -88,12 +89,12 @@ export interface CurrencyInfo { localeOverrides: LocaleOverrides[] } -export interface FiatCurrency { +export type FiatCurrency = { id: string info: CurrencyInfo } -export interface GetInfoResponse { +export type GetInfoResponse = { balanceSat: number pendingSendSat: number pendingReceiveSat: number @@ -101,7 +102,7 @@ export interface GetInfoResponse { pubkey: string } -export interface LnInvoice { +export type LnInvoice = { bolt11: string network: Network payeePubkey: string @@ -116,18 +117,18 @@ export interface LnInvoice { minFinalCltvExpiryDelta: number } -export interface LightningPaymentLimitsResponse { +export type LightningPaymentLimitsResponse = { send: Limits receive: Limits } -export interface Limits { +export type Limits = { minSat: number maxSat: number maxZeroConfSat: number } -export interface LiquidAddressData { +export type LiquidAddressData = { address: string network: Network assetId?: string @@ -136,7 +137,7 @@ export interface LiquidAddressData { message?: string } -export interface ListPaymentsRequest { +export type ListPaymentsRequest = { filters?: PaymentType[] fromTimestamp?: number toTimestamp?: number @@ -145,27 +146,27 @@ export interface ListPaymentsRequest { details?: ListPaymentDetails } -export interface LnUrlAuthRequestData { +export type LnUrlAuthRequestData = { k1: string domain: string url: string action?: string } -export interface LnUrlErrorData { +export type LnUrlErrorData = { reason: string } -export interface LnUrlPayErrorData { +export type LnUrlPayErrorData = { paymentHash: string reason: string } -export interface LnUrlPayRequest { +export type LnUrlPayRequest = { prepareResponse: PrepareLnUrlPayResponse } -export interface LnUrlPayRequestData { +export type LnUrlPayRequestData = { callback: string minSendable: number maxSendable: number @@ -177,18 +178,18 @@ export interface LnUrlPayRequestData { lnAddress?: string } -export interface LnUrlPaySuccessData { +export type LnUrlPaySuccessData = { successAction?: SuccessActionProcessed payment: Payment } -export interface LnUrlWithdrawRequest { +export type LnUrlWithdrawRequest = { data: LnUrlWithdrawRequestData amountMsat: number description?: string } -export interface LnUrlWithdrawRequestData { +export type LnUrlWithdrawRequestData = { callback: string k1: string defaultDescription: string @@ -196,41 +197,41 @@ export interface LnUrlWithdrawRequestData { maxWithdrawable: number } -export interface LnUrlWithdrawSuccessData { +export type LnUrlWithdrawSuccessData = { invoice: LnInvoice } -export interface LocaleOverrides { +export type LocaleOverrides = { locale: string spacing?: number symbol: SymbolType } -export interface LocalizedName { +export type LocalizedName = { locale: string name: string } -export interface LogEntry { +export type LogEntry = { line: string level: string } -export interface MessageSuccessActionData { +export type MessageSuccessActionData = { message: string } -export interface OnchainPaymentLimitsResponse { +export type OnchainPaymentLimitsResponse = { send: Limits receive: Limits } -export interface PayOnchainRequest { +export type PayOnchainRequest = { address: string prepareResponse: PreparePayOnchainResponse } -export interface Payment { +export type Payment = { timestamp: number amountSat: number feesSat: number @@ -241,90 +242,90 @@ export interface Payment { txId?: string } -export interface PrepareBuyBitcoinRequest { +export type PrepareBuyBitcoinRequest = { provider: BuyBitcoinProvider amountSat: number } -export interface PrepareBuyBitcoinResponse { +export type PrepareBuyBitcoinResponse = { provider: BuyBitcoinProvider amountSat: number feesSat: number } -export interface PrepareLnUrlPayRequest { +export type PrepareLnUrlPayRequest = { data: LnUrlPayRequestData amountMsat: number comment?: string validateSuccessActionUrl?: boolean } -export interface PrepareLnUrlPayResponse { +export type PrepareLnUrlPayResponse = { destination: SendDestination feesSat: number successAction?: SuccessAction } -export interface PreparePayOnchainRequest { +export type PreparePayOnchainRequest = { amount: PayOnchainAmount feeRateSatPerVbyte?: number } -export interface PreparePayOnchainResponse { +export type PreparePayOnchainResponse = { receiverAmountSat: number claimFeesSat: number totalFeesSat: number } -export interface PrepareReceiveRequest { +export type PrepareReceiveRequest = { paymentMethod: PaymentMethod payerAmountSat?: number } -export interface PrepareReceiveResponse { +export type PrepareReceiveResponse = { payerAmountSat?: number paymentMethod: PaymentMethod feesSat: number } -export interface PrepareRefundRequest { +export type PrepareRefundRequest = { swapAddress: string refundAddress: string feeRateSatPerVbyte: number } -export interface PrepareRefundResponse { +export type PrepareRefundResponse = { txVsize: number txFeeSat: number refundTxId?: string } -export interface PrepareSendRequest { +export type PrepareSendRequest = { destination: string amountSat?: number } -export interface PrepareSendResponse { +export type PrepareSendResponse = { destination: SendDestination feesSat: number } -export interface Rate { +export type Rate = { coin: string value: number } -export interface ReceivePaymentRequest { +export type ReceivePaymentRequest = { prepareResponse: PrepareReceiveResponse description?: string useDescriptionHash?: boolean } -export interface ReceivePaymentResponse { +export type ReceivePaymentResponse = { destination: string } -export interface RecommendedFees { +export type RecommendedFees = { fastestFee: number halfHourFee: number hourFee: number @@ -332,31 +333,31 @@ export interface RecommendedFees { minimumFee: number } -export interface RefundRequest { +export type RefundRequest = { swapAddress: string refundAddress: string feeRateSatPerVbyte: number } -export interface RefundResponse { +export type RefundResponse = { refundTxId: string } -export interface RefundableSwap { +export type RefundableSwap = { swapAddress: string timestamp: number amountSat: number } -export interface RestoreRequest { +export type RestoreRequest = { backupPath?: string } -export interface RouteHint { +export type RouteHint = { hops: RouteHintHop[] } -export interface RouteHintHop { +export type RouteHintHop = { srcNodeId: string shortChannelId: string feesBaseMsat: number @@ -366,30 +367,30 @@ export interface RouteHintHop { htlcMaximumMsat?: number } -export interface SendPaymentRequest { +export type SendPaymentRequest = { prepareResponse: PrepareSendResponse } -export interface SendPaymentResponse { +export type SendPaymentResponse = { payment: Payment } -export interface SignMessageRequest { +export type SignMessageRequest = { message: string } -export interface SignMessageResponse { +export type SignMessageResponse = { signature: string } -export interface SymbolType { +export type SymbolType = { grapheme?: string template?: string rtl?: boolean position?: number } -export interface UrlSuccessActionData { +export type UrlSuccessActionData = { description: string url: string matchesCallbackDomain: boolean @@ -416,7 +417,7 @@ export enum GetPaymentRequestVariant { LIGHTNING = "lightning" } -export interface GetPaymentRequest { +export type GetPaymentRequest = { type: GetPaymentRequestVariant.LIGHTNING, paymentHash: string } @@ -684,7 +685,7 @@ export const connect = async (req: ConnectRequest): Promise => { export const addEventListener = async (listener: EventListener): Promise => { const response = await BreezSDKLiquid.addEventListener() BreezSDKLiquidEmitter.addListener(`event-${response}`, listener) - + return response }