Skip to content

Commit

Permalink
feat: add main sdk hook
Browse files Browse the repository at this point in the history
  • Loading branch information
hydra-yse committed Nov 22, 2024
1 parent f024c00 commit b6f39e8
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions lib/bindings/src/breez_sdk_liquid.udl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -644,6 +645,12 @@ callback interface Signer {

[Throws=SignerError]
sequence<u8> hmac_sha256(sequence<u8> msg, string derivation_path);

[Throws=SignerError]
sequence<u8> ecies_encrypt(sequence<u8> msg);

[Throws=SignerError]
sequence<u8> ecies_decrypt(sequence<u8> msg);
};

interface BindingLiquidSdk {
Expand Down
7 changes: 7 additions & 0 deletions lib/core/src/frb_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2286,6 +2286,7 @@ impl SseDecode for crate::model::Config {
let mut var_network = <crate::model::LiquidNetwork>::sse_decode(deserializer);
let mut var_paymentTimeoutSec = <u64>::sse_decode(deserializer);
let mut var_zeroConfMinFeeRateMsat = <u32>::sse_decode(deserializer);
let mut var_syncServiceUrl = <String>::sse_decode(deserializer);
let mut var_zeroConfMaxAmountSat = <Option<u64>>::sse_decode(deserializer);
let mut var_breezApiKey = <Option<String>>::sse_decode(deserializer);
return crate::model::Config {
Expand All @@ -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,
};
Expand Down Expand Up @@ -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(),
]
Expand Down Expand Up @@ -6290,6 +6293,7 @@ impl SseEncode for crate::model::Config {
<crate::model::LiquidNetwork>::sse_encode(self.network, serializer);
<u64>::sse_encode(self.payment_timeout_sec, serializer);
<u32>::sse_encode(self.zero_conf_min_fee_rate_msat, serializer);
<String>::sse_encode(self.sync_service_url, serializer);
<Option<u64>>::sse_encode(self.zero_conf_max_amount_sat, serializer);
<Option<String>>::sse_encode(self.breez_api_key, serializer);
}
Expand Down Expand Up @@ -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(),
}
Expand Down Expand Up @@ -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(),
}
Expand Down Expand Up @@ -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,
}
Expand Down
9 changes: 7 additions & 2 deletions lib/core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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<u64>,
Expand All @@ -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),
}
Expand All @@ -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,
}
Expand Down Expand Up @@ -251,10 +256,10 @@ pub trait Signer: Send + Sync {
fn hmac_sha256(&self, msg: Vec<u8>, derivation_path: String) -> Result<Vec<u8>, SignerError>;

/// Encrypts a message using (ECIES)[ecies::encrypt]
fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError>;
fn ecies_encrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError>;

/// Decrypts a message using (ECIES)[ecies::decrypt]
fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError>;
fn ecies_decrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError>;
}

/// An argument when calling [crate::sdk::LiquidSdk::connect].
Expand Down
21 changes: 21 additions & 0 deletions lib/core/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<SyncService>,
pub(crate) receive_swap_handler: ReceiveSwapHandler,
pub(crate) chain_swap_handler: Arc<ChainSwapHandler>,
pub(crate) buy_bitcoin_service: Arc<dyn BuyBitcoinApi>,
Expand Down Expand Up @@ -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,
Expand All @@ -221,6 +233,7 @@ impl LiquidSdk {
shutdown_receiver,
send_swap_handler,
receive_swap_handler,
sync_service,
chain_swap_handler,
buy_bitcoin_service,
});
Expand Down Expand Up @@ -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;

Expand Down
8 changes: 4 additions & 4 deletions lib/core/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,16 +254,16 @@ impl Signer for SdkSigner {
.to_vec())
}

fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
fn ecies_encrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
let keypair = self.xprv.to_keypair(&self.secp);
let rc_pub = keypair.public_key().to_public_key().to_bytes();
Ok(ecies::encrypt(&rc_pub, msg)
Ok(ecies::encrypt(&rc_pub, &msg)
.map_err(|err| anyhow::anyhow!("Could not encrypt data: {err}"))?)
}

fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
fn ecies_decrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
let rc_prv = self.xprv.to_priv().to_bytes();
Ok(ecies::decrypt(&rc_prv, msg)
Ok(ecies::decrypt(&rc_prv, &msg)
.map_err(|err| anyhow::anyhow!("Could not decrypt data: {err}"))?)
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/core/src/sync/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl Record {
let id = Self::get_id_from_sync_data(&data);
let data = data.to_bytes()?;
let data = signer
.ecies_encrypt(&data)
.ecies_encrypt(data)
.map_err(|err| anyhow::anyhow!("Could not encrypt sync data: {err:?}"))?;
let schema_version = CURRENT_SCHEMA_VERSION.to_string();
Ok(Self {
Expand Down Expand Up @@ -126,7 +126,7 @@ impl Record {
}

pub(crate) fn decrypt(self, signer: Arc<Box<dyn Signer>>) -> Result<DecryptedRecord> {
let dec_data = signer.ecies_decrypt(self.data.as_slice())?;
let dec_data = signer.ecies_decrypt(self.data)?;
let data = serde_json::from_slice(&dec_data)?;
Ok(DecryptedRecord {
id: self.id,
Expand Down
56 changes: 20 additions & 36 deletions lib/core/src/sync/model/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
inner: tonic::client::Grpc<T>,
Expand Down Expand Up @@ -127,9 +127,8 @@ pub mod syncer_client {
<T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody,
>,
>,
<T as tonic::codegen::Service<
http::Request<tonic::body::BoxBody>,
>>::Error: Into<StdError> + std::marker::Send + std::marker::Sync,
<T as tonic::codegen::Service<http::Request<tonic::body::BoxBody>>>::Error:
Into<StdError> + std::marker::Send + std::marker::Sync,
{
SyncerClient::new(InterceptedService::new(inner, interceptor))
}
Expand Down Expand Up @@ -168,39 +167,28 @@ pub mod syncer_client {
&mut self,
request: impl tonic::IntoRequest<super::SetRecordRequest>,
) -> std::result::Result<tonic::Response<super::SetRecordReply>, 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<super::ListChangesRequest>,
) -> std::result::Result<
tonic::Response<super::ListChangesReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
) -> std::result::Result<tonic::Response<super::ListChangesReply>, 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(
Expand All @@ -210,18 +198,14 @@ pub mod syncer_client {
tonic::Response<tonic::codec::Streaming<super::Record>>,
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
}
}
Expand Down
14 changes: 13 additions & 1 deletion lib/core/src/test_utils/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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},
};

Expand Down Expand Up @@ -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::<Record>(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,
Expand All @@ -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,
})
Expand Down
8 changes: 4 additions & 4 deletions lib/core/src/test_utils/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,15 @@ impl Signer for MockSigner {
todo!()
}

fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
fn ecies_encrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
let rc_pub = self.keypair.public_key().to_public_key().to_bytes();
Ok(ecies::encrypt(&rc_pub, msg)
Ok(ecies::encrypt(&rc_pub, &msg)
.map_err(|err| anyhow::anyhow!("Could not encrypt data: {err}"))?)
}

fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
fn ecies_decrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
let rc_prv = self.keypair.secret_bytes();
Ok(ecies::decrypt(&rc_prv, msg)
Ok(ecies::decrypt(&rc_prv, &msg)
.map_err(|err| anyhow::anyhow!("Could not decrypt data: {err}"))?)
}
}
Loading

0 comments on commit b6f39e8

Please sign in to comment.