mirror of
https://github.com/aljazceru/breez-sdk-liquid.git
synced 2025-12-23 17:04:25 +01:00
Add ability to parse an invoice (#240)
* Add ability to parse an invoice * Simplify LNInvoice initialization * Add missing LNInvoice fields * Cargo fmt * Re-generate bindings after merging main branch * Explicitly check the invoice signature * Remove redundant signature check * Strip potential lightning: prefix before parsing bolt11
This commit is contained in:
2
cli/Cargo.lock
generated
2
cli/Cargo.lock
generated
@@ -370,7 +370,7 @@ checksum = "829a082bd3761fde7476dc2ed85ca56c11628948460ece621e4f56fef5046567"
|
||||
[[package]]
|
||||
name = "boltz-client"
|
||||
version = "0.1.3"
|
||||
source = "git+https://github.com/ok300/boltz-rust?branch=ok300-breez-latest-05-27#faecead854e8b0803f744b25bd0c47853cc487da"
|
||||
source = "git+https://github.com/ok300/boltz-rust?branch=ok300-breez-latest-05-28#92e4166131702dfa17b083796e6d0fc7eacf8f00"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"bitcoin 0.31.2",
|
||||
|
||||
@@ -92,7 +92,7 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
let mnemonic = persistence.get_or_create_mnemonic()?;
|
||||
let network = args.network.unwrap_or(Network::LiquidTestnet);
|
||||
let network = args.network.unwrap_or(Network::Testnet);
|
||||
let sdk = LiquidSdk::connect(ConnectRequest {
|
||||
mnemonic: mnemonic.to_string(),
|
||||
data_dir: Some(data_dir_str),
|
||||
@@ -104,8 +104,8 @@ async fn main() -> Result<()> {
|
||||
.await?;
|
||||
|
||||
let cli_prompt = match network {
|
||||
Network::Liquid => "breez-liquid-cli [mainnet]> ",
|
||||
Network::LiquidTestnet => "breez-liquid-cli [testnet]> ",
|
||||
Network::Mainnet => "breez-liquid-cli [mainnet]> ",
|
||||
Network::Testnet => "breez-liquid-cli [testnet]> ",
|
||||
};
|
||||
|
||||
loop {
|
||||
|
||||
2
lib/Cargo.lock
generated
2
lib/Cargo.lock
generated
@@ -490,7 +490,7 @@ checksum = "829a082bd3761fde7476dc2ed85ca56c11628948460ece621e4f56fef5046567"
|
||||
[[package]]
|
||||
name = "boltz-client"
|
||||
version = "0.1.3"
|
||||
source = "git+https://github.com/ok300/boltz-rust?branch=ok300-breez-latest-05-27#faecead854e8b0803f744b25bd0c47853cc487da"
|
||||
source = "git+https://github.com/ok300/boltz-rust?branch=ok300-breez-latest-05-28#92e4166131702dfa17b083796e6d0fc7eacf8f00"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"bitcoin 0.31.2",
|
||||
|
||||
@@ -79,6 +79,30 @@ typedef struct wire_cst_list_payment {
|
||||
int32_t len;
|
||||
} wire_cst_list_payment;
|
||||
|
||||
typedef struct wire_cst_route_hint_hop {
|
||||
struct wire_cst_list_prim_u_8_strict *src_node_id;
|
||||
uint64_t short_channel_id;
|
||||
uint32_t fees_base_msat;
|
||||
uint32_t fees_proportional_millionths;
|
||||
uint64_t cltv_expiry_delta;
|
||||
uint64_t *htlc_minimum_msat;
|
||||
uint64_t *htlc_maximum_msat;
|
||||
} wire_cst_route_hint_hop;
|
||||
|
||||
typedef struct wire_cst_list_route_hint_hop {
|
||||
struct wire_cst_route_hint_hop *ptr;
|
||||
int32_t len;
|
||||
} wire_cst_list_route_hint_hop;
|
||||
|
||||
typedef struct wire_cst_route_hint {
|
||||
struct wire_cst_list_route_hint_hop *hops;
|
||||
} wire_cst_route_hint;
|
||||
|
||||
typedef struct wire_cst_list_route_hint {
|
||||
struct wire_cst_route_hint *ptr;
|
||||
int32_t len;
|
||||
} wire_cst_list_route_hint;
|
||||
|
||||
typedef struct wire_cst_get_info_response {
|
||||
uint64_t balance_sat;
|
||||
uint64_t pending_send_sat;
|
||||
@@ -137,6 +161,21 @@ typedef struct wire_cst_liquid_sdk_event {
|
||||
union LiquidSdkEventKind kind;
|
||||
} wire_cst_liquid_sdk_event;
|
||||
|
||||
typedef struct wire_cst_ln_invoice {
|
||||
struct wire_cst_list_prim_u_8_strict *bolt11;
|
||||
int32_t network;
|
||||
struct wire_cst_list_prim_u_8_strict *payee_pubkey;
|
||||
struct wire_cst_list_prim_u_8_strict *payment_hash;
|
||||
struct wire_cst_list_prim_u_8_strict *description;
|
||||
struct wire_cst_list_prim_u_8_strict *description_hash;
|
||||
uint64_t *amount_msat;
|
||||
uint64_t timestamp;
|
||||
uint64_t expiry;
|
||||
struct wire_cst_list_route_hint *routing_hints;
|
||||
struct wire_cst_list_prim_u_8_strict *payment_secret;
|
||||
uint64_t min_final_cltv_expiry_delta;
|
||||
} wire_cst_ln_invoice;
|
||||
|
||||
typedef struct wire_cst_PaymentError_Generic {
|
||||
struct wire_cst_list_prim_u_8_strict *err;
|
||||
} wire_cst_PaymentError_Generic;
|
||||
@@ -227,6 +266,9 @@ void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_sync(int64_t po
|
||||
void frbgen_breez_liquid_wire__crate__bindings__connect(int64_t port_,
|
||||
struct wire_cst_connect_request *req);
|
||||
|
||||
void frbgen_breez_liquid_wire__crate__bindings__parse_invoice(int64_t port_,
|
||||
struct wire_cst_list_prim_u_8_strict *input);
|
||||
|
||||
void frbgen_breez_liquid_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(const void *ptr);
|
||||
|
||||
void frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(const void *ptr);
|
||||
@@ -254,6 +296,10 @@ uint64_t *frbgen_breez_liquid_cst_new_box_autoadd_u_64(uint64_t value);
|
||||
struct wire_cst_list_payment *frbgen_breez_liquid_cst_new_list_payment(int32_t len);
|
||||
|
||||
struct wire_cst_list_prim_u_8_strict *frbgen_breez_liquid_cst_new_list_prim_u_8_strict(int32_t len);
|
||||
|
||||
struct wire_cst_list_route_hint *frbgen_breez_liquid_cst_new_list_route_hint(int32_t len);
|
||||
|
||||
struct wire_cst_list_route_hint_hop *frbgen_breez_liquid_cst_new_list_route_hint_hop(int32_t len);
|
||||
static int64_t dummy_method_to_enforce_bundling(void) {
|
||||
int64_t dummy_var = 0;
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_backup_request);
|
||||
@@ -268,6 +314,8 @@ static int64_t dummy_method_to_enforce_bundling(void) {
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_box_autoadd_u_64);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_list_payment);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_list_prim_u_8_strict);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_list_route_hint);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_cst_new_list_route_hint_hop);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_add_event_listener);
|
||||
@@ -283,6 +331,7 @@ static int64_t dummy_method_to_enforce_bundling(void) {
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_send_payment);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_sync);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_wire__crate__bindings__connect);
|
||||
dummy_var ^= ((int64_t) (void*) frbgen_breez_liquid_wire__crate__bindings__parse_invoice);
|
||||
dummy_var ^= ((int64_t) (void*) store_dart_post_cobject);
|
||||
return dummy_var;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ enum PaymentError {
|
||||
};
|
||||
|
||||
enum Network {
|
||||
"Liquid",
|
||||
"LiquidTestnet",
|
||||
"Mainnet",
|
||||
"Testnet",
|
||||
};
|
||||
|
||||
dictionary ConnectRequest {
|
||||
@@ -79,6 +79,35 @@ dictionary RestoreRequest {
|
||||
string? backup_path = null;
|
||||
};
|
||||
|
||||
dictionary RouteHint {
|
||||
sequence<RouteHintHop> hops;
|
||||
};
|
||||
|
||||
dictionary RouteHintHop {
|
||||
string src_node_id;
|
||||
u64 short_channel_id;
|
||||
u32 fees_base_msat;
|
||||
u32 fees_proportional_millionths;
|
||||
u64 cltv_expiry_delta;
|
||||
u64? htlc_minimum_msat;
|
||||
u64? htlc_maximum_msat;
|
||||
};
|
||||
|
||||
dictionary LNInvoice {
|
||||
string bolt11;
|
||||
Network network;
|
||||
string payee_pubkey;
|
||||
string payment_hash;
|
||||
string? description;
|
||||
string? description_hash;
|
||||
u64? amount_msat;
|
||||
u64 timestamp;
|
||||
u64 expiry;
|
||||
sequence<RouteHint> routing_hints;
|
||||
sequence<u8> payment_secret;
|
||||
u64 min_final_cltv_expiry_delta;
|
||||
};
|
||||
|
||||
dictionary Payment {
|
||||
string tx_id;
|
||||
string? swap_id = null;
|
||||
@@ -122,6 +151,9 @@ callback interface EventListener {
|
||||
namespace breez_liquid_sdk {
|
||||
[Throws=LiquidSdkError]
|
||||
BindingLiquidSdk connect(ConnectRequest req);
|
||||
|
||||
[Throws=PaymentError]
|
||||
LNInvoice parse_invoice(string invoice);
|
||||
};
|
||||
|
||||
interface BindingLiquidSdk {
|
||||
|
||||
@@ -18,6 +18,10 @@ pub fn connect(req: ConnectRequest) -> Result<Arc<BindingLiquidSdk>, LiquidSdkEr
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_invoice(input: String) -> Result<LNInvoice, PaymentError> {
|
||||
LiquidSdk::parse_invoice(&input)
|
||||
}
|
||||
|
||||
pub struct BindingLiquidSdk {
|
||||
sdk: Arc<LiquidSdk>,
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ frb = ["dep:flutter_rust_bridge"]
|
||||
anyhow = { workspace = true }
|
||||
bip39 = { version = "2.0.0", features = ["serde"] }
|
||||
#boltz-client = { git = "https://github.com/SatoshiPortal/boltz-rust", rev = "a05731cc33030ada9ae14afcafe0cded22842ba6" }
|
||||
boltz-client = { git = "https://github.com/ok300/boltz-rust", branch = "ok300-breez-latest-05-27" }
|
||||
boltz-client = { git = "https://github.com/ok300/boltz-rust", branch = "ok300-breez-latest-05-28" }
|
||||
flutter_rust_bridge = { version = "=2.0.0-dev.36", features = ["chrono"], optional = true }
|
||||
log = "0.4.20"
|
||||
lwk_common = "0.5.1"
|
||||
|
||||
@@ -27,6 +27,10 @@ pub fn connect(req: ConnectRequest) -> Result<BindingLiquidSdk, LiquidSdkError>
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_invoice(input: String) -> Result<LNInvoice, PaymentError> {
|
||||
LiquidSdk::parse_invoice(&input)
|
||||
}
|
||||
|
||||
pub struct BindingLiquidSdk {
|
||||
sdk: Arc<LiquidSdk>,
|
||||
}
|
||||
|
||||
@@ -247,6 +247,45 @@ impl CstDecode<Vec<u8>> for *mut wire_cst_list_prim_u_8_strict {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<Vec<crate::model::RouteHint>> for *mut wire_cst_list_route_hint {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> Vec<crate::model::RouteHint> {
|
||||
let vec = unsafe {
|
||||
let wrap = flutter_rust_bridge::for_generated::box_from_leak_ptr(self);
|
||||
flutter_rust_bridge::for_generated::vec_from_leak_ptr(wrap.ptr, wrap.len)
|
||||
};
|
||||
vec.into_iter().map(CstDecode::cst_decode).collect()
|
||||
}
|
||||
}
|
||||
impl CstDecode<Vec<crate::model::RouteHintHop>> for *mut wire_cst_list_route_hint_hop {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> Vec<crate::model::RouteHintHop> {
|
||||
let vec = unsafe {
|
||||
let wrap = flutter_rust_bridge::for_generated::box_from_leak_ptr(self);
|
||||
flutter_rust_bridge::for_generated::vec_from_leak_ptr(wrap.ptr, wrap.len)
|
||||
};
|
||||
vec.into_iter().map(CstDecode::cst_decode).collect()
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::model::LNInvoice> for wire_cst_ln_invoice {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::model::LNInvoice {
|
||||
crate::model::LNInvoice {
|
||||
bolt11: self.bolt11.cst_decode(),
|
||||
network: self.network.cst_decode(),
|
||||
payee_pubkey: self.payee_pubkey.cst_decode(),
|
||||
payment_hash: self.payment_hash.cst_decode(),
|
||||
description: self.description.cst_decode(),
|
||||
description_hash: self.description_hash.cst_decode(),
|
||||
amount_msat: self.amount_msat.cst_decode(),
|
||||
timestamp: self.timestamp.cst_decode(),
|
||||
expiry: self.expiry.cst_decode(),
|
||||
routing_hints: self.routing_hints.cst_decode(),
|
||||
payment_secret: self.payment_secret.cst_decode(),
|
||||
min_final_cltv_expiry_delta: self.min_final_cltv_expiry_delta.cst_decode(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::model::Payment> for wire_cst_payment {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::model::Payment {
|
||||
@@ -362,6 +401,28 @@ impl CstDecode<crate::model::RestoreRequest> for wire_cst_restore_request {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::model::RouteHint> for wire_cst_route_hint {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::model::RouteHint {
|
||||
crate::model::RouteHint {
|
||||
hops: self.hops.cst_decode(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::model::RouteHintHop> for wire_cst_route_hint_hop {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::model::RouteHintHop {
|
||||
crate::model::RouteHintHop {
|
||||
src_node_id: self.src_node_id.cst_decode(),
|
||||
short_channel_id: self.short_channel_id.cst_decode(),
|
||||
fees_base_msat: self.fees_base_msat.cst_decode(),
|
||||
fees_proportional_millionths: self.fees_proportional_millionths.cst_decode(),
|
||||
cltv_expiry_delta: self.cltv_expiry_delta.cst_decode(),
|
||||
htlc_minimum_msat: self.htlc_minimum_msat.cst_decode(),
|
||||
htlc_maximum_msat: self.htlc_maximum_msat.cst_decode(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::model::SendPaymentResponse> for wire_cst_send_payment_response {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::model::SendPaymentResponse {
|
||||
@@ -449,6 +510,29 @@ impl Default for wire_cst_liquid_sdk_event {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_ln_invoice {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
bolt11: core::ptr::null_mut(),
|
||||
network: Default::default(),
|
||||
payee_pubkey: core::ptr::null_mut(),
|
||||
payment_hash: core::ptr::null_mut(),
|
||||
description: core::ptr::null_mut(),
|
||||
description_hash: core::ptr::null_mut(),
|
||||
amount_msat: core::ptr::null_mut(),
|
||||
timestamp: Default::default(),
|
||||
expiry: Default::default(),
|
||||
routing_hints: core::ptr::null_mut(),
|
||||
payment_secret: core::ptr::null_mut(),
|
||||
min_final_cltv_expiry_delta: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for wire_cst_ln_invoice {
|
||||
fn default() -> Self {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_payment {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
@@ -558,6 +642,36 @@ impl Default for wire_cst_restore_request {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_route_hint {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
hops: core::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for wire_cst_route_hint {
|
||||
fn default() -> Self {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_route_hint_hop {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
src_node_id: core::ptr::null_mut(),
|
||||
short_channel_id: Default::default(),
|
||||
fees_base_msat: Default::default(),
|
||||
fees_proportional_millionths: Default::default(),
|
||||
cltv_expiry_delta: Default::default(),
|
||||
htlc_minimum_msat: core::ptr::null_mut(),
|
||||
htlc_maximum_msat: core::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for wire_cst_route_hint_hop {
|
||||
fn default() -> Self {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_send_payment_response {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
@@ -683,6 +797,14 @@ pub extern "C" fn frbgen_breez_liquid_wire__crate__bindings__connect(
|
||||
wire__crate__bindings__connect_impl(port_, req)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn frbgen_breez_liquid_wire__crate__bindings__parse_invoice(
|
||||
port_: i64,
|
||||
input: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__bindings__parse_invoice_impl(port_, input)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn frbgen_breez_liquid_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(
|
||||
ptr: *const std::ffi::c_void,
|
||||
@@ -798,6 +920,34 @@ pub extern "C" fn frbgen_breez_liquid_cst_new_list_prim_u_8_strict(
|
||||
flutter_rust_bridge::for_generated::new_leak_box_ptr(ans)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn frbgen_breez_liquid_cst_new_list_route_hint(
|
||||
len: i32,
|
||||
) -> *mut wire_cst_list_route_hint {
|
||||
let wrap = wire_cst_list_route_hint {
|
||||
ptr: flutter_rust_bridge::for_generated::new_leak_vec_ptr(
|
||||
<wire_cst_route_hint>::new_with_null_ptr(),
|
||||
len,
|
||||
),
|
||||
len,
|
||||
};
|
||||
flutter_rust_bridge::for_generated::new_leak_box_ptr(wrap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn frbgen_breez_liquid_cst_new_list_route_hint_hop(
|
||||
len: i32,
|
||||
) -> *mut wire_cst_list_route_hint_hop {
|
||||
let wrap = wire_cst_list_route_hint_hop {
|
||||
ptr: flutter_rust_bridge::for_generated::new_leak_vec_ptr(
|
||||
<wire_cst_route_hint_hop>::new_with_null_ptr(),
|
||||
len,
|
||||
),
|
||||
len,
|
||||
};
|
||||
flutter_rust_bridge::for_generated::new_leak_box_ptr(wrap)
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_backup_request {
|
||||
@@ -901,6 +1051,34 @@ pub struct wire_cst_list_prim_u_8_strict {
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_list_route_hint {
|
||||
ptr: *mut wire_cst_route_hint,
|
||||
len: i32,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_list_route_hint_hop {
|
||||
ptr: *mut wire_cst_route_hint_hop,
|
||||
len: i32,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_ln_invoice {
|
||||
bolt11: *mut wire_cst_list_prim_u_8_strict,
|
||||
network: i32,
|
||||
payee_pubkey: *mut wire_cst_list_prim_u_8_strict,
|
||||
payment_hash: *mut wire_cst_list_prim_u_8_strict,
|
||||
description: *mut wire_cst_list_prim_u_8_strict,
|
||||
description_hash: *mut wire_cst_list_prim_u_8_strict,
|
||||
amount_msat: *mut u64,
|
||||
timestamp: u64,
|
||||
expiry: u64,
|
||||
routing_hints: *mut wire_cst_list_route_hint,
|
||||
payment_secret: *mut wire_cst_list_prim_u_8_strict,
|
||||
min_final_cltv_expiry_delta: u64,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_payment {
|
||||
tx_id: *mut wire_cst_list_prim_u_8_strict,
|
||||
swap_id: *mut wire_cst_list_prim_u_8_strict,
|
||||
@@ -990,6 +1168,22 @@ pub struct wire_cst_restore_request {
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_route_hint {
|
||||
hops: *mut wire_cst_list_route_hint_hop,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_route_hint_hop {
|
||||
src_node_id: *mut wire_cst_list_prim_u_8_strict,
|
||||
short_channel_id: u64,
|
||||
fees_base_msat: u32,
|
||||
fees_proportional_millionths: u32,
|
||||
cltv_expiry_delta: u64,
|
||||
htlc_minimum_msat: *mut u64,
|
||||
htlc_maximum_msat: *mut u64,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_send_payment_response {
|
||||
payment: wire_cst_payment,
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
||||
default_rust_auto_opaque = RustAutoOpaqueNom,
|
||||
);
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.0.0-dev.36";
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1552546000;
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 84136112;
|
||||
|
||||
// Section: executor
|
||||
|
||||
@@ -320,6 +320,24 @@ fn wire__crate__bindings__connect_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__bindings__parse_invoice_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
input: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "parse_invoice",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_input = input.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco((move || crate::bindings::parse_invoice(api_input))())
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Section: dart2rust
|
||||
|
||||
@@ -339,8 +357,8 @@ impl CstDecode<crate::model::Network> for i32 {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::model::Network {
|
||||
match self {
|
||||
0 => crate::model::Network::Liquid,
|
||||
1 => crate::model::Network::LiquidTestnet,
|
||||
0 => crate::model::Network::Mainnet,
|
||||
1 => crate::model::Network::Testnet,
|
||||
_ => unreachable!("Invalid variant for Network: {}", self),
|
||||
}
|
||||
}
|
||||
@@ -590,13 +608,69 @@ impl SseDecode for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for Vec<crate::model::RouteHint> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut len_ = <i32>::sse_decode(deserializer);
|
||||
let mut ans_ = vec![];
|
||||
for idx_ in 0..len_ {
|
||||
ans_.push(<crate::model::RouteHint>::sse_decode(deserializer));
|
||||
}
|
||||
return ans_;
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for Vec<crate::model::RouteHintHop> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut len_ = <i32>::sse_decode(deserializer);
|
||||
let mut ans_ = vec![];
|
||||
for idx_ in 0..len_ {
|
||||
ans_.push(<crate::model::RouteHintHop>::sse_decode(deserializer));
|
||||
}
|
||||
return ans_;
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::model::LNInvoice {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut var_bolt11 = <String>::sse_decode(deserializer);
|
||||
let mut var_network = <crate::model::Network>::sse_decode(deserializer);
|
||||
let mut var_payeePubkey = <String>::sse_decode(deserializer);
|
||||
let mut var_paymentHash = <String>::sse_decode(deserializer);
|
||||
let mut var_description = <Option<String>>::sse_decode(deserializer);
|
||||
let mut var_descriptionHash = <Option<String>>::sse_decode(deserializer);
|
||||
let mut var_amountMsat = <Option<u64>>::sse_decode(deserializer);
|
||||
let mut var_timestamp = <u64>::sse_decode(deserializer);
|
||||
let mut var_expiry = <u64>::sse_decode(deserializer);
|
||||
let mut var_routingHints = <Vec<crate::model::RouteHint>>::sse_decode(deserializer);
|
||||
let mut var_paymentSecret = <Vec<u8>>::sse_decode(deserializer);
|
||||
let mut var_minFinalCltvExpiryDelta = <u64>::sse_decode(deserializer);
|
||||
return crate::model::LNInvoice {
|
||||
bolt11: var_bolt11,
|
||||
network: var_network,
|
||||
payee_pubkey: var_payeePubkey,
|
||||
payment_hash: var_paymentHash,
|
||||
description: var_description,
|
||||
description_hash: var_descriptionHash,
|
||||
amount_msat: var_amountMsat,
|
||||
timestamp: var_timestamp,
|
||||
expiry: var_expiry,
|
||||
routing_hints: var_routingHints,
|
||||
payment_secret: var_paymentSecret,
|
||||
min_final_cltv_expiry_delta: var_minFinalCltvExpiryDelta,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::model::Network {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut inner = <i32>::sse_decode(deserializer);
|
||||
return match inner {
|
||||
0 => crate::model::Network::Liquid,
|
||||
1 => crate::model::Network::LiquidTestnet,
|
||||
0 => crate::model::Network::Mainnet,
|
||||
1 => crate::model::Network::Testnet,
|
||||
_ => unreachable!("Invalid variant for Network: {}", inner),
|
||||
};
|
||||
}
|
||||
@@ -804,6 +878,36 @@ impl SseDecode for crate::model::RestoreRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::model::RouteHint {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut var_hops = <Vec<crate::model::RouteHintHop>>::sse_decode(deserializer);
|
||||
return crate::model::RouteHint { hops: var_hops };
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::model::RouteHintHop {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut var_srcNodeId = <String>::sse_decode(deserializer);
|
||||
let mut var_shortChannelId = <u64>::sse_decode(deserializer);
|
||||
let mut var_feesBaseMsat = <u32>::sse_decode(deserializer);
|
||||
let mut var_feesProportionalMillionths = <u32>::sse_decode(deserializer);
|
||||
let mut var_cltvExpiryDelta = <u64>::sse_decode(deserializer);
|
||||
let mut var_htlcMinimumMsat = <Option<u64>>::sse_decode(deserializer);
|
||||
let mut var_htlcMaximumMsat = <Option<u64>>::sse_decode(deserializer);
|
||||
return crate::model::RouteHintHop {
|
||||
src_node_id: var_srcNodeId,
|
||||
short_channel_id: var_shortChannelId,
|
||||
fees_base_msat: var_feesBaseMsat,
|
||||
fees_proportional_millionths: var_feesProportionalMillionths,
|
||||
cltv_expiry_delta: var_cltvExpiryDelta,
|
||||
htlc_minimum_msat: var_htlcMinimumMsat,
|
||||
htlc_maximum_msat: var_htlcMaximumMsat,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::model::SendPaymentResponse {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
@@ -1011,11 +1115,39 @@ impl flutter_rust_bridge::IntoIntoDart<crate::model::LiquidSdkEvent>
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::model::LNInvoice {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
[
|
||||
self.bolt11.into_into_dart().into_dart(),
|
||||
self.network.into_into_dart().into_dart(),
|
||||
self.payee_pubkey.into_into_dart().into_dart(),
|
||||
self.payment_hash.into_into_dart().into_dart(),
|
||||
self.description.into_into_dart().into_dart(),
|
||||
self.description_hash.into_into_dart().into_dart(),
|
||||
self.amount_msat.into_into_dart().into_dart(),
|
||||
self.timestamp.into_into_dart().into_dart(),
|
||||
self.expiry.into_into_dart().into_dart(),
|
||||
self.routing_hints.into_into_dart().into_dart(),
|
||||
self.payment_secret.into_into_dart().into_dart(),
|
||||
self.min_final_cltv_expiry_delta
|
||||
.into_into_dart()
|
||||
.into_dart(),
|
||||
]
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::model::LNInvoice {}
|
||||
impl flutter_rust_bridge::IntoIntoDart<crate::model::LNInvoice> for crate::model::LNInvoice {
|
||||
fn into_into_dart(self) -> crate::model::LNInvoice {
|
||||
self
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::model::Network {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
match self {
|
||||
Self::Liquid => 0.into_dart(),
|
||||
Self::LiquidTestnet => 1.into_dart(),
|
||||
Self::Mainnet => 0.into_dart(),
|
||||
Self::Testnet => 1.into_dart(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1232,6 +1364,41 @@ impl flutter_rust_bridge::IntoIntoDart<crate::model::RestoreRequest>
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::model::RouteHint {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
[self.hops.into_into_dart().into_dart()].into_dart()
|
||||
}
|
||||
}
|
||||
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::model::RouteHint {}
|
||||
impl flutter_rust_bridge::IntoIntoDart<crate::model::RouteHint> for crate::model::RouteHint {
|
||||
fn into_into_dart(self) -> crate::model::RouteHint {
|
||||
self
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::model::RouteHintHop {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
[
|
||||
self.src_node_id.into_into_dart().into_dart(),
|
||||
self.short_channel_id.into_into_dart().into_dart(),
|
||||
self.fees_base_msat.into_into_dart().into_dart(),
|
||||
self.fees_proportional_millionths
|
||||
.into_into_dart()
|
||||
.into_dart(),
|
||||
self.cltv_expiry_delta.into_into_dart().into_dart(),
|
||||
self.htlc_minimum_msat.into_into_dart().into_dart(),
|
||||
self.htlc_maximum_msat.into_into_dart().into_dart(),
|
||||
]
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::model::RouteHintHop {}
|
||||
impl flutter_rust_bridge::IntoIntoDart<crate::model::RouteHintHop> for crate::model::RouteHintHop {
|
||||
fn into_into_dart(self) -> crate::model::RouteHintHop {
|
||||
self
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::model::SendPaymentResponse {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
[self.payment.into_into_dart().into_dart()].into_dart()
|
||||
@@ -1403,13 +1570,51 @@ impl SseEncode for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for Vec<crate::model::RouteHint> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<i32>::sse_encode(self.len() as _, serializer);
|
||||
for item in self {
|
||||
<crate::model::RouteHint>::sse_encode(item, serializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for Vec<crate::model::RouteHintHop> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<i32>::sse_encode(self.len() as _, serializer);
|
||||
for item in self {
|
||||
<crate::model::RouteHintHop>::sse_encode(item, serializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::model::LNInvoice {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<String>::sse_encode(self.bolt11, serializer);
|
||||
<crate::model::Network>::sse_encode(self.network, serializer);
|
||||
<String>::sse_encode(self.payee_pubkey, serializer);
|
||||
<String>::sse_encode(self.payment_hash, serializer);
|
||||
<Option<String>>::sse_encode(self.description, serializer);
|
||||
<Option<String>>::sse_encode(self.description_hash, serializer);
|
||||
<Option<u64>>::sse_encode(self.amount_msat, serializer);
|
||||
<u64>::sse_encode(self.timestamp, serializer);
|
||||
<u64>::sse_encode(self.expiry, serializer);
|
||||
<Vec<crate::model::RouteHint>>::sse_encode(self.routing_hints, serializer);
|
||||
<Vec<u8>>::sse_encode(self.payment_secret, serializer);
|
||||
<u64>::sse_encode(self.min_final_cltv_expiry_delta, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::model::Network {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<i32>::sse_encode(
|
||||
match self {
|
||||
crate::model::Network::Liquid => 0,
|
||||
crate::model::Network::LiquidTestnet => 1,
|
||||
crate::model::Network::Mainnet => 0,
|
||||
crate::model::Network::Testnet => 1,
|
||||
_ => {
|
||||
unimplemented!("");
|
||||
}
|
||||
@@ -1587,6 +1792,26 @@ impl SseEncode for crate::model::RestoreRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::model::RouteHint {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<Vec<crate::model::RouteHintHop>>::sse_encode(self.hops, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::model::RouteHintHop {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<String>::sse_encode(self.src_node_id, serializer);
|
||||
<u64>::sse_encode(self.short_channel_id, serializer);
|
||||
<u32>::sse_encode(self.fees_base_msat, serializer);
|
||||
<u32>::sse_encode(self.fees_proportional_millionths, serializer);
|
||||
<u64>::sse_encode(self.cltv_expiry_delta, serializer);
|
||||
<Option<u64>>::sse_encode(self.htlc_minimum_msat, serializer);
|
||||
<Option<u64>>::sse_encode(self.htlc_maximum_msat, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::model::SendPaymentResponse {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
|
||||
@@ -3,7 +3,7 @@ use boltz_client::network::Chain;
|
||||
use boltz_client::swaps::boltzv2::{
|
||||
CreateReverseResponse, CreateSubmarineResponse, Leaf, SwapTree,
|
||||
};
|
||||
use boltz_client::Keypair;
|
||||
use boltz_client::{Keypair, ToHex};
|
||||
use lwk_signer::SwSigner;
|
||||
use lwk_wollet::{ElectrumUrl, ElementsNetwork, WolletDescriptor};
|
||||
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef};
|
||||
@@ -15,15 +15,17 @@ use crate::utils;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize)]
|
||||
pub enum Network {
|
||||
Liquid,
|
||||
LiquidTestnet,
|
||||
/// Mainnet Bitcoin and Liquid chains
|
||||
Mainnet,
|
||||
/// Testnet Bitcoin and Liquid chains
|
||||
Testnet,
|
||||
}
|
||||
|
||||
impl From<Network> for ElementsNetwork {
|
||||
fn from(value: Network) -> Self {
|
||||
match value {
|
||||
Network::Liquid => ElementsNetwork::Liquid,
|
||||
Network::LiquidTestnet => ElementsNetwork::LiquidTestnet,
|
||||
Network::Mainnet => ElementsNetwork::Liquid,
|
||||
Network::Testnet => ElementsNetwork::LiquidTestnet,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,8 +33,8 @@ impl From<Network> for ElementsNetwork {
|
||||
impl From<Network> for Chain {
|
||||
fn from(value: Network) -> Self {
|
||||
match value {
|
||||
Network::Liquid => Chain::Liquid,
|
||||
Network::LiquidTestnet => Chain::LiquidTestnet,
|
||||
Network::Mainnet => Chain::Liquid,
|
||||
Network::Testnet => Chain::LiquidTestnet,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,8 +44,22 @@ impl TryFrom<&str> for Network {
|
||||
|
||||
fn try_from(value: &str) -> Result<Network, anyhow::Error> {
|
||||
match value.to_lowercase().as_str() {
|
||||
"mainnet" => Ok(Network::Liquid),
|
||||
"testnet" => Ok(Network::LiquidTestnet),
|
||||
"mainnet" => Ok(Network::Mainnet),
|
||||
"testnet" => Ok(Network::Testnet),
|
||||
_ => Err(anyhow!("Invalid network")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<boltz_client::lightning_invoice::Currency> for Network {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(
|
||||
value: boltz_client::lightning_invoice::Currency,
|
||||
) -> Result<Network, anyhow::Error> {
|
||||
match value {
|
||||
boltz_client::lightning_invoice::Currency::Bitcoin => Ok(Network::Mainnet),
|
||||
boltz_client::lightning_invoice::Currency::BitcoinTestnet => Ok(Network::Testnet),
|
||||
_ => Err(anyhow!("Invalid network")),
|
||||
}
|
||||
}
|
||||
@@ -88,8 +104,8 @@ impl LiquidSdkOptions {
|
||||
pub(crate) fn get_electrum_url(&self) -> ElectrumUrl {
|
||||
self.electrum_url.clone().unwrap_or({
|
||||
let (url, validate_domain, tls) = match &self.network {
|
||||
Network::Liquid => ("blockstream.info:995", true, true),
|
||||
Network::LiquidTestnet => ("blockstream.info:465", true, true),
|
||||
Network::Mainnet => ("blockstream.info:995", true, true),
|
||||
Network::Testnet => ("blockstream.info:465", true, true),
|
||||
};
|
||||
ElectrumUrl::new(url, tls, validate_domain)
|
||||
})
|
||||
@@ -539,6 +555,69 @@ impl Payment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper for a BOLT11 LN invoice
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct LNInvoice {
|
||||
pub bolt11: String,
|
||||
pub network: Network,
|
||||
pub payee_pubkey: String,
|
||||
pub payment_hash: String,
|
||||
pub description: Option<String>,
|
||||
pub description_hash: Option<String>,
|
||||
pub amount_msat: Option<u64>,
|
||||
pub timestamp: u64,
|
||||
pub expiry: u64,
|
||||
pub routing_hints: Vec<RouteHint>,
|
||||
pub payment_secret: Vec<u8>,
|
||||
pub min_final_cltv_expiry_delta: u64,
|
||||
}
|
||||
|
||||
/// A route hint for a LN payment
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct RouteHint {
|
||||
pub hops: Vec<RouteHintHop>,
|
||||
}
|
||||
|
||||
impl RouteHint {
|
||||
pub fn from_ldk_hint(hint: &boltz_client::lightning_invoice::RouteHint) -> RouteHint {
|
||||
let mut hops = Vec::new();
|
||||
for hop in hint.0.iter() {
|
||||
let pubkey_res = hop.src_node_id.serialize().to_hex();
|
||||
|
||||
let router_hop = RouteHintHop {
|
||||
src_node_id: pubkey_res,
|
||||
short_channel_id: hop.short_channel_id,
|
||||
fees_base_msat: hop.fees.base_msat,
|
||||
fees_proportional_millionths: hop.fees.proportional_millionths,
|
||||
cltv_expiry_delta: u64::from(hop.cltv_expiry_delta),
|
||||
htlc_minimum_msat: hop.htlc_minimum_msat,
|
||||
htlc_maximum_msat: hop.htlc_maximum_msat,
|
||||
};
|
||||
hops.push(router_hop);
|
||||
}
|
||||
RouteHint { hops }
|
||||
}
|
||||
}
|
||||
|
||||
/// Details of a specific hop in a larger route hint
|
||||
#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RouteHintHop {
|
||||
/// The node_id of the non-target end of the route
|
||||
pub src_node_id: String,
|
||||
/// The short_channel_id of this channel
|
||||
pub short_channel_id: u64,
|
||||
/// The fees which must be paid to use this channel
|
||||
pub fees_base_msat: u32,
|
||||
pub fees_proportional_millionths: u32,
|
||||
|
||||
/// The difference in CLTV values between this node and the next node.
|
||||
pub cltv_expiry_delta: u64,
|
||||
/// The minimum value, in msat, which must be relayed to the next hop.
|
||||
pub htlc_minimum_msat: Option<u64>,
|
||||
/// The maximum value in msat available for routing with a single HTLC.
|
||||
pub htlc_maximum_msat: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
struct InternalLeaf {
|
||||
pub output: String,
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::model::Network;
|
||||
impl Persister {
|
||||
pub(crate) fn get_default_backup_path(&self) -> PathBuf {
|
||||
self.main_db_dir.join(match self.network {
|
||||
Network::Liquid => "backup.sql",
|
||||
Network::LiquidTestnet => "backup-testnet.sql",
|
||||
Network::Mainnet => "backup.sql",
|
||||
Network::Testnet => "backup-testnet.sql",
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ impl Persister {
|
||||
|
||||
pub(crate) fn get_connection(&self) -> Result<Connection> {
|
||||
let db_file = match self.network {
|
||||
Liquid => "storage.sql",
|
||||
LiquidTestnet => "storage-testnet.sql",
|
||||
Mainnet => "storage.sql",
|
||||
Testnet => "storage-testnet.sql",
|
||||
};
|
||||
Ok(Connection::open(self.main_db_dir.join(db_file))?)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
use std::time::Instant;
|
||||
use std::{fs, path::PathBuf, str::FromStr, sync::Arc, time::Duration};
|
||||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
time::{Duration, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use boltz_client::lightning_invoice::Bolt11InvoiceDescription;
|
||||
use boltz_client::network::Chain;
|
||||
use boltz_client::swaps::boltzv2;
|
||||
use boltz_client::ToHex;
|
||||
@@ -65,7 +72,7 @@ pub struct LiquidSdk {
|
||||
|
||||
impl LiquidSdk {
|
||||
pub async fn connect(req: ConnectRequest) -> Result<Arc<LiquidSdk>> {
|
||||
let is_mainnet = req.network == Network::Liquid;
|
||||
let is_mainnet = req.network == Network::Mainnet;
|
||||
let signer = SwSigner::new(&req.mnemonic, is_mainnet)?;
|
||||
let descriptor = LiquidSdk::get_descriptor(&signer, req.network)?;
|
||||
|
||||
@@ -155,9 +162,13 @@ impl LiquidSdk {
|
||||
}
|
||||
});
|
||||
|
||||
self.status_stream.clone().track_pending_swaps(self.shutdown_receiver.clone()).await;
|
||||
self.status_stream
|
||||
.clone()
|
||||
.track_pending_swaps(self.shutdown_receiver.clone())
|
||||
.await;
|
||||
|
||||
self.track_swap_updates(self.shutdown_receiver.clone()).await;
|
||||
self.track_swap_updates(self.shutdown_receiver.clone())
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -233,7 +244,7 @@ impl LiquidSdk {
|
||||
}
|
||||
|
||||
fn get_descriptor(signer: &SwSigner, network: Network) -> Result<WolletDescriptor> {
|
||||
let is_mainnet = network == Network::Liquid;
|
||||
let is_mainnet = network == Network::Mainnet;
|
||||
let descriptor_str = singlesig_desc(
|
||||
signer,
|
||||
Singlesig::Wpkh,
|
||||
@@ -658,8 +669,8 @@ impl LiquidSdk {
|
||||
|
||||
pub(crate) fn boltz_url_v2(network: Network) -> &'static str {
|
||||
match network {
|
||||
Network::LiquidTestnet => BOLTZ_TESTNET_URL_V2,
|
||||
Network::Liquid => BOLTZ_MAINNET_URL_V2,
|
||||
Network::Testnet => BOLTZ_TESTNET_URL_V2,
|
||||
Network::Mainnet => BOLTZ_MAINNET_URL_V2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -705,8 +716,8 @@ impl LiquidSdk {
|
||||
.map_err(|_| PaymentError::InvalidInvoice)?;
|
||||
|
||||
match (invoice.network().to_string().as_str(), self.network) {
|
||||
("bitcoin", Network::Liquid) => {}
|
||||
("testnet", Network::LiquidTestnet) => {}
|
||||
("bitcoin", Network::Mainnet) => {}
|
||||
("testnet", Network::Testnet) => {}
|
||||
_ => return Err(PaymentError::InvalidInvoice),
|
||||
}
|
||||
|
||||
@@ -740,8 +751,8 @@ impl LiquidSdk {
|
||||
// TODO Replace this with own address when LWK supports taproot
|
||||
// https://github.com/Blockstream/lwk/issues/31
|
||||
let temp_p2tr_addr = match self.network {
|
||||
Network::Liquid => "lq1pqvzxvqhrf54dd4sny4cag7497pe38252qefk46t92frs7us8r80ja9ha8r5me09nn22m4tmdqp5p4wafq3s59cql3v9n45t5trwtxrmxfsyxjnstkctj",
|
||||
Network::LiquidTestnet => "tlq1pq0wqu32e2xacxeyps22x8gjre4qk3u6r70pj4r62hzczxeyz8x3yxucrpn79zy28plc4x37aaf33kwt6dz2nn6gtkya6h02mwpzy4eh69zzexq7cf5y5"
|
||||
Network::Mainnet => "lq1pqvzxvqhrf54dd4sny4cag7497pe38252qefk46t92frs7us8r80ja9ha8r5me09nn22m4tmdqp5p4wafq3s59cql3v9n45t5trwtxrmxfsyxjnstkctj",
|
||||
Network::Testnet => "tlq1pq0wqu32e2xacxeyps22x8gjre4qk3u6r70pj4r62hzczxeyz8x3yxucrpn79zy28plc4x37aaf33kwt6dz2nn6gtkya6h02mwpzy4eh69zzexq7cf5y5"
|
||||
};
|
||||
|
||||
// Create a throw-away tx similar to the lockup tx, in order to estimate fees
|
||||
@@ -884,8 +895,8 @@ impl LiquidSdk {
|
||||
Amount::from_sat(self.get_broadcast_fee_estimation(amount_sat).await?);
|
||||
let client = self.boltz_client_v2();
|
||||
let is_lowball = match self.network {
|
||||
Network::Liquid => None,
|
||||
Network::LiquidTestnet => Some((&client, boltz_client::network::Chain::LiquidTestnet)),
|
||||
Network::Mainnet => None,
|
||||
Network::Testnet => Some((&client, boltz_client::network::Chain::LiquidTestnet)),
|
||||
};
|
||||
|
||||
match self
|
||||
@@ -1399,6 +1410,54 @@ impl LiquidSdk {
|
||||
err: format!("Could not create LiquidSwapKey: {e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_invoice(input: &str) -> Result<LNInvoice, PaymentError> {
|
||||
let input = input
|
||||
.strip_prefix("lightning:")
|
||||
.or(input.strip_prefix("LIGHTNING:"))
|
||||
.unwrap_or(input);
|
||||
let invoice = Bolt11Invoice::from_str(input).map_err(|_| PaymentError::InvalidInvoice)?;
|
||||
|
||||
// Try to take payee pubkey from the tagged fields, if doesn't exist recover it from the signature
|
||||
let payee_pubkey: String = match invoice.payee_pub_key() {
|
||||
Some(key) => key.serialize().to_hex(),
|
||||
None => invoice.recover_payee_pub_key().serialize().to_hex(),
|
||||
};
|
||||
let description = match invoice.description() {
|
||||
Bolt11InvoiceDescription::Direct(msg) => Some(msg.to_string()),
|
||||
Bolt11InvoiceDescription::Hash(_) => None,
|
||||
};
|
||||
let description_hash = match invoice.description() {
|
||||
Bolt11InvoiceDescription::Direct(_) => None,
|
||||
Bolt11InvoiceDescription::Hash(h) => Some(h.0.to_string()),
|
||||
};
|
||||
let timestamp = invoice
|
||||
.timestamp()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_err(|_| PaymentError::InvalidInvoice)?
|
||||
.as_secs();
|
||||
let routing_hints = invoice
|
||||
.route_hints()
|
||||
.iter()
|
||||
.map(RouteHint::from_ldk_hint)
|
||||
.collect();
|
||||
|
||||
let res = LNInvoice {
|
||||
bolt11: input.to_string(),
|
||||
network: invoice.currency().try_into()?,
|
||||
payee_pubkey,
|
||||
payment_hash: invoice.payment_hash().to_hex(),
|
||||
description,
|
||||
description_hash,
|
||||
amount_msat: invoice.amount_milli_satoshis(),
|
||||
timestamp,
|
||||
expiry: invoice.expiry_time().as_secs(),
|
||||
routing_hints,
|
||||
payment_secret: invoice.payment_secret().0.to_vec(),
|
||||
min_final_cltv_expiry_delta: invoice.min_final_cltv_expiry_delta(),
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -1438,7 +1497,7 @@ mod tests {
|
||||
let sdk = LiquidSdk::connect(ConnectRequest {
|
||||
mnemonic: TEST_MNEMONIC.to_string(),
|
||||
data_dir: Some(data_dir_str),
|
||||
network: Network::LiquidTestnet,
|
||||
network: Network::Testnet,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1456,13 +1515,15 @@ mod tests {
|
||||
let sdk = LiquidSdk::connect(ConnectRequest {
|
||||
mnemonic: TEST_MNEMONIC.to_string(),
|
||||
data_dir: Some(data_dir_str),
|
||||
network: Network::LiquidTestnet,
|
||||
network: Network::Testnet,
|
||||
})
|
||||
.await?;
|
||||
|
||||
let prepare_response = sdk.prepare_receive_payment(&PrepareReceiveRequest {
|
||||
let prepare_response = sdk
|
||||
.prepare_receive_payment(&PrepareReceiveRequest {
|
||||
payer_amount_sat: 1_000,
|
||||
}).await?;
|
||||
})
|
||||
.await?;
|
||||
sdk.receive_payment(&prepare_response).await?;
|
||||
assert!(!list_pending(&sdk).await?.is_empty());
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
Future<BindingLiquidSdk> connect({required ConnectRequest req, dynamic hint}) =>
|
||||
RustLib.instance.api.crateBindingsConnect(req: req, hint: hint);
|
||||
|
||||
Future<LNInvoice> parseInvoice({required String input, dynamic hint}) =>
|
||||
RustLib.instance.api.crateBindingsParseInvoice(input: input, hint: hint);
|
||||
|
||||
// Rust type: RustOpaqueNom<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<BindingLiquidSdk>>
|
||||
@sealed
|
||||
class BindingLiquidSdk extends RustOpaque {
|
||||
|
||||
@@ -53,7 +53,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
||||
String get codegenVersion => '2.0.0-dev.36';
|
||||
|
||||
@override
|
||||
int get rustContentHash => -1552546000;
|
||||
int get rustContentHash => 84136112;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig(
|
||||
stem: 'breez_liquid_sdk',
|
||||
@@ -98,6 +98,8 @@ abstract class RustLibApi extends BaseApi {
|
||||
|
||||
Future<BindingLiquidSdk> crateBindingsConnect({required ConnectRequest req, dynamic hint});
|
||||
|
||||
Future<LNInvoice> crateBindingsParseInvoice({required String input, dynamic hint});
|
||||
|
||||
RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_BindingLiquidSdk;
|
||||
|
||||
RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_BindingLiquidSdk;
|
||||
@@ -456,6 +458,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["req"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<LNInvoice> crateBindingsParseInvoice({required String input, dynamic hint}) {
|
||||
return handler.executeNormal(NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(input);
|
||||
return wire.wire__crate__bindings__parse_invoice(port_, arg0);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_ln_invoice,
|
||||
decodeErrorData: dco_decode_payment_error,
|
||||
),
|
||||
constMeta: kCrateBindingsParseInvoiceConstMeta,
|
||||
argValues: [input],
|
||||
apiImpl: this,
|
||||
hint: hint,
|
||||
));
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateBindingsParseInvoiceConstMeta => const TaskConstMeta(
|
||||
debugName: "parse_invoice",
|
||||
argNames: ["input"],
|
||||
);
|
||||
|
||||
RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_BindingLiquidSdk => wire
|
||||
.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk;
|
||||
|
||||
@@ -678,6 +703,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return raw as Uint8List;
|
||||
}
|
||||
|
||||
@protected
|
||||
List<RouteHint> dco_decode_list_route_hint(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return (raw as List<dynamic>).map(dco_decode_route_hint).toList();
|
||||
}
|
||||
|
||||
@protected
|
||||
List<RouteHintHop> dco_decode_list_route_hint_hop(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return (raw as List<dynamic>).map(dco_decode_route_hint_hop).toList();
|
||||
}
|
||||
|
||||
@protected
|
||||
LNInvoice dco_decode_ln_invoice(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
final arr = raw as List<dynamic>;
|
||||
if (arr.length != 12) throw Exception('unexpected arr length: expect 12 but see ${arr.length}');
|
||||
return LNInvoice(
|
||||
bolt11: dco_decode_String(arr[0]),
|
||||
network: dco_decode_network(arr[1]),
|
||||
payeePubkey: dco_decode_String(arr[2]),
|
||||
paymentHash: dco_decode_String(arr[3]),
|
||||
description: dco_decode_opt_String(arr[4]),
|
||||
descriptionHash: dco_decode_opt_String(arr[5]),
|
||||
amountMsat: dco_decode_opt_box_autoadd_u_64(arr[6]),
|
||||
timestamp: dco_decode_u_64(arr[7]),
|
||||
expiry: dco_decode_u_64(arr[8]),
|
||||
routingHints: dco_decode_list_route_hint(arr[9]),
|
||||
paymentSecret: dco_decode_list_prim_u_8_strict(arr[10]),
|
||||
minFinalCltvExpiryDelta: dco_decode_u_64(arr[11]),
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
Network dco_decode_network(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -836,6 +894,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
RouteHint dco_decode_route_hint(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
final arr = raw as List<dynamic>;
|
||||
if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}');
|
||||
return RouteHint(
|
||||
hops: dco_decode_list_route_hint_hop(arr[0]),
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
RouteHintHop dco_decode_route_hint_hop(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
final arr = raw as List<dynamic>;
|
||||
if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}');
|
||||
return RouteHintHop(
|
||||
srcNodeId: dco_decode_String(arr[0]),
|
||||
shortChannelId: dco_decode_u_64(arr[1]),
|
||||
feesBaseMsat: dco_decode_u_32(arr[2]),
|
||||
feesProportionalMillionths: dco_decode_u_32(arr[3]),
|
||||
cltvExpiryDelta: dco_decode_u_64(arr[4]),
|
||||
htlcMinimumMsat: dco_decode_opt_box_autoadd_u_64(arr[5]),
|
||||
htlcMaximumMsat: dco_decode_opt_box_autoadd_u_64(arr[6]),
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
SendPaymentResponse dco_decode_send_payment_response(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -1089,6 +1173,60 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return deserializer.buffer.getUint8List(len_);
|
||||
}
|
||||
|
||||
@protected
|
||||
List<RouteHint> sse_decode_list_route_hint(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
var len_ = sse_decode_i_32(deserializer);
|
||||
var ans_ = <RouteHint>[];
|
||||
for (var idx_ = 0; idx_ < len_; ++idx_) {
|
||||
ans_.add(sse_decode_route_hint(deserializer));
|
||||
}
|
||||
return ans_;
|
||||
}
|
||||
|
||||
@protected
|
||||
List<RouteHintHop> sse_decode_list_route_hint_hop(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
var len_ = sse_decode_i_32(deserializer);
|
||||
var ans_ = <RouteHintHop>[];
|
||||
for (var idx_ = 0; idx_ < len_; ++idx_) {
|
||||
ans_.add(sse_decode_route_hint_hop(deserializer));
|
||||
}
|
||||
return ans_;
|
||||
}
|
||||
|
||||
@protected
|
||||
LNInvoice sse_decode_ln_invoice(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var var_bolt11 = sse_decode_String(deserializer);
|
||||
var var_network = sse_decode_network(deserializer);
|
||||
var var_payeePubkey = sse_decode_String(deserializer);
|
||||
var var_paymentHash = sse_decode_String(deserializer);
|
||||
var var_description = sse_decode_opt_String(deserializer);
|
||||
var var_descriptionHash = sse_decode_opt_String(deserializer);
|
||||
var var_amountMsat = sse_decode_opt_box_autoadd_u_64(deserializer);
|
||||
var var_timestamp = sse_decode_u_64(deserializer);
|
||||
var var_expiry = sse_decode_u_64(deserializer);
|
||||
var var_routingHints = sse_decode_list_route_hint(deserializer);
|
||||
var var_paymentSecret = sse_decode_list_prim_u_8_strict(deserializer);
|
||||
var var_minFinalCltvExpiryDelta = sse_decode_u_64(deserializer);
|
||||
return LNInvoice(
|
||||
bolt11: var_bolt11,
|
||||
network: var_network,
|
||||
payeePubkey: var_payeePubkey,
|
||||
paymentHash: var_paymentHash,
|
||||
description: var_description,
|
||||
descriptionHash: var_descriptionHash,
|
||||
amountMsat: var_amountMsat,
|
||||
timestamp: var_timestamp,
|
||||
expiry: var_expiry,
|
||||
routingHints: var_routingHints,
|
||||
paymentSecret: var_paymentSecret,
|
||||
minFinalCltvExpiryDelta: var_minFinalCltvExpiryDelta);
|
||||
}
|
||||
|
||||
@protected
|
||||
Network sse_decode_network(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1246,6 +1384,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return RestoreRequest(backupPath: var_backupPath);
|
||||
}
|
||||
|
||||
@protected
|
||||
RouteHint sse_decode_route_hint(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var var_hops = sse_decode_list_route_hint_hop(deserializer);
|
||||
return RouteHint(hops: var_hops);
|
||||
}
|
||||
|
||||
@protected
|
||||
RouteHintHop sse_decode_route_hint_hop(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var var_srcNodeId = sse_decode_String(deserializer);
|
||||
var var_shortChannelId = sse_decode_u_64(deserializer);
|
||||
var var_feesBaseMsat = sse_decode_u_32(deserializer);
|
||||
var var_feesProportionalMillionths = sse_decode_u_32(deserializer);
|
||||
var var_cltvExpiryDelta = sse_decode_u_64(deserializer);
|
||||
var var_htlcMinimumMsat = sse_decode_opt_box_autoadd_u_64(deserializer);
|
||||
var var_htlcMaximumMsat = sse_decode_opt_box_autoadd_u_64(deserializer);
|
||||
return RouteHintHop(
|
||||
srcNodeId: var_srcNodeId,
|
||||
shortChannelId: var_shortChannelId,
|
||||
feesBaseMsat: var_feesBaseMsat,
|
||||
feesProportionalMillionths: var_feesProportionalMillionths,
|
||||
cltvExpiryDelta: var_cltvExpiryDelta,
|
||||
htlcMinimumMsat: var_htlcMinimumMsat,
|
||||
htlcMaximumMsat: var_htlcMaximumMsat);
|
||||
}
|
||||
|
||||
@protected
|
||||
SendPaymentResponse sse_decode_send_payment_response(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1550,6 +1715,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
serializer.buffer.putUint8List(self);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_list_route_hint(List<RouteHint> self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_i_32(self.length, serializer);
|
||||
for (final item in self) {
|
||||
sse_encode_route_hint(item, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_list_route_hint_hop(List<RouteHintHop> self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_i_32(self.length, serializer);
|
||||
for (final item in self) {
|
||||
sse_encode_route_hint_hop(item, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_ln_invoice(LNInvoice self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_String(self.bolt11, serializer);
|
||||
sse_encode_network(self.network, serializer);
|
||||
sse_encode_String(self.payeePubkey, serializer);
|
||||
sse_encode_String(self.paymentHash, serializer);
|
||||
sse_encode_opt_String(self.description, serializer);
|
||||
sse_encode_opt_String(self.descriptionHash, serializer);
|
||||
sse_encode_opt_box_autoadd_u_64(self.amountMsat, serializer);
|
||||
sse_encode_u_64(self.timestamp, serializer);
|
||||
sse_encode_u_64(self.expiry, serializer);
|
||||
sse_encode_list_route_hint(self.routingHints, serializer);
|
||||
sse_encode_list_prim_u_8_strict(self.paymentSecret, serializer);
|
||||
sse_encode_u_64(self.minFinalCltvExpiryDelta, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_network(Network self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1681,6 +1881,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
sse_encode_opt_String(self.backupPath, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_route_hint(RouteHint self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_list_route_hint_hop(self.hops, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_route_hint_hop(RouteHintHop self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_String(self.srcNodeId, serializer);
|
||||
sse_encode_u_64(self.shortChannelId, serializer);
|
||||
sse_encode_u_32(self.feesBaseMsat, serializer);
|
||||
sse_encode_u_32(self.feesProportionalMillionths, serializer);
|
||||
sse_encode_u_64(self.cltvExpiryDelta, serializer);
|
||||
sse_encode_opt_box_autoadd_u_64(self.htlcMinimumMsat, serializer);
|
||||
sse_encode_opt_box_autoadd_u_64(self.htlcMaximumMsat, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_send_payment_response(SendPaymentResponse self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
@@ -103,6 +103,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<RouteHint> dco_decode_list_route_hint(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<RouteHintHop> dco_decode_list_route_hint_hop(dynamic raw);
|
||||
|
||||
@protected
|
||||
LNInvoice dco_decode_ln_invoice(dynamic raw);
|
||||
|
||||
@protected
|
||||
Network dco_decode_network(dynamic raw);
|
||||
|
||||
@@ -142,6 +151,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
RestoreRequest dco_decode_restore_request(dynamic raw);
|
||||
|
||||
@protected
|
||||
RouteHint dco_decode_route_hint(dynamic raw);
|
||||
|
||||
@protected
|
||||
RouteHintHop dco_decode_route_hint_hop(dynamic raw);
|
||||
|
||||
@protected
|
||||
SendPaymentResponse dco_decode_send_payment_response(dynamic raw);
|
||||
|
||||
@@ -240,6 +255,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<RouteHint> sse_decode_list_route_hint(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<RouteHintHop> sse_decode_list_route_hint_hop(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
LNInvoice sse_decode_ln_invoice(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Network sse_decode_network(SseDeserializer deserializer);
|
||||
|
||||
@@ -279,6 +303,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
RestoreRequest sse_decode_restore_request(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
RouteHint sse_decode_route_hint(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
RouteHintHop sse_decode_route_hint_hop(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
SendPaymentResponse sse_decode_send_payment_response(SseDeserializer deserializer);
|
||||
|
||||
@@ -411,6 +441,26 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
return ans;
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<wire_cst_list_route_hint> cst_encode_list_route_hint(List<RouteHint> raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
final ans = wire.cst_new_list_route_hint(raw.length);
|
||||
for (var i = 0; i < raw.length; ++i) {
|
||||
cst_api_fill_to_wire_route_hint(raw[i], ans.ref.ptr[i]);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<wire_cst_list_route_hint_hop> cst_encode_list_route_hint_hop(List<RouteHintHop> raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
final ans = wire.cst_new_list_route_hint_hop(raw.length);
|
||||
for (var i = 0; i < raw.length; ++i) {
|
||||
cst_api_fill_to_wire_route_hint_hop(raw[i], ans.ref.ptr[i]);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> cst_encode_opt_String(String? raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
@@ -575,6 +625,22 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_ln_invoice(LNInvoice apiObj, wire_cst_ln_invoice wireObj) {
|
||||
wireObj.bolt11 = cst_encode_String(apiObj.bolt11);
|
||||
wireObj.network = cst_encode_network(apiObj.network);
|
||||
wireObj.payee_pubkey = cst_encode_String(apiObj.payeePubkey);
|
||||
wireObj.payment_hash = cst_encode_String(apiObj.paymentHash);
|
||||
wireObj.description = cst_encode_opt_String(apiObj.description);
|
||||
wireObj.description_hash = cst_encode_opt_String(apiObj.descriptionHash);
|
||||
wireObj.amount_msat = cst_encode_opt_box_autoadd_u_64(apiObj.amountMsat);
|
||||
wireObj.timestamp = cst_encode_u_64(apiObj.timestamp);
|
||||
wireObj.expiry = cst_encode_u_64(apiObj.expiry);
|
||||
wireObj.routing_hints = cst_encode_list_route_hint(apiObj.routingHints);
|
||||
wireObj.payment_secret = cst_encode_list_prim_u_8_strict(apiObj.paymentSecret);
|
||||
wireObj.min_final_cltv_expiry_delta = cst_encode_u_64(apiObj.minFinalCltvExpiryDelta);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_payment(Payment apiObj, wire_cst_payment wireObj) {
|
||||
wireObj.tx_id = cst_encode_String(apiObj.txId);
|
||||
@@ -695,6 +761,22 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
wireObj.backup_path = cst_encode_opt_String(apiObj.backupPath);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_route_hint(RouteHint apiObj, wire_cst_route_hint wireObj) {
|
||||
wireObj.hops = cst_encode_list_route_hint_hop(apiObj.hops);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_route_hint_hop(RouteHintHop apiObj, wire_cst_route_hint_hop wireObj) {
|
||||
wireObj.src_node_id = cst_encode_String(apiObj.srcNodeId);
|
||||
wireObj.short_channel_id = cst_encode_u_64(apiObj.shortChannelId);
|
||||
wireObj.fees_base_msat = cst_encode_u_32(apiObj.feesBaseMsat);
|
||||
wireObj.fees_proportional_millionths = cst_encode_u_32(apiObj.feesProportionalMillionths);
|
||||
wireObj.cltv_expiry_delta = cst_encode_u_64(apiObj.cltvExpiryDelta);
|
||||
wireObj.htlc_minimum_msat = cst_encode_opt_box_autoadd_u_64(apiObj.htlcMinimumMsat);
|
||||
wireObj.htlc_maximum_msat = cst_encode_opt_box_autoadd_u_64(apiObj.htlcMaximumMsat);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_send_payment_response(
|
||||
SendPaymentResponse apiObj, wire_cst_send_payment_response wireObj) {
|
||||
@@ -816,6 +898,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_route_hint(List<RouteHint> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_route_hint_hop(List<RouteHintHop> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_ln_invoice(LNInvoice self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_network(Network self, SseSerializer serializer);
|
||||
|
||||
@@ -855,6 +946,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_encode_restore_request(RestoreRequest self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_route_hint(RouteHint self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_route_hint_hop(RouteHintHop self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_send_payment_response(SendPaymentResponse self, SseSerializer serializer);
|
||||
|
||||
@@ -1149,6 +1246,22 @@ class RustLibWire implements BaseWire {
|
||||
late final _wire__crate__bindings__connect = _wire__crate__bindings__connectPtr
|
||||
.asFunction<void Function(int, ffi.Pointer<wire_cst_connect_request>)>();
|
||||
|
||||
void wire__crate__bindings__parse_invoice(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> input,
|
||||
) {
|
||||
return _wire__crate__bindings__parse_invoice(
|
||||
port_,
|
||||
input,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__bindings__parse_invoicePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64, ffi.Pointer<wire_cst_list_prim_u_8_strict>)>>(
|
||||
'frbgen_breez_liquid_wire__crate__bindings__parse_invoice');
|
||||
late final _wire__crate__bindings__parse_invoice = _wire__crate__bindings__parse_invoicePtr
|
||||
.asFunction<void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)>();
|
||||
|
||||
void
|
||||
rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(
|
||||
ffi.Pointer<ffi.Void> ptr,
|
||||
@@ -1313,6 +1426,34 @@ class RustLibWire implements BaseWire {
|
||||
late final _cst_new_list_prim_u_8_strict =
|
||||
_cst_new_list_prim_u_8_strictPtr.asFunction<ffi.Pointer<wire_cst_list_prim_u_8_strict> Function(int)>();
|
||||
|
||||
ffi.Pointer<wire_cst_list_route_hint> cst_new_list_route_hint(
|
||||
int len,
|
||||
) {
|
||||
return _cst_new_list_route_hint(
|
||||
len,
|
||||
);
|
||||
}
|
||||
|
||||
late final _cst_new_list_route_hintPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Pointer<wire_cst_list_route_hint> Function(ffi.Int32)>>(
|
||||
'frbgen_breez_liquid_cst_new_list_route_hint');
|
||||
late final _cst_new_list_route_hint =
|
||||
_cst_new_list_route_hintPtr.asFunction<ffi.Pointer<wire_cst_list_route_hint> Function(int)>();
|
||||
|
||||
ffi.Pointer<wire_cst_list_route_hint_hop> cst_new_list_route_hint_hop(
|
||||
int len,
|
||||
) {
|
||||
return _cst_new_list_route_hint_hop(
|
||||
len,
|
||||
);
|
||||
}
|
||||
|
||||
late final _cst_new_list_route_hint_hopPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Pointer<wire_cst_list_route_hint_hop> Function(ffi.Int32)>>(
|
||||
'frbgen_breez_liquid_cst_new_list_route_hint_hop');
|
||||
late final _cst_new_list_route_hint_hop =
|
||||
_cst_new_list_route_hint_hopPtr.asFunction<ffi.Pointer<wire_cst_list_route_hint_hop> Function(int)>();
|
||||
|
||||
int dummy_method_to_enforce_bundling() {
|
||||
return _dummy_method_to_enforce_bundling();
|
||||
}
|
||||
@@ -1416,6 +1557,44 @@ final class wire_cst_list_payment extends ffi.Struct {
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_route_hint_hop extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> src_node_id;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int short_channel_id;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int fees_base_msat;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int fees_proportional_millionths;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int cltv_expiry_delta;
|
||||
|
||||
external ffi.Pointer<ffi.Uint64> htlc_minimum_msat;
|
||||
|
||||
external ffi.Pointer<ffi.Uint64> htlc_maximum_msat;
|
||||
}
|
||||
|
||||
final class wire_cst_list_route_hint_hop extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_route_hint_hop> ptr;
|
||||
|
||||
@ffi.Int32()
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_route_hint extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_route_hint_hop> hops;
|
||||
}
|
||||
|
||||
final class wire_cst_list_route_hint extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_route_hint> ptr;
|
||||
|
||||
@ffi.Int32()
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_get_info_response extends ffi.Struct {
|
||||
@ffi.Uint64()
|
||||
external int balance_sat;
|
||||
@@ -1489,6 +1668,36 @@ final class wire_cst_liquid_sdk_event extends ffi.Struct {
|
||||
external LiquidSdkEventKind kind;
|
||||
}
|
||||
|
||||
final class wire_cst_ln_invoice extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> bolt11;
|
||||
|
||||
@ffi.Int32()
|
||||
external int network;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> payee_pubkey;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> payment_hash;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> description;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> description_hash;
|
||||
|
||||
external ffi.Pointer<ffi.Uint64> amount_msat;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int timestamp;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int expiry;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_route_hint> routing_hints;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> payment_secret;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int min_final_cltv_expiry_delta;
|
||||
}
|
||||
|
||||
final class wire_cst_PaymentError_Generic extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> err;
|
||||
}
|
||||
|
||||
@@ -126,9 +126,76 @@ sealed class LiquidSdkEvent with _$LiquidSdkEvent {
|
||||
const factory LiquidSdkEvent.synced() = LiquidSdkEvent_Synced;
|
||||
}
|
||||
|
||||
/// Wrapper for a BOLT11 LN invoice
|
||||
class LNInvoice {
|
||||
final String bolt11;
|
||||
final Network network;
|
||||
final String payeePubkey;
|
||||
final String paymentHash;
|
||||
final String? description;
|
||||
final String? descriptionHash;
|
||||
final BigInt? amountMsat;
|
||||
final BigInt timestamp;
|
||||
final BigInt expiry;
|
||||
final List<RouteHint> routingHints;
|
||||
final Uint8List paymentSecret;
|
||||
final BigInt minFinalCltvExpiryDelta;
|
||||
|
||||
const LNInvoice({
|
||||
required this.bolt11,
|
||||
required this.network,
|
||||
required this.payeePubkey,
|
||||
required this.paymentHash,
|
||||
this.description,
|
||||
this.descriptionHash,
|
||||
this.amountMsat,
|
||||
required this.timestamp,
|
||||
required this.expiry,
|
||||
required this.routingHints,
|
||||
required this.paymentSecret,
|
||||
required this.minFinalCltvExpiryDelta,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
bolt11.hashCode ^
|
||||
network.hashCode ^
|
||||
payeePubkey.hashCode ^
|
||||
paymentHash.hashCode ^
|
||||
description.hashCode ^
|
||||
descriptionHash.hashCode ^
|
||||
amountMsat.hashCode ^
|
||||
timestamp.hashCode ^
|
||||
expiry.hashCode ^
|
||||
routingHints.hashCode ^
|
||||
paymentSecret.hashCode ^
|
||||
minFinalCltvExpiryDelta.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is LNInvoice &&
|
||||
runtimeType == other.runtimeType &&
|
||||
bolt11 == other.bolt11 &&
|
||||
network == other.network &&
|
||||
payeePubkey == other.payeePubkey &&
|
||||
paymentHash == other.paymentHash &&
|
||||
description == other.description &&
|
||||
descriptionHash == other.descriptionHash &&
|
||||
amountMsat == other.amountMsat &&
|
||||
timestamp == other.timestamp &&
|
||||
expiry == other.expiry &&
|
||||
routingHints == other.routingHints &&
|
||||
paymentSecret == other.paymentSecret &&
|
||||
minFinalCltvExpiryDelta == other.minFinalCltvExpiryDelta;
|
||||
}
|
||||
|
||||
enum Network {
|
||||
liquid,
|
||||
liquidTestnet,
|
||||
/// Mainnet Bitcoin and Liquid chains
|
||||
mainnet,
|
||||
|
||||
/// Testnet Bitcoin and Liquid chains
|
||||
testnet,
|
||||
;
|
||||
}
|
||||
|
||||
@@ -386,6 +453,77 @@ class RestoreRequest {
|
||||
other is RestoreRequest && runtimeType == other.runtimeType && backupPath == other.backupPath;
|
||||
}
|
||||
|
||||
/// A route hint for a LN payment
|
||||
class RouteHint {
|
||||
final List<RouteHintHop> hops;
|
||||
|
||||
const RouteHint({
|
||||
required this.hops,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode => hops.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) || other is RouteHint && runtimeType == other.runtimeType && hops == other.hops;
|
||||
}
|
||||
|
||||
/// Details of a specific hop in a larger route hint
|
||||
class RouteHintHop {
|
||||
/// The node_id of the non-target end of the route
|
||||
final String srcNodeId;
|
||||
|
||||
/// The short_channel_id of this channel
|
||||
final BigInt shortChannelId;
|
||||
|
||||
/// The fees which must be paid to use this channel
|
||||
final int feesBaseMsat;
|
||||
final int feesProportionalMillionths;
|
||||
|
||||
/// The difference in CLTV values between this node and the next node.
|
||||
final BigInt cltvExpiryDelta;
|
||||
|
||||
/// The minimum value, in msat, which must be relayed to the next hop.
|
||||
final BigInt? htlcMinimumMsat;
|
||||
|
||||
/// The maximum value in msat available for routing with a single HTLC.
|
||||
final BigInt? htlcMaximumMsat;
|
||||
|
||||
const RouteHintHop({
|
||||
required this.srcNodeId,
|
||||
required this.shortChannelId,
|
||||
required this.feesBaseMsat,
|
||||
required this.feesProportionalMillionths,
|
||||
required this.cltvExpiryDelta,
|
||||
this.htlcMinimumMsat,
|
||||
this.htlcMaximumMsat,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
srcNodeId.hashCode ^
|
||||
shortChannelId.hashCode ^
|
||||
feesBaseMsat.hashCode ^
|
||||
feesProportionalMillionths.hashCode ^
|
||||
cltvExpiryDelta.hashCode ^
|
||||
htlcMinimumMsat.hashCode ^
|
||||
htlcMaximumMsat.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is RouteHintHop &&
|
||||
runtimeType == other.runtimeType &&
|
||||
srcNodeId == other.srcNodeId &&
|
||||
shortChannelId == other.shortChannelId &&
|
||||
feesBaseMsat == other.feesBaseMsat &&
|
||||
feesProportionalMillionths == other.feesProportionalMillionths &&
|
||||
cltvExpiryDelta == other.cltvExpiryDelta &&
|
||||
htlcMinimumMsat == other.htlcMinimumMsat &&
|
||||
htlcMaximumMsat == other.htlcMaximumMsat;
|
||||
}
|
||||
|
||||
class SendPaymentResponse {
|
||||
final Payment payment;
|
||||
|
||||
|
||||
@@ -77,6 +77,23 @@ class FlutterBreezLiquidBindings {
|
||||
_frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_backupPtr
|
||||
.asFunction<void Function(int, int, ffi.Pointer<wire_cst_backup_request>)>();
|
||||
|
||||
void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_disconnect(
|
||||
int port_,
|
||||
int that,
|
||||
) {
|
||||
return _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_disconnect(
|
||||
port_,
|
||||
that,
|
||||
);
|
||||
}
|
||||
|
||||
late final _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_disconnectPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64, ffi.UintPtr)>>(
|
||||
'frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_disconnect');
|
||||
late final _frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_disconnect =
|
||||
_frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_disconnectPtr
|
||||
.asFunction<void Function(int, int)>();
|
||||
|
||||
void frbgen_breez_liquid_wire__crate__bindings__BindingLiquidSdk_empty_wallet_cache(
|
||||
int port_,
|
||||
int that,
|
||||
@@ -266,6 +283,23 @@ class FlutterBreezLiquidBindings {
|
||||
_frbgen_breez_liquid_wire__crate__bindings__connectPtr
|
||||
.asFunction<void Function(int, ffi.Pointer<wire_cst_connect_request>)>();
|
||||
|
||||
void frbgen_breez_liquid_wire__crate__bindings__parse_invoice(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> input,
|
||||
) {
|
||||
return _frbgen_breez_liquid_wire__crate__bindings__parse_invoice(
|
||||
port_,
|
||||
input,
|
||||
);
|
||||
}
|
||||
|
||||
late final _frbgen_breez_liquid_wire__crate__bindings__parse_invoicePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64, ffi.Pointer<wire_cst_list_prim_u_8_strict>)>>(
|
||||
'frbgen_breez_liquid_wire__crate__bindings__parse_invoice');
|
||||
late final _frbgen_breez_liquid_wire__crate__bindings__parse_invoice =
|
||||
_frbgen_breez_liquid_wire__crate__bindings__parse_invoicePtr
|
||||
.asFunction<void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)>();
|
||||
|
||||
void
|
||||
frbgen_breez_liquid_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerBindingLiquidSdk(
|
||||
ffi.Pointer<ffi.Void> ptr,
|
||||
@@ -443,6 +477,35 @@ class FlutterBreezLiquidBindings {
|
||||
_frbgen_breez_liquid_cst_new_list_prim_u_8_strictPtr
|
||||
.asFunction<ffi.Pointer<wire_cst_list_prim_u_8_strict> Function(int)>();
|
||||
|
||||
ffi.Pointer<wire_cst_list_route_hint> frbgen_breez_liquid_cst_new_list_route_hint(
|
||||
int len,
|
||||
) {
|
||||
return _frbgen_breez_liquid_cst_new_list_route_hint(
|
||||
len,
|
||||
);
|
||||
}
|
||||
|
||||
late final _frbgen_breez_liquid_cst_new_list_route_hintPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Pointer<wire_cst_list_route_hint> Function(ffi.Int32)>>(
|
||||
'frbgen_breez_liquid_cst_new_list_route_hint');
|
||||
late final _frbgen_breez_liquid_cst_new_list_route_hint = _frbgen_breez_liquid_cst_new_list_route_hintPtr
|
||||
.asFunction<ffi.Pointer<wire_cst_list_route_hint> Function(int)>();
|
||||
|
||||
ffi.Pointer<wire_cst_list_route_hint_hop> frbgen_breez_liquid_cst_new_list_route_hint_hop(
|
||||
int len,
|
||||
) {
|
||||
return _frbgen_breez_liquid_cst_new_list_route_hint_hop(
|
||||
len,
|
||||
);
|
||||
}
|
||||
|
||||
late final _frbgen_breez_liquid_cst_new_list_route_hint_hopPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Pointer<wire_cst_list_route_hint_hop> Function(ffi.Int32)>>(
|
||||
'frbgen_breez_liquid_cst_new_list_route_hint_hop');
|
||||
late final _frbgen_breez_liquid_cst_new_list_route_hint_hop =
|
||||
_frbgen_breez_liquid_cst_new_list_route_hint_hopPtr
|
||||
.asFunction<ffi.Pointer<wire_cst_list_route_hint_hop> Function(int)>();
|
||||
|
||||
int dummy_method_to_enforce_bundling() {
|
||||
return _dummy_method_to_enforce_bundling();
|
||||
}
|
||||
@@ -557,6 +620,44 @@ final class wire_cst_list_payment extends ffi.Struct {
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_route_hint_hop extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> src_node_id;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int short_channel_id;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int fees_base_msat;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int fees_proportional_millionths;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int cltv_expiry_delta;
|
||||
|
||||
external ffi.Pointer<ffi.Uint64> htlc_minimum_msat;
|
||||
|
||||
external ffi.Pointer<ffi.Uint64> htlc_maximum_msat;
|
||||
}
|
||||
|
||||
final class wire_cst_list_route_hint_hop extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_route_hint_hop> ptr;
|
||||
|
||||
@ffi.Int32()
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_route_hint extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_route_hint_hop> hops;
|
||||
}
|
||||
|
||||
final class wire_cst_list_route_hint extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_route_hint> ptr;
|
||||
|
||||
@ffi.Int32()
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_get_info_response extends ffi.Struct {
|
||||
@ffi.Uint64()
|
||||
external int balance_sat;
|
||||
@@ -630,6 +731,36 @@ final class wire_cst_liquid_sdk_event extends ffi.Struct {
|
||||
external LiquidSdkEventKind kind;
|
||||
}
|
||||
|
||||
final class wire_cst_ln_invoice extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> bolt11;
|
||||
|
||||
@ffi.Int32()
|
||||
external int network;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> payee_pubkey;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> payment_hash;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> description;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> description_hash;
|
||||
|
||||
external ffi.Pointer<ffi.Uint64> amount_msat;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int timestamp;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int expiry;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_route_hint> routing_hints;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> payment_secret;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int min_final_cltv_expiry_delta;
|
||||
}
|
||||
|
||||
final class wire_cst_PaymentError_Generic extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> err;
|
||||
}
|
||||
|
||||
@@ -152,6 +152,80 @@ fun asGetInfoResponseList(arr: ReadableArray): List<GetInfoResponse> {
|
||||
return list
|
||||
}
|
||||
|
||||
fun asLnInvoice(lnInvoice: ReadableMap): LnInvoice? {
|
||||
if (!validateMandatoryFields(
|
||||
lnInvoice,
|
||||
arrayOf(
|
||||
"bolt11",
|
||||
"network",
|
||||
"payeePubkey",
|
||||
"paymentHash",
|
||||
"timestamp",
|
||||
"expiry",
|
||||
"routingHints",
|
||||
"paymentSecret",
|
||||
"minFinalCltvExpiryDelta",
|
||||
),
|
||||
)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
val bolt11 = lnInvoice.getString("bolt11")!!
|
||||
val network = lnInvoice.getString("network")?.let { asNetwork(it) }!!
|
||||
val payeePubkey = lnInvoice.getString("payeePubkey")!!
|
||||
val paymentHash = lnInvoice.getString("paymentHash")!!
|
||||
val description = if (hasNonNullKey(lnInvoice, "description")) lnInvoice.getString("description") else null
|
||||
val descriptionHash = if (hasNonNullKey(lnInvoice, "descriptionHash")) lnInvoice.getString("descriptionHash") else null
|
||||
val amountMsat = if (hasNonNullKey(lnInvoice, "amountMsat")) lnInvoice.getDouble("amountMsat").toULong() else null
|
||||
val timestamp = lnInvoice.getDouble("timestamp").toULong()
|
||||
val expiry = lnInvoice.getDouble("expiry").toULong()
|
||||
val routingHints = lnInvoice.getArray("routingHints")?.let { asRouteHintList(it) }!!
|
||||
val paymentSecret = lnInvoice.getArray("paymentSecret")?.let { asUByteList(it) }!!
|
||||
val minFinalCltvExpiryDelta = lnInvoice.getDouble("minFinalCltvExpiryDelta").toULong()
|
||||
return LnInvoice(
|
||||
bolt11,
|
||||
network,
|
||||
payeePubkey,
|
||||
paymentHash,
|
||||
description,
|
||||
descriptionHash,
|
||||
amountMsat,
|
||||
timestamp,
|
||||
expiry,
|
||||
routingHints,
|
||||
paymentSecret,
|
||||
minFinalCltvExpiryDelta,
|
||||
)
|
||||
}
|
||||
|
||||
fun readableMapOf(lnInvoice: LnInvoice): ReadableMap {
|
||||
return readableMapOf(
|
||||
"bolt11" to lnInvoice.bolt11,
|
||||
"network" to lnInvoice.network.name.lowercase(),
|
||||
"payeePubkey" to lnInvoice.payeePubkey,
|
||||
"paymentHash" to lnInvoice.paymentHash,
|
||||
"description" to lnInvoice.description,
|
||||
"descriptionHash" to lnInvoice.descriptionHash,
|
||||
"amountMsat" to lnInvoice.amountMsat,
|
||||
"timestamp" to lnInvoice.timestamp,
|
||||
"expiry" to lnInvoice.expiry,
|
||||
"routingHints" to readableArrayOf(lnInvoice.routingHints),
|
||||
"paymentSecret" to readableArrayOf(lnInvoice.paymentSecret),
|
||||
"minFinalCltvExpiryDelta" to lnInvoice.minFinalCltvExpiryDelta,
|
||||
)
|
||||
}
|
||||
|
||||
fun asLnInvoiceList(arr: ReadableArray): List<LnInvoice> {
|
||||
val list = ArrayList<LnInvoice>()
|
||||
for (value in arr.toArrayList()) {
|
||||
when (value) {
|
||||
is ReadableMap -> list.add(asLnInvoice(value)!!)
|
||||
else -> throw LiquidSdkException.Generic(errUnexpectedType("${value::class.java.name}"))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
fun asPayment(payment: ReadableMap): Payment? {
|
||||
if (!validateMandatoryFields(
|
||||
payment,
|
||||
@@ -424,6 +498,94 @@ fun asRestoreRequestList(arr: ReadableArray): List<RestoreRequest> {
|
||||
return list
|
||||
}
|
||||
|
||||
fun asRouteHint(routeHint: ReadableMap): RouteHint? {
|
||||
if (!validateMandatoryFields(
|
||||
routeHint,
|
||||
arrayOf(
|
||||
"hops",
|
||||
),
|
||||
)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
val hops = routeHint.getArray("hops")?.let { asRouteHintHopList(it) }!!
|
||||
return RouteHint(
|
||||
hops,
|
||||
)
|
||||
}
|
||||
|
||||
fun readableMapOf(routeHint: RouteHint): ReadableMap {
|
||||
return readableMapOf(
|
||||
"hops" to readableArrayOf(routeHint.hops),
|
||||
)
|
||||
}
|
||||
|
||||
fun asRouteHintList(arr: ReadableArray): List<RouteHint> {
|
||||
val list = ArrayList<RouteHint>()
|
||||
for (value in arr.toArrayList()) {
|
||||
when (value) {
|
||||
is ReadableMap -> list.add(asRouteHint(value)!!)
|
||||
else -> throw LiquidSdkException.Generic(errUnexpectedType("${value::class.java.name}"))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
fun asRouteHintHop(routeHintHop: ReadableMap): RouteHintHop? {
|
||||
if (!validateMandatoryFields(
|
||||
routeHintHop,
|
||||
arrayOf(
|
||||
"srcNodeId",
|
||||
"shortChannelId",
|
||||
"feesBaseMsat",
|
||||
"feesProportionalMillionths",
|
||||
"cltvExpiryDelta",
|
||||
),
|
||||
)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
val srcNodeId = routeHintHop.getString("srcNodeId")!!
|
||||
val shortChannelId = routeHintHop.getDouble("shortChannelId").toULong()
|
||||
val feesBaseMsat = routeHintHop.getInt("feesBaseMsat").toUInt()
|
||||
val feesProportionalMillionths = routeHintHop.getInt("feesProportionalMillionths").toUInt()
|
||||
val cltvExpiryDelta = routeHintHop.getDouble("cltvExpiryDelta").toULong()
|
||||
val htlcMinimumMsat = if (hasNonNullKey(routeHintHop, "htlcMinimumMsat")) routeHintHop.getDouble("htlcMinimumMsat").toULong() else null
|
||||
val htlcMaximumMsat = if (hasNonNullKey(routeHintHop, "htlcMaximumMsat")) routeHintHop.getDouble("htlcMaximumMsat").toULong() else null
|
||||
return RouteHintHop(
|
||||
srcNodeId,
|
||||
shortChannelId,
|
||||
feesBaseMsat,
|
||||
feesProportionalMillionths,
|
||||
cltvExpiryDelta,
|
||||
htlcMinimumMsat,
|
||||
htlcMaximumMsat,
|
||||
)
|
||||
}
|
||||
|
||||
fun readableMapOf(routeHintHop: RouteHintHop): ReadableMap {
|
||||
return readableMapOf(
|
||||
"srcNodeId" to routeHintHop.srcNodeId,
|
||||
"shortChannelId" to routeHintHop.shortChannelId,
|
||||
"feesBaseMsat" to routeHintHop.feesBaseMsat,
|
||||
"feesProportionalMillionths" to routeHintHop.feesProportionalMillionths,
|
||||
"cltvExpiryDelta" to routeHintHop.cltvExpiryDelta,
|
||||
"htlcMinimumMsat" to routeHintHop.htlcMinimumMsat,
|
||||
"htlcMaximumMsat" to routeHintHop.htlcMaximumMsat,
|
||||
)
|
||||
}
|
||||
|
||||
fun asRouteHintHopList(arr: ReadableArray): List<RouteHintHop> {
|
||||
val list = ArrayList<RouteHintHop>()
|
||||
for (value in arr.toArrayList()) {
|
||||
when (value) {
|
||||
is ReadableMap -> list.add(asRouteHintHop(value)!!)
|
||||
else -> throw LiquidSdkException.Generic(errUnexpectedType("${value::class.java.name}"))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
fun asSendPaymentResponse(sendPaymentResponse: ReadableMap): SendPaymentResponse? {
|
||||
if (!validateMandatoryFields(
|
||||
sendPaymentResponse,
|
||||
@@ -607,6 +769,9 @@ fun pushToArray(
|
||||
when (value) {
|
||||
null -> array.pushNull()
|
||||
is Payment -> array.pushMap(readableMapOf(value))
|
||||
is RouteHint -> array.pushMap(readableMapOf(value))
|
||||
is RouteHintHop -> array.pushMap(readableMapOf(value))
|
||||
is UByte -> array.pushInt(value.toInt())
|
||||
is Array<*> -> array.pushArray(readableArrayOf(value.asIterable()))
|
||||
is List<*> -> array.pushArray(readableArrayOf(value))
|
||||
else -> throw LiquidSdkException.Generic(errUnexpectedType("${value::class.java.name}"))
|
||||
|
||||
@@ -40,6 +40,21 @@ class BreezLiquidSDKModule(reactContext: ReactApplicationContext) : ReactContext
|
||||
@ReactMethod
|
||||
fun removeListeners(count: Int) {}
|
||||
|
||||
@ReactMethod
|
||||
fun parseInvoice(
|
||||
invoice: String,
|
||||
promise: Promise,
|
||||
) {
|
||||
executor.execute {
|
||||
try {
|
||||
val res = parseInvoice(invoice)
|
||||
promise.resolve(readableMapOf(res))
|
||||
} catch (e: Exception) {
|
||||
promise.reject(e.javaClass.simpleName.replace("Exception", "Error"), e.message, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun connect(
|
||||
req: ReadableMap,
|
||||
|
||||
@@ -167,6 +167,110 @@ enum BreezLiquidSDKMapper {
|
||||
return getInfoResponseList.map { v -> [String: Any?] in dictionaryOf(getInfoResponse: v) }
|
||||
}
|
||||
|
||||
static func asLnInvoice(lnInvoice: [String: Any?]) throws -> LnInvoice {
|
||||
guard let bolt11 = lnInvoice["bolt11"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "bolt11", typeName: "LnInvoice"))
|
||||
}
|
||||
guard let networkTmp = lnInvoice["network"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "network", typeName: "LnInvoice"))
|
||||
}
|
||||
let network = try asNetwork(network: networkTmp)
|
||||
|
||||
guard let payeePubkey = lnInvoice["payeePubkey"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "payeePubkey", typeName: "LnInvoice"))
|
||||
}
|
||||
guard let paymentHash = lnInvoice["paymentHash"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "paymentHash", typeName: "LnInvoice"))
|
||||
}
|
||||
var description: String?
|
||||
if hasNonNilKey(data: lnInvoice, key: "description") {
|
||||
guard let descriptionTmp = lnInvoice["description"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "description"))
|
||||
}
|
||||
description = descriptionTmp
|
||||
}
|
||||
var descriptionHash: String?
|
||||
if hasNonNilKey(data: lnInvoice, key: "descriptionHash") {
|
||||
guard let descriptionHashTmp = lnInvoice["descriptionHash"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "descriptionHash"))
|
||||
}
|
||||
descriptionHash = descriptionHashTmp
|
||||
}
|
||||
var amountMsat: UInt64?
|
||||
if hasNonNilKey(data: lnInvoice, key: "amountMsat") {
|
||||
guard let amountMsatTmp = lnInvoice["amountMsat"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "amountMsat"))
|
||||
}
|
||||
amountMsat = amountMsatTmp
|
||||
}
|
||||
guard let timestamp = lnInvoice["timestamp"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "timestamp", typeName: "LnInvoice"))
|
||||
}
|
||||
guard let expiry = lnInvoice["expiry"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "expiry", typeName: "LnInvoice"))
|
||||
}
|
||||
guard let routingHintsTmp = lnInvoice["routingHints"] as? [[String: Any?]] else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "routingHints", typeName: "LnInvoice"))
|
||||
}
|
||||
let routingHints = try asRouteHintList(arr: routingHintsTmp)
|
||||
|
||||
guard let paymentSecret = lnInvoice["paymentSecret"] as? [UInt8] else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "paymentSecret", typeName: "LnInvoice"))
|
||||
}
|
||||
guard let minFinalCltvExpiryDelta = lnInvoice["minFinalCltvExpiryDelta"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "minFinalCltvExpiryDelta", typeName: "LnInvoice"))
|
||||
}
|
||||
|
||||
return LnInvoice(
|
||||
bolt11: bolt11,
|
||||
network: network,
|
||||
payeePubkey: payeePubkey,
|
||||
paymentHash: paymentHash,
|
||||
description: description,
|
||||
descriptionHash: descriptionHash,
|
||||
amountMsat: amountMsat,
|
||||
timestamp: timestamp,
|
||||
expiry: expiry,
|
||||
routingHints: routingHints,
|
||||
paymentSecret: paymentSecret,
|
||||
minFinalCltvExpiryDelta: minFinalCltvExpiryDelta
|
||||
)
|
||||
}
|
||||
|
||||
static func dictionaryOf(lnInvoice: LnInvoice) -> [String: Any?] {
|
||||
return [
|
||||
"bolt11": lnInvoice.bolt11,
|
||||
"network": valueOf(network: lnInvoice.network),
|
||||
"payeePubkey": lnInvoice.payeePubkey,
|
||||
"paymentHash": lnInvoice.paymentHash,
|
||||
"description": lnInvoice.description == nil ? nil : lnInvoice.description,
|
||||
"descriptionHash": lnInvoice.descriptionHash == nil ? nil : lnInvoice.descriptionHash,
|
||||
"amountMsat": lnInvoice.amountMsat == nil ? nil : lnInvoice.amountMsat,
|
||||
"timestamp": lnInvoice.timestamp,
|
||||
"expiry": lnInvoice.expiry,
|
||||
"routingHints": arrayOf(routeHintList: lnInvoice.routingHints),
|
||||
"paymentSecret": lnInvoice.paymentSecret,
|
||||
"minFinalCltvExpiryDelta": lnInvoice.minFinalCltvExpiryDelta,
|
||||
]
|
||||
}
|
||||
|
||||
static func asLnInvoiceList(arr: [Any]) throws -> [LnInvoice] {
|
||||
var list = [LnInvoice]()
|
||||
for value in arr {
|
||||
if let val = value as? [String: Any?] {
|
||||
var lnInvoice = try asLnInvoice(lnInvoice: val)
|
||||
list.append(lnInvoice)
|
||||
} else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedType(typeName: "LnInvoice"))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
static func arrayOf(lnInvoiceList: [LnInvoice]) -> [Any] {
|
||||
return lnInvoiceList.map { v -> [String: Any?] in dictionaryOf(lnInvoice: v) }
|
||||
}
|
||||
|
||||
static func asPayment(payment: [String: Any?]) throws -> Payment {
|
||||
guard let txId = payment["txId"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "txId", typeName: "Payment"))
|
||||
@@ -482,6 +586,110 @@ enum BreezLiquidSDKMapper {
|
||||
return restoreRequestList.map { v -> [String: Any?] in dictionaryOf(restoreRequest: v) }
|
||||
}
|
||||
|
||||
static func asRouteHint(routeHint: [String: Any?]) throws -> RouteHint {
|
||||
guard let hopsTmp = routeHint["hops"] as? [[String: Any?]] else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "hops", typeName: "RouteHint"))
|
||||
}
|
||||
let hops = try asRouteHintHopList(arr: hopsTmp)
|
||||
|
||||
return RouteHint(
|
||||
hops: hops)
|
||||
}
|
||||
|
||||
static func dictionaryOf(routeHint: RouteHint) -> [String: Any?] {
|
||||
return [
|
||||
"hops": arrayOf(routeHintHopList: routeHint.hops),
|
||||
]
|
||||
}
|
||||
|
||||
static func asRouteHintList(arr: [Any]) throws -> [RouteHint] {
|
||||
var list = [RouteHint]()
|
||||
for value in arr {
|
||||
if let val = value as? [String: Any?] {
|
||||
var routeHint = try asRouteHint(routeHint: val)
|
||||
list.append(routeHint)
|
||||
} else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedType(typeName: "RouteHint"))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
static func arrayOf(routeHintList: [RouteHint]) -> [Any] {
|
||||
return routeHintList.map { v -> [String: Any?] in dictionaryOf(routeHint: v) }
|
||||
}
|
||||
|
||||
static func asRouteHintHop(routeHintHop: [String: Any?]) throws -> RouteHintHop {
|
||||
guard let srcNodeId = routeHintHop["srcNodeId"] as? String else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "srcNodeId", typeName: "RouteHintHop"))
|
||||
}
|
||||
guard let shortChannelId = routeHintHop["shortChannelId"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "shortChannelId", typeName: "RouteHintHop"))
|
||||
}
|
||||
guard let feesBaseMsat = routeHintHop["feesBaseMsat"] as? UInt32 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "feesBaseMsat", typeName: "RouteHintHop"))
|
||||
}
|
||||
guard let feesProportionalMillionths = routeHintHop["feesProportionalMillionths"] as? UInt32 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "feesProportionalMillionths", typeName: "RouteHintHop"))
|
||||
}
|
||||
guard let cltvExpiryDelta = routeHintHop["cltvExpiryDelta"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "cltvExpiryDelta", typeName: "RouteHintHop"))
|
||||
}
|
||||
var htlcMinimumMsat: UInt64?
|
||||
if hasNonNilKey(data: routeHintHop, key: "htlcMinimumMsat") {
|
||||
guard let htlcMinimumMsatTmp = routeHintHop["htlcMinimumMsat"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "htlcMinimumMsat"))
|
||||
}
|
||||
htlcMinimumMsat = htlcMinimumMsatTmp
|
||||
}
|
||||
var htlcMaximumMsat: UInt64?
|
||||
if hasNonNilKey(data: routeHintHop, key: "htlcMaximumMsat") {
|
||||
guard let htlcMaximumMsatTmp = routeHintHop["htlcMaximumMsat"] as? UInt64 else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "htlcMaximumMsat"))
|
||||
}
|
||||
htlcMaximumMsat = htlcMaximumMsatTmp
|
||||
}
|
||||
|
||||
return RouteHintHop(
|
||||
srcNodeId: srcNodeId,
|
||||
shortChannelId: shortChannelId,
|
||||
feesBaseMsat: feesBaseMsat,
|
||||
feesProportionalMillionths: feesProportionalMillionths,
|
||||
cltvExpiryDelta: cltvExpiryDelta,
|
||||
htlcMinimumMsat: htlcMinimumMsat,
|
||||
htlcMaximumMsat: htlcMaximumMsat
|
||||
)
|
||||
}
|
||||
|
||||
static func dictionaryOf(routeHintHop: RouteHintHop) -> [String: Any?] {
|
||||
return [
|
||||
"srcNodeId": routeHintHop.srcNodeId,
|
||||
"shortChannelId": routeHintHop.shortChannelId,
|
||||
"feesBaseMsat": routeHintHop.feesBaseMsat,
|
||||
"feesProportionalMillionths": routeHintHop.feesProportionalMillionths,
|
||||
"cltvExpiryDelta": routeHintHop.cltvExpiryDelta,
|
||||
"htlcMinimumMsat": routeHintHop.htlcMinimumMsat == nil ? nil : routeHintHop.htlcMinimumMsat,
|
||||
"htlcMaximumMsat": routeHintHop.htlcMaximumMsat == nil ? nil : routeHintHop.htlcMaximumMsat,
|
||||
]
|
||||
}
|
||||
|
||||
static func asRouteHintHopList(arr: [Any]) throws -> [RouteHintHop] {
|
||||
var list = [RouteHintHop]()
|
||||
for value in arr {
|
||||
if let val = value as? [String: Any?] {
|
||||
var routeHintHop = try asRouteHintHop(routeHintHop: val)
|
||||
list.append(routeHintHop)
|
||||
} else {
|
||||
throw LiquidSdkError.Generic(message: errUnexpectedType(typeName: "RouteHintHop"))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
static func arrayOf(routeHintHopList: [RouteHintHop]) -> [Any] {
|
||||
return routeHintHopList.map { v -> [String: Any?] in dictionaryOf(routeHintHop: v) }
|
||||
}
|
||||
|
||||
static func asSendPaymentResponse(sendPaymentResponse: [String: Any?]) throws -> SendPaymentResponse {
|
||||
guard let paymentTmp = sendPaymentResponse["payment"] as? [String: Any?] else {
|
||||
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "payment", typeName: "SendPaymentResponse"))
|
||||
@@ -648,11 +856,11 @@ enum BreezLiquidSDKMapper {
|
||||
|
||||
static func asNetwork(network: String) throws -> Network {
|
||||
switch network {
|
||||
case "liquid":
|
||||
return Network.liquid
|
||||
case "mainnet":
|
||||
return Network.mainnet
|
||||
|
||||
case "liquidTestnet":
|
||||
return Network.liquidTestnet
|
||||
case "testnet":
|
||||
return Network.testnet
|
||||
|
||||
default: throw LiquidSdkError.Generic(message: "Invalid variant \(network) for enum Network")
|
||||
}
|
||||
@@ -660,11 +868,11 @@ enum BreezLiquidSDKMapper {
|
||||
|
||||
static func valueOf(network: Network) -> String {
|
||||
switch network {
|
||||
case .liquid:
|
||||
return "liquid"
|
||||
case .mainnet:
|
||||
return "mainnet"
|
||||
|
||||
case .liquidTestnet:
|
||||
return "liquidTestnet"
|
||||
case .testnet:
|
||||
return "testnet"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
|
||||
@interface RCT_EXTERN_MODULE(RNBreezLiquidSDK, RCTEventEmitter)
|
||||
|
||||
RCT_EXTERN_METHOD(
|
||||
parseInvoice: (NSString*)invoice
|
||||
resolve: (RCTPromiseResolveBlock)resolve
|
||||
reject: (RCTPromiseRejectBlock)reject
|
||||
)
|
||||
|
||||
RCT_EXTERN_METHOD(
|
||||
connect: (NSDictionary*)req
|
||||
resolve: (RCTPromiseResolveBlock)resolve
|
||||
|
||||
@@ -56,6 +56,16 @@ class RNBreezLiquidSDK: RCTEventEmitter {
|
||||
throw LiquidSdkError.Generic(message: "Not initialized")
|
||||
}
|
||||
|
||||
@objc(parseInvoice:resolve:reject:)
|
||||
func parseInvoice(_ invoice: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
||||
do {
|
||||
var res = try BreezLiquidSDK.parseInvoice(invoice: invoice)
|
||||
resolve(BreezLiquidSDKMapper.dictionaryOf(lnInvoice: res))
|
||||
} catch let err {
|
||||
rejectErr(err: err, reject: reject)
|
||||
}
|
||||
}
|
||||
|
||||
@objc(connect:resolve:reject:)
|
||||
func connect(_ req: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
||||
if bindingLiquidSdk != nil {
|
||||
|
||||
@@ -40,6 +40,21 @@ export interface GetInfoResponse {
|
||||
pubkey: string
|
||||
}
|
||||
|
||||
export interface LnInvoice {
|
||||
bolt11: string
|
||||
network: Network
|
||||
payeePubkey: string
|
||||
paymentHash: string
|
||||
description?: string
|
||||
descriptionHash?: string
|
||||
amountMsat?: number
|
||||
timestamp: number
|
||||
expiry: number
|
||||
routingHints: RouteHint[]
|
||||
paymentSecret: number[]
|
||||
minFinalCltvExpiryDelta: number
|
||||
}
|
||||
|
||||
export interface Payment {
|
||||
txId: string
|
||||
swapId?: string
|
||||
@@ -80,6 +95,20 @@ export interface RestoreRequest {
|
||||
backupPath?: string
|
||||
}
|
||||
|
||||
export interface RouteHint {
|
||||
hops: RouteHintHop[]
|
||||
}
|
||||
|
||||
export interface RouteHintHop {
|
||||
srcNodeId: string
|
||||
shortChannelId: number
|
||||
feesBaseMsat: number
|
||||
feesProportionalMillionths: number
|
||||
cltvExpiryDelta: number
|
||||
htlcMinimumMsat?: number
|
||||
htlcMaximumMsat?: number
|
||||
}
|
||||
|
||||
export interface SendPaymentResponse {
|
||||
payment: Payment
|
||||
}
|
||||
@@ -117,8 +146,8 @@ export type LiquidSdkEvent = {
|
||||
}
|
||||
|
||||
export enum Network {
|
||||
LIQUID = "liquid",
|
||||
LIQUID_TESTNET = "liquidTestnet"
|
||||
MAINNET = "mainnet",
|
||||
TESTNET = "testnet"
|
||||
}
|
||||
|
||||
export enum PaymentState {
|
||||
@@ -146,6 +175,11 @@ export const addEventListener = async (listener: EventListener): Promise<string>
|
||||
|
||||
return response
|
||||
}
|
||||
export const parseInvoice = async (invoice: string): Promise<LnInvoice> => {
|
||||
const response = await BreezLiquidSDK.parseInvoice(invoice)
|
||||
return response
|
||||
}
|
||||
|
||||
|
||||
export const removeEventListener = async (id: string): Promise<void> => {
|
||||
await BreezLiquidSDK.removeEventListener(id)
|
||||
|
||||
Reference in New Issue
Block a user