diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 7e67fe79..cb917d4f 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "sdk-common" version = "0.6.2" -source = "git+https://github.com/breez/breez-sdk?branch=ok300-sdk-common-parse-bolt12-offer#11c6812c81407881a014390cb3da68cea169bcf1" +source = "git+https://github.com/breez/breez-sdk?branch=ok300-sdk-common-parse-bolt12-offer#8da4455e4a5a077e40c440d6c875236d666fffb0" dependencies = [ "aes 0.8.4", "anyhow", diff --git a/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h b/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h index 1994f674..1aa4f461 100644 --- a/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h +++ b/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h @@ -171,8 +171,42 @@ typedef struct wire_cst_SendDestination_Bolt11 { struct wire_cst_ln_invoice *invoice; } wire_cst_SendDestination_Bolt11; +typedef struct wire_cst_list_String { + struct wire_cst_list_prim_u_8_strict **ptr; + int32_t len; +} wire_cst_list_String; + +typedef struct wire_cst_Amount_Bitcoin { + uint64_t amount_msat; +} wire_cst_Amount_Bitcoin; + +typedef struct wire_cst_Amount_Currency { + struct wire_cst_list_prim_u_8_strict *iso4217_code; + uint64_t fractional_amount; +} wire_cst_Amount_Currency; + +typedef union AmountKind { + struct wire_cst_Amount_Bitcoin Bitcoin; + struct wire_cst_Amount_Currency Currency; +} AmountKind; + +typedef struct wire_cst_amount { + int32_t tag; + union AmountKind kind; +} wire_cst_amount; + +typedef struct wire_cst_ln_offer { + struct wire_cst_list_prim_u_8_strict *bolt12; + struct wire_cst_list_String *chains; + struct wire_cst_amount *amount; + struct wire_cst_list_prim_u_8_strict *description; + uint64_t *absolute_expiry; + struct wire_cst_list_prim_u_8_strict *issuer; + struct wire_cst_list_prim_u_8_strict *signing_pubkey; +} wire_cst_ln_offer; + typedef struct wire_cst_SendDestination_Bolt12 { - struct wire_cst_list_prim_u_8_strict *offer; + struct wire_cst_ln_offer *offer; uint64_t receiver_amount_sat; } wire_cst_SendDestination_Bolt12; @@ -480,25 +514,6 @@ typedef struct wire_cst_aes_success_action_data_result { union AesSuccessActionDataResultKind kind; } wire_cst_aes_success_action_data_result; -typedef struct wire_cst_Amount_Bitcoin { - uint64_t amount_msat; -} wire_cst_Amount_Bitcoin; - -typedef struct wire_cst_Amount_Currency { - struct wire_cst_list_prim_u_8_strict *iso4217_code; - uint64_t fractional_amount; -} wire_cst_Amount_Currency; - -typedef union AmountKind { - struct wire_cst_Amount_Bitcoin Bitcoin; - struct wire_cst_Amount_Currency Currency; -} AmountKind; - -typedef struct wire_cst_amount { - int32_t tag; - union AmountKind kind; -} wire_cst_amount; - typedef struct wire_cst_bitcoin_address_data { struct wire_cst_list_prim_u_8_strict *address; int32_t network; @@ -507,21 +522,6 @@ typedef struct wire_cst_bitcoin_address_data { struct wire_cst_list_prim_u_8_strict *message; } wire_cst_bitcoin_address_data; -typedef struct wire_cst_list_String { - struct wire_cst_list_prim_u_8_strict **ptr; - int32_t len; -} wire_cst_list_String; - -typedef struct wire_cst_ln_offer { - struct wire_cst_list_prim_u_8_strict *bolt12; - struct wire_cst_list_String *chains; - struct wire_cst_amount *amount; - struct wire_cst_list_prim_u_8_strict *description; - uint64_t *absolute_expiry; - struct wire_cst_list_prim_u_8_strict *issuer; - struct wire_cst_list_prim_u_8_strict *signing_pubkey; -} wire_cst_ln_offer; - typedef struct wire_cst_ln_url_error_data { struct wire_cst_list_prim_u_8_strict *reason; } wire_cst_ln_url_error_data; diff --git a/lib/bindings/src/breez_sdk_liquid.udl b/lib/bindings/src/breez_sdk_liquid.udl index ecae1d4a..8a8e2862 100644 --- a/lib/bindings/src/breez_sdk_liquid.udl +++ b/lib/bindings/src/breez_sdk_liquid.udl @@ -397,7 +397,7 @@ dictionary PrepareSendRequest { interface SendDestination { LiquidAddress(LiquidAddressData address_data); Bolt11(LNInvoice invoice); - Bolt12(string offer, u64 receiver_amount_sat); + Bolt12(LNOffer offer, u64 receiver_amount_sat); }; dictionary PrepareSendResponse { diff --git a/lib/core/src/frb_generated.rs b/lib/core/src/frb_generated.rs index d361c26a..2aaa2374 100644 --- a/lib/core/src/frb_generated.rs +++ b/lib/core/src/frb_generated.rs @@ -3999,7 +3999,7 @@ impl SseDecode for crate::model::SendDestination { }; } 2 => { - let mut var_offer = ::sse_decode(deserializer); + let mut var_offer = ::sse_decode(deserializer); let mut var_receiverAmountSat = ::sse_decode(deserializer); return crate::model::SendDestination::Bolt12 { offer: var_offer, @@ -7803,7 +7803,7 @@ impl SseEncode for crate::model::SendDestination { receiver_amount_sat, } => { ::sse_encode(2, serializer); - ::sse_encode(offer, serializer); + ::sse_encode(offer, serializer); ::sse_encode(receiver_amount_sat, serializer); } _ => { @@ -12882,7 +12882,7 @@ mod io { #[repr(C)] #[derive(Clone, Copy)] pub struct wire_cst_SendDestination_Bolt12 { - offer: *mut wire_cst_list_prim_u_8_strict, + offer: *mut wire_cst_ln_offer, receiver_amount_sat: u64, } #[repr(C)] diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs index 826cc243..03353141 100644 --- a/lib/core/src/model.rs +++ b/lib/core/src/model.rs @@ -363,7 +363,7 @@ pub enum SendDestination { invoice: LNInvoice, }, Bolt12 { - offer: String, + offer: LNOffer, receiver_amount_sat: u64, }, } diff --git a/lib/core/src/sdk.rs b/lib/core/src/sdk.rs index 798493ae..b2f2bf50 100644 --- a/lib/core/src/sdk.rs +++ b/lib/core/src/sdk.rs @@ -1,3 +1,7 @@ +use std::collections::HashMap; +use std::time::Instant; +use std::{fs, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; + use anyhow::{anyhow, Result}; use boltz_client::{swaps::boltz::*, util::secrets::Preimage}; use buy::{BuyBitcoinApi, BuyBitcoinService}; @@ -19,9 +23,6 @@ use sdk_common::input_parser::InputType; use sdk_common::liquid::LiquidAddressData; use sdk_common::prelude::{FiatAPI, FiatCurrency, LnUrlPayError, LnUrlWithdrawError, Rate}; use signer::SdkSigner; -use std::collections::HashMap; -use std::time::Instant; -use std::{fs, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; use tokio::sync::{watch, Mutex, RwLock}; use tokio::time::MissedTickBehavior; use tokio_stream::wrappers::BroadcastStream; @@ -45,6 +46,7 @@ use crate::{ persist::Persister, utils, *, }; +use ::lightning::offers::offer::Offer; pub const DEFAULT_DATA_DIR: &str = ".data"; /// Number of blocks to monitor a swap after its timeout block height @@ -766,7 +768,7 @@ impl LiquidSdk { let receiver_amount_sat; let payment_destination; - match sdk_common::input_parser::parse(&req.destination).await { + match Self::parse(&req.destination).await { Ok(InputType::LiquidAddress { address: mut liquid_address_data, }) => { @@ -860,7 +862,7 @@ impl LiquidSdk { }; payment_destination = SendDestination::Bolt11 { invoice }; } - Ok(InputType::Bolt12Offer { offer: _ }) => { + Ok(InputType::Bolt12Offer { offer }) => { receiver_amount_sat = match req.amount { Some(PayAmount::Receiver { amount_sat }) => Ok(amount_sat), _ => Err(PaymentError::amount_missing( @@ -877,7 +879,7 @@ impl LiquidSdk { fees_sat = boltz_fees_total + lockup_fees_sat; payment_destination = SendDestination::Bolt12 { - offer: req.destination.clone(), + offer, receiver_amount_sat, }; } @@ -968,7 +970,7 @@ impl LiquidSdk { } => { let bolt12_invoice = self .swapper - .get_bolt12_invoice(offer, *receiver_amount_sat)?; + .get_bolt12_invoice(&offer.bolt12, *receiver_amount_sat)?; self.pay_bolt12_invoice(&bolt12_invoice, *fees_sat).await } } @@ -2582,9 +2584,43 @@ impl LiquidSdk { /// Parses a string into an [InputType]. See [input_parser::parse]. pub async fn parse(input: &str) -> Result { + if let Ok(offer) = input.parse::() { + return Ok(InputType::Bolt12Offer { + offer: LNOffer { + bolt12: input.to_string(), + chains: offer + .chains() + .iter() + .map(|chain| chain.to_string()) + .collect(), + // TODO This conversion (between lightning-v0.0.125 to -v0.0.118 Amount types) + // won't be needed when Liquid SDK uses the same lightning crate version as sdk-common + amount: offer.amount().map(|amount| match amount { + ::lightning::offers::offer::Amount::Bitcoin { amount_msats } => { + Amount::Bitcoin { + amount_msat: amount_msats, + } + } + ::lightning::offers::offer::Amount::Currency { + iso4217_code, + amount, + } => Amount::Currency { + iso4217_code: String::from_utf8(iso4217_code.to_vec()) + .expect("Expecting a valid ISO 4217 character sequence"), + fractional_amount: amount, + }, + }), + description: offer.description().map(|d| d.to_string()), + absolute_expiry: offer.absolute_expiry().map(|expiry| expiry.as_secs()), + issuer: offer.issuer().map(|s| s.to_string()), + signing_pubkey: offer.signing_pubkey().map(|pk| pk.to_string()), + }, + }); + } + parse(input) .await - .map_err(|e| PaymentError::Generic { err: e.to_string() }) + .map_err(|e| PaymentError::generic(&e.to_string())) } /// Parses a string into an [LNInvoice]. See [invoice::parse_invoice]. diff --git a/packages/dart/lib/src/frb_generated.dart b/packages/dart/lib/src/frb_generated.dart index 4c88030d..0a6a1c65 100644 --- a/packages/dart/lib/src/frb_generated.dart +++ b/packages/dart/lib/src/frb_generated.dart @@ -2912,7 +2912,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); case 2: return SendDestination_Bolt12( - offer: dco_decode_String(raw[1]), + offer: dco_decode_box_autoadd_ln_offer(raw[1]), receiverAmountSat: dco_decode_u_64(raw[2]), ); default: @@ -4828,7 +4828,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_invoice = sse_decode_box_autoadd_ln_invoice(deserializer); return SendDestination_Bolt11(invoice: var_invoice); case 2: - var var_offer = sse_decode_String(deserializer); + var var_offer = sse_decode_box_autoadd_ln_offer(deserializer); var var_receiverAmountSat = sse_decode_u_64(deserializer); return SendDestination_Bolt12(offer: var_offer, receiverAmountSat: var_receiverAmountSat); default: @@ -6596,7 +6596,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_ln_invoice(invoice, serializer); case SendDestination_Bolt12(offer: final offer, receiverAmountSat: final receiverAmountSat): sse_encode_i_32(2, serializer); - sse_encode_String(offer, serializer); + sse_encode_box_autoadd_ln_offer(offer, serializer); sse_encode_u_64(receiverAmountSat, serializer); default: throw UnimplementedError(''); diff --git a/packages/dart/lib/src/frb_generated.io.dart b/packages/dart/lib/src/frb_generated.io.dart index 080e412e..4ce0b527 100644 --- a/packages/dart/lib/src/frb_generated.io.dart +++ b/packages/dart/lib/src/frb_generated.io.dart @@ -3045,7 +3045,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { return; } if (apiObj is SendDestination_Bolt12) { - var pre_offer = cst_encode_String(apiObj.offer); + var pre_offer = cst_encode_box_autoadd_ln_offer(apiObj.offer); var pre_receiver_amount_sat = cst_encode_u_64(apiObj.receiverAmountSat); wireObj.tag = 2; wireObj.kind.Bolt12.offer = pre_offer; @@ -5411,8 +5411,56 @@ final class wire_cst_SendDestination_Bolt11 extends ffi.Struct { external ffi.Pointer invoice; } +final class wire_cst_list_String extends ffi.Struct { + external ffi.Pointer> ptr; + + @ffi.Int32() + external int len; +} + +final class wire_cst_Amount_Bitcoin extends ffi.Struct { + @ffi.Uint64() + external int amount_msat; +} + +final class wire_cst_Amount_Currency extends ffi.Struct { + external ffi.Pointer iso4217_code; + + @ffi.Uint64() + external int fractional_amount; +} + +final class AmountKind extends ffi.Union { + external wire_cst_Amount_Bitcoin Bitcoin; + + external wire_cst_Amount_Currency Currency; +} + +final class wire_cst_amount extends ffi.Struct { + @ffi.Int32() + external int tag; + + external AmountKind kind; +} + +final class wire_cst_ln_offer extends ffi.Struct { + external ffi.Pointer bolt12; + + external ffi.Pointer chains; + + external ffi.Pointer amount; + + external ffi.Pointer description; + + external ffi.Pointer absolute_expiry; + + external ffi.Pointer issuer; + + external ffi.Pointer signing_pubkey; +} + final class wire_cst_SendDestination_Bolt12 extends ffi.Struct { - external ffi.Pointer offer; + external ffi.Pointer offer; @ffi.Uint64() external int receiver_amount_sat; @@ -5842,31 +5890,6 @@ final class wire_cst_aes_success_action_data_result extends ffi.Struct { external AesSuccessActionDataResultKind kind; } -final class wire_cst_Amount_Bitcoin extends ffi.Struct { - @ffi.Uint64() - external int amount_msat; -} - -final class wire_cst_Amount_Currency extends ffi.Struct { - external ffi.Pointer iso4217_code; - - @ffi.Uint64() - external int fractional_amount; -} - -final class AmountKind extends ffi.Union { - external wire_cst_Amount_Bitcoin Bitcoin; - - external wire_cst_Amount_Currency Currency; -} - -final class wire_cst_amount extends ffi.Struct { - @ffi.Int32() - external int tag; - - external AmountKind kind; -} - final class wire_cst_bitcoin_address_data extends ffi.Struct { external ffi.Pointer address; @@ -5880,29 +5903,6 @@ final class wire_cst_bitcoin_address_data extends ffi.Struct { external ffi.Pointer message; } -final class wire_cst_list_String extends ffi.Struct { - external ffi.Pointer> ptr; - - @ffi.Int32() - external int len; -} - -final class wire_cst_ln_offer extends ffi.Struct { - external ffi.Pointer bolt12; - - external ffi.Pointer chains; - - external ffi.Pointer amount; - - external ffi.Pointer description; - - external ffi.Pointer absolute_expiry; - - external ffi.Pointer issuer; - - external ffi.Pointer signing_pubkey; -} - final class wire_cst_ln_url_error_data extends ffi.Struct { external ffi.Pointer reason; } diff --git a/packages/dart/lib/src/model.dart b/packages/dart/lib/src/model.dart index 62dad616..39fab758 100644 --- a/packages/dart/lib/src/model.dart +++ b/packages/dart/lib/src/model.dart @@ -1258,7 +1258,7 @@ sealed class SendDestination with _$SendDestination { required LNInvoice invoice, }) = SendDestination_Bolt11; const factory SendDestination.bolt12({ - required String offer, + required LNOffer offer, required BigInt receiverAmountSat, }) = SendDestination_Bolt12; } diff --git a/packages/dart/lib/src/model.freezed.dart b/packages/dart/lib/src/model.freezed.dart index 5ffb0210..e0f93d35 100644 --- a/packages/dart/lib/src/model.freezed.dart +++ b/packages/dart/lib/src/model.freezed.dart @@ -1927,7 +1927,7 @@ abstract class _$$SendDestination_Bolt12ImplCopyWith<$Res> { _$SendDestination_Bolt12Impl value, $Res Function(_$SendDestination_Bolt12Impl) then) = __$$SendDestination_Bolt12ImplCopyWithImpl<$Res>; @useResult - $Res call({String offer, BigInt receiverAmountSat}); + $Res call({LNOffer offer, BigInt receiverAmountSat}); } /// @nodoc @@ -1950,7 +1950,7 @@ class __$$SendDestination_Bolt12ImplCopyWithImpl<$Res> offer: null == offer ? _value.offer : offer // ignore: cast_nullable_to_non_nullable - as String, + as LNOffer, receiverAmountSat: null == receiverAmountSat ? _value.receiverAmountSat : receiverAmountSat // ignore: cast_nullable_to_non_nullable @@ -1965,7 +1965,7 @@ class _$SendDestination_Bolt12Impl extends SendDestination_Bolt12 { const _$SendDestination_Bolt12Impl({required this.offer, required this.receiverAmountSat}) : super._(); @override - final String offer; + final LNOffer offer; @override final BigInt receiverAmountSat; @@ -1998,10 +1998,10 @@ class _$SendDestination_Bolt12Impl extends SendDestination_Bolt12 { abstract class SendDestination_Bolt12 extends SendDestination { const factory SendDestination_Bolt12( - {required final String offer, required final BigInt receiverAmountSat}) = _$SendDestination_Bolt12Impl; + {required final LNOffer offer, required final BigInt receiverAmountSat}) = _$SendDestination_Bolt12Impl; const SendDestination_Bolt12._() : super._(); - String get offer; + LNOffer get offer; BigInt get receiverAmountSat; /// Create a copy of SendDestination