diff --git a/lib/core/src/chain_swap.rs b/lib/core/src/chain_swap.rs index 9515aaa07..feb167687 100644 --- a/lib/core/src/chain_swap.rs +++ b/lib/core/src/chain_swap.rs @@ -378,11 +378,13 @@ impl ChainSwapHandler { } async fn handle_amountless_update(&self, swap: &ChainSwap) -> Result<(), PaymentError> { + let id = swap.id.clone(); + let quote = self .swapper - .get_zero_amount_chain_swap_quote(&swap.id) + .get_zero_amount_chain_swap_quote(&id) .map(|quote| quote.to_sat())?; - info!("Got quote of {quote} sat for swap {}", &swap.id); + info!("Got quote of {quote} sat for swap {}", &id); match self.validate_amountless_swap(swap, quote).await? { ValidateAmountlessSwapResult::ReadyForAccepting { @@ -391,12 +393,12 @@ impl ChainSwapHandler { } => { debug!("Zero-amount swap validated. Auto-accepting..."); self.persister.update_zero_amount_swap_values( - &swap.id, + &id, user_lockup_amount_sat, receiver_amount_sat, )?; self.swapper - .accept_zero_amount_chain_swap_quote(&swap.id, quote) + .accept_zero_amount_chain_swap_quote(&id, quote) .map_err(Into::into) } ValidateAmountlessSwapResult::RequiresUserAction { @@ -406,12 +408,15 @@ impl ChainSwapHandler { debug!("Zero-amount swap validated. Fees are too high for automatic accepting. Moving to WaitingFeeAcceptance"); // While the user doesn't accept new fees, let's continue to show the original estimate self.persister.update_zero_amount_swap_values( - &swap.id, + &id, user_lockup_amount_sat, receiver_amount_sat_original_estimate, )?; - self.update_swap_info(&swap.id, WaitingFeeAcceptance, None, None, None, None) - .await + self.update_swap_info(&ChainSwapUpdate { + swap_id: id, + to_state: WaitingFeeAcceptance, + ..Default::default() + }) } } } @@ -940,9 +945,9 @@ impl ChainSwapHandler { let id = &swap.id; ensure_sdk!( - swap.state == Refundable, + swap.state.is_refundable(), PaymentError::Generic { - err: format!("Chain Swap {id} was not marked as `Refundable`") + err: format!("Chain Swap {id} was not in refundable state") } ); diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs index f4701b307..d977bae2e 100644 --- a/lib/core/src/model.rs +++ b/lib/core/src/model.rs @@ -1,3 +1,4 @@ +use std::cmp::PartialEq; use std::path::PathBuf; use anyhow::{anyhow, Result}; @@ -1169,6 +1170,15 @@ impl FromSql for PaymentState { } } +impl PaymentState { + pub(crate) fn is_refundable(&self) -> bool { + matches!( + self, + PaymentState::Refundable | PaymentState::WaitingFeeAcceptance + ) + } +} + #[derive(Debug, Copy, Clone, Eq, EnumString, Display, Hash, PartialEq, Serialize)] #[strum(serialize_all = "lowercase")] pub enum PaymentType { diff --git a/lib/core/src/sdk.rs b/lib/core/src/sdk.rs index d6b939f01..89478e55c 100644 --- a/lib/core/src/sdk.rs +++ b/lib/core/src/sdk.rs @@ -2501,7 +2501,11 @@ impl LiquidSdk { let mut pending_send_sat = 0; let mut pending_receive_sat = 0; let payments = self.persister.get_payments(&ListPaymentsRequest { - states: Some(vec![PaymentState::Pending, PaymentState::RefundPending]), + states: Some(vec![ + PaymentState::Pending, + PaymentState::RefundPending, + PaymentState::WaitingFeeAcceptance, + ]), ..Default::default() })?; @@ -2570,6 +2574,13 @@ impl LiquidSdk { err: format!("Could not find Swap {}", req.swap_id), })?; + ensure_sdk!( + chain_swap.state == WaitingFeeAcceptance, + SdkError::Generic { + err: "Payment is not WaitingFeeAcceptance".to_string() + } + ); + let server_lockup_quote = self .swapper .get_zero_amount_chain_swap_quote(&req.swap_id)?; @@ -2604,6 +2615,13 @@ impl LiquidSdk { err: format!("Could not find Swap {}", swap_id), })?; + ensure_sdk!( + chain_swap.state == WaitingFeeAcceptance, + PaymentError::Generic { + err: "Payment is not WaitingFeeAcceptance".to_string() + } + ); + let server_lockup_quote = self.swapper.get_zero_amount_chain_swap_quote(&swap_id)?; ensure_sdk!( @@ -2618,9 +2636,11 @@ impl LiquidSdk { )?; self.swapper .accept_zero_amount_chain_swap_quote(&swap_id, server_lockup_quote.to_sat())?; - self.chain_swap_handler - .update_swap_info(&swap_id, Pending, None, None, None, None) - .await + self.chain_swap_handler.update_swap_info(&ChainSwapUpdate { + swap_id, + to_state: Pending, + ..Default::default() + }) } /// Empties the Liquid Wallet cache for the [Config::network]. @@ -3561,8 +3581,7 @@ mod tests { async fn test_zero_amount_chain_swap_zero_leeway() -> Result<()> { let user_lockup_sat = 50_000; - let (_tmp_dir, persister) = new_persister()?; - let persister = Arc::new(persister); + create_persister!(persister); let swapper = Arc::new(MockSwapper::new()); let status_stream = Arc::new(MockStatusStream::new()); let liquid_chain_service = Arc::new(Mutex::new(MockLiquidChainService::new())); @@ -3626,8 +3645,7 @@ mod tests { let user_lockup_sat = 50_000; let onchain_fee_rate_leeway_sat_per_vbyte = 5; - let (_tmp_dir, persister) = new_persister()?; - let persister = Arc::new(persister); + create_persister!(persister); let swapper = Arc::new(MockSwapper::new()); let status_stream = Arc::new(MockStatusStream::new()); let liquid_chain_service = Arc::new(Mutex::new(MockLiquidChainService::new())); diff --git a/lib/core/src/sync/mod.rs b/lib/core/src/sync/mod.rs index e32511a4d..c01889e31 100644 --- a/lib/core/src/sync/mod.rs +++ b/lib/core/src/sync/mod.rs @@ -570,6 +570,7 @@ mod tests { None, true, None, + false, ))?; sync_service.push().await?; diff --git a/packages/dart/lib/src/frb_generated.dart b/packages/dart/lib/src/frb_generated.dart index 778843003..f128a449f 100644 --- a/packages/dart/lib/src/frb_generated.dart +++ b/packages/dart/lib/src/frb_generated.dart @@ -1476,6 +1476,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return dco_decode_ln_url_error_data(raw); } + @protected + LnUrlInfo dco_decode_box_autoadd_ln_url_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_ln_url_info(raw); + } + @protected LnUrlPayErrorData dco_decode_box_autoadd_ln_url_pay_error_data(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -1693,7 +1699,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Config dco_decode_config(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 13) throw Exception('unexpected arr length: expect 13 but see ${arr.length}'); + if (arr.length != 14) throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); return Config( liquidElectrumUrl: dco_decode_String(arr[0]), bitcoinElectrumUrl: dco_decode_String(arr[1]), @@ -1703,11 +1709,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { network: dco_decode_liquid_network(arr[5]), paymentTimeoutSec: dco_decode_u_64(arr[6]), zeroConfMinFeeRateMsat: dco_decode_u_32(arr[7]), - zeroConfMaxAmountSat: dco_decode_opt_box_autoadd_u_64(arr[8]), - breezApiKey: dco_decode_opt_String(arr[9]), - externalInputParsers: dco_decode_opt_list_external_input_parser(arr[10]), - useDefaultExternalInputParsers: dco_decode_bool(arr[11]), - onchainFeeRateLeewaySatPerVbyte: dco_decode_opt_box_autoadd_u_32(arr[12]), + syncServiceUrl: dco_decode_String(arr[8]), + zeroConfMaxAmountSat: dco_decode_opt_box_autoadd_u_64(arr[9]), + breezApiKey: dco_decode_opt_String(arr[10]), + externalInputParsers: dco_decode_opt_list_external_input_parser(arr[11]), + useDefaultExternalInputParsers: dco_decode_bool(arr[12]), + onchainFeeRateLeewaySatPerVbyte: dco_decode_opt_box_autoadd_u_32(arr[13]), ); } @@ -1958,6 +1965,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + List dco_decode_list_payment_state(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_payment_state).toList(); + } + @protected List dco_decode_list_payment_type(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -1968,14 +1981,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ListPaymentsRequest dco_decode_list_payments_request(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return ListPaymentsRequest( filters: dco_decode_opt_list_payment_type(arr[0]), - fromTimestamp: dco_decode_opt_box_autoadd_i_64(arr[1]), - toTimestamp: dco_decode_opt_box_autoadd_i_64(arr[2]), - offset: dco_decode_opt_box_autoadd_u_32(arr[3]), - limit: dco_decode_opt_box_autoadd_u_32(arr[4]), - details: dco_decode_opt_box_autoadd_list_payment_details(arr[5]), + states: dco_decode_opt_list_payment_state(arr[1]), + fromTimestamp: dco_decode_opt_box_autoadd_i_64(arr[2]), + toTimestamp: dco_decode_opt_box_autoadd_i_64(arr[3]), + offset: dco_decode_opt_box_autoadd_u_32(arr[4]), + limit: dco_decode_opt_box_autoadd_u_32(arr[5]), + details: dco_decode_opt_box_autoadd_list_payment_details(arr[6]), ); } @@ -2116,6 +2130,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + LnUrlInfo dco_decode_ln_url_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + return LnUrlInfo( + lnAddress: dco_decode_opt_String(arr[0]), + lnurlPayComment: dco_decode_opt_String(arr[1]), + lnurlPayDomain: dco_decode_opt_String(arr[2]), + lnurlPayMetadata: dco_decode_opt_String(arr[3]), + lnurlPaySuccessAction: dco_decode_opt_box_autoadd_success_action_processed(arr[4]), + lnurlPayUnprocessedSuccessAction: dco_decode_opt_box_autoadd_success_action(arr[5]), + lnurlWithdrawEndpoint: dco_decode_opt_String(arr[6]), + ); + } + @protected LnUrlPayError dco_decode_ln_url_pay_error(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2429,6 +2459,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_box_autoadd_list_payment_details(raw); } + @protected + LnUrlInfo? dco_decode_opt_box_autoadd_ln_url_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_ln_url_info(raw); + } + @protected PayAmount? dco_decode_opt_box_autoadd_pay_amount(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2477,6 +2513,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_list_external_input_parser(raw); } + @protected + List? dco_decode_opt_list_payment_state(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_list_payment_state(raw); + } + @protected List? dco_decode_opt_list_payment_type(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2539,8 +2581,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { bolt11: dco_decode_opt_String(raw[4]), bolt12Offer: dco_decode_opt_String(raw[5]), paymentHash: dco_decode_opt_String(raw[6]), - refundTxId: dco_decode_opt_String(raw[7]), - refundTxAmountSat: dco_decode_opt_box_autoadd_u_64(raw[8]), + lnurlInfo: dco_decode_opt_box_autoadd_ln_url_info(raw[7]), + refundTxId: dco_decode_opt_String(raw[8]), + refundTxAmountSat: dco_decode_opt_box_autoadd_u_64(raw[9]), ); case 1: return PaymentDetails_Liquid( @@ -2689,11 +2732,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PrepareLnUrlPayResponse dco_decode_prepare_ln_url_pay_response(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 5) throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); return PrepareLnUrlPayResponse( destination: dco_decode_send_destination(arr[0]), feesSat: dco_decode_u_64(arr[1]), - successAction: dco_decode_opt_box_autoadd_success_action(arr[2]), + data: dco_decode_ln_url_pay_request_data(arr[2]), + comment: dco_decode_opt_String(arr[3]), + successAction: dco_decode_opt_box_autoadd_success_action(arr[4]), ); } @@ -3402,6 +3447,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_ln_url_error_data(deserializer)); } + @protected + LnUrlInfo sse_decode_box_autoadd_ln_url_info(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_ln_url_info(deserializer)); + } + @protected LnUrlPayErrorData sse_decode_box_autoadd_ln_url_pay_error_data(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3618,6 +3669,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_network = sse_decode_liquid_network(deserializer); var var_paymentTimeoutSec = sse_decode_u_64(deserializer); var var_zeroConfMinFeeRateMsat = sse_decode_u_32(deserializer); + var var_syncServiceUrl = sse_decode_String(deserializer); var var_zeroConfMaxAmountSat = sse_decode_opt_box_autoadd_u_64(deserializer); var var_breezApiKey = sse_decode_opt_String(deserializer); var var_externalInputParsers = sse_decode_opt_list_external_input_parser(deserializer); @@ -3632,6 +3684,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { network: var_network, paymentTimeoutSec: var_paymentTimeoutSec, zeroConfMinFeeRateMsat: var_zeroConfMinFeeRateMsat, + syncServiceUrl: var_syncServiceUrl, zeroConfMaxAmountSat: var_zeroConfMaxAmountSat, breezApiKey: var_breezApiKey, externalInputParsers: var_externalInputParsers, @@ -3917,6 +3970,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + List sse_decode_list_payment_state(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_payment_state(deserializer)); + } + return ans_; + } + @protected List sse_decode_list_payment_type(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3933,6 +3998,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ListPaymentsRequest sse_decode_list_payments_request(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_filters = sse_decode_opt_list_payment_type(deserializer); + var var_states = sse_decode_opt_list_payment_state(deserializer); var var_fromTimestamp = sse_decode_opt_box_autoadd_i_64(deserializer); var var_toTimestamp = sse_decode_opt_box_autoadd_i_64(deserializer); var var_offset = sse_decode_opt_box_autoadd_u_32(deserializer); @@ -3940,6 +4006,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_details = sse_decode_opt_box_autoadd_list_payment_details(deserializer); return ListPaymentsRequest( filters: var_filters, + states: var_states, fromTimestamp: var_fromTimestamp, toTimestamp: var_toTimestamp, offset: var_offset, @@ -4114,6 +4181,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return LnUrlErrorData(reason: var_reason); } + @protected + LnUrlInfo sse_decode_ln_url_info(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_lnAddress = sse_decode_opt_String(deserializer); + var var_lnurlPayComment = sse_decode_opt_String(deserializer); + var var_lnurlPayDomain = sse_decode_opt_String(deserializer); + var var_lnurlPayMetadata = sse_decode_opt_String(deserializer); + var var_lnurlPaySuccessAction = sse_decode_opt_box_autoadd_success_action_processed(deserializer); + var var_lnurlPayUnprocessedSuccessAction = sse_decode_opt_box_autoadd_success_action(deserializer); + var var_lnurlWithdrawEndpoint = sse_decode_opt_String(deserializer); + return LnUrlInfo( + lnAddress: var_lnAddress, + lnurlPayComment: var_lnurlPayComment, + lnurlPayDomain: var_lnurlPayDomain, + lnurlPayMetadata: var_lnurlPayMetadata, + lnurlPaySuccessAction: var_lnurlPaySuccessAction, + lnurlPayUnprocessedSuccessAction: var_lnurlPayUnprocessedSuccessAction, + lnurlWithdrawEndpoint: var_lnurlWithdrawEndpoint); + } + @protected LnUrlPayError sse_decode_ln_url_pay_error(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4421,6 +4508,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + LnUrlInfo? sse_decode_opt_box_autoadd_ln_url_info(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_ln_url_info(deserializer)); + } else { + return null; + } + } + @protected PayAmount? sse_decode_opt_box_autoadd_pay_amount(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4509,6 +4607,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + List? sse_decode_opt_list_payment_state(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_list_payment_state(deserializer)); + } else { + return null; + } + } + @protected List? sse_decode_opt_list_payment_type(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4581,6 +4690,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_bolt11 = sse_decode_opt_String(deserializer); var var_bolt12Offer = sse_decode_opt_String(deserializer); var var_paymentHash = sse_decode_opt_String(deserializer); + var var_lnurlInfo = sse_decode_opt_box_autoadd_ln_url_info(deserializer); var var_refundTxId = sse_decode_opt_String(deserializer); var var_refundTxAmountSat = sse_decode_opt_box_autoadd_u_64(deserializer); return PaymentDetails_Lightning( @@ -4590,6 +4700,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { bolt11: var_bolt11, bolt12Offer: var_bolt12Offer, paymentHash: var_paymentHash, + lnurlInfo: var_lnurlInfo, refundTxId: var_refundTxId, refundTxAmountSat: var_refundTxAmountSat); case 1: @@ -4732,9 +4843,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs var var_destination = sse_decode_send_destination(deserializer); var var_feesSat = sse_decode_u_64(deserializer); + var var_data = sse_decode_ln_url_pay_request_data(deserializer); + var var_comment = sse_decode_opt_String(deserializer); var var_successAction = sse_decode_opt_box_autoadd_success_action(deserializer); return PrepareLnUrlPayResponse( - destination: var_destination, feesSat: var_feesSat, successAction: var_successAction); + destination: var_destination, + feesSat: var_feesSat, + data: var_data, + comment: var_comment, + successAction: var_successAction); } @protected @@ -5486,6 +5603,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_ln_url_error_data(self, serializer); } + @protected + void sse_encode_box_autoadd_ln_url_info(LnUrlInfo self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_ln_url_info(self, serializer); + } + @protected void sse_encode_box_autoadd_ln_url_pay_error_data(LnUrlPayErrorData self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5705,6 +5828,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_liquid_network(self.network, serializer); sse_encode_u_64(self.paymentTimeoutSec, serializer); sse_encode_u_32(self.zeroConfMinFeeRateMsat, serializer); + sse_encode_String(self.syncServiceUrl, serializer); sse_encode_opt_box_autoadd_u_64(self.zeroConfMaxAmountSat, serializer); sse_encode_opt_String(self.breezApiKey, serializer); sse_encode_opt_list_external_input_parser(self.externalInputParsers, serializer); @@ -5936,6 +6060,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_payment_state(List 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_payment_state(item, serializer); + } + } + @protected void sse_encode_list_payment_type(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5949,6 +6082,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { void sse_encode_list_payments_request(ListPaymentsRequest self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_opt_list_payment_type(self.filters, serializer); + sse_encode_opt_list_payment_state(self.states, serializer); sse_encode_opt_box_autoadd_i_64(self.fromTimestamp, serializer); sse_encode_opt_box_autoadd_i_64(self.toTimestamp, serializer); sse_encode_opt_box_autoadd_u_32(self.offset, serializer); @@ -6082,6 +6216,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.reason, serializer); } + @protected + void sse_encode_ln_url_info(LnUrlInfo self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_opt_String(self.lnAddress, serializer); + sse_encode_opt_String(self.lnurlPayComment, serializer); + sse_encode_opt_String(self.lnurlPayDomain, serializer); + sse_encode_opt_String(self.lnurlPayMetadata, serializer); + sse_encode_opt_box_autoadd_success_action_processed(self.lnurlPaySuccessAction, serializer); + sse_encode_opt_box_autoadd_success_action(self.lnurlPayUnprocessedSuccessAction, serializer); + sse_encode_opt_String(self.lnurlWithdrawEndpoint, serializer); + } + @protected void sse_encode_ln_url_pay_error(LnUrlPayError self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -6349,6 +6495,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_box_autoadd_ln_url_info(LnUrlInfo? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_ln_url_info(self, serializer); + } + } + @protected void sse_encode_opt_box_autoadd_pay_amount(PayAmount? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -6430,6 +6586,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_list_payment_state(List? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_list_payment_state(self, serializer); + } + } + @protected void sse_encode_opt_list_payment_type(List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -6486,6 +6652,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { bolt11: final bolt11, bolt12Offer: final bolt12Offer, paymentHash: final paymentHash, + lnurlInfo: final lnurlInfo, refundTxId: final refundTxId, refundTxAmountSat: final refundTxAmountSat ): @@ -6496,6 +6663,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(bolt11, serializer); sse_encode_opt_String(bolt12Offer, serializer); sse_encode_opt_String(paymentHash, serializer); + sse_encode_opt_box_autoadd_ln_url_info(lnurlInfo, serializer); sse_encode_opt_String(refundTxId, serializer); sse_encode_opt_box_autoadd_u_64(refundTxAmountSat, serializer); case PaymentDetails_Liquid(destination: final destination, description: final description): @@ -6627,6 +6795,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_send_destination(self.destination, serializer); sse_encode_u_64(self.feesSat, serializer); + sse_encode_ln_url_pay_request_data(self.data, serializer); + sse_encode_opt_String(self.comment, serializer); sse_encode_opt_box_autoadd_success_action(self.successAction, serializer); } diff --git a/packages/react-native/ios/BreezSDKLiquidMapper.swift b/packages/react-native/ios/BreezSDKLiquidMapper.swift index 00e958bae..5574db15a 100644 --- a/packages/react-native/ios/BreezSDKLiquidMapper.swift +++ b/packages/react-native/ios/BreezSDKLiquidMapper.swift @@ -339,6 +339,9 @@ enum BreezSDKLiquidMapper { guard let zeroConfMinFeeRateMsat = config["zeroConfMinFeeRateMsat"] as? UInt32 else { throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "zeroConfMinFeeRateMsat", typeName: "Config")) } + guard let syncServiceUrl = config["syncServiceUrl"] as? String else { + throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "syncServiceUrl", typeName: "Config")) + } var breezApiKey: String? if hasNonNilKey(data: config, key: "breezApiKey") { guard let breezApiKeyTmp = config["breezApiKey"] as? String else { @@ -376,7 +379,7 @@ enum BreezSDKLiquidMapper { onchainFeeRateLeewaySatPerVbyte = onchainFeeRateLeewaySatPerVbyteTmp } - return Config(liquidElectrumUrl: liquidElectrumUrl, bitcoinElectrumUrl: bitcoinElectrumUrl, mempoolspaceUrl: mempoolspaceUrl, workingDir: workingDir, network: network, paymentTimeoutSec: paymentTimeoutSec, zeroConfMinFeeRateMsat: zeroConfMinFeeRateMsat, breezApiKey: breezApiKey, cacheDir: cacheDir, zeroConfMaxAmountSat: zeroConfMaxAmountSat, useDefaultExternalInputParsers: useDefaultExternalInputParsers, externalInputParsers: externalInputParsers, onchainFeeRateLeewaySatPerVbyte: onchainFeeRateLeewaySatPerVbyte) + return Config(liquidElectrumUrl: liquidElectrumUrl, bitcoinElectrumUrl: bitcoinElectrumUrl, mempoolspaceUrl: mempoolspaceUrl, workingDir: workingDir, network: network, paymentTimeoutSec: paymentTimeoutSec, zeroConfMinFeeRateMsat: zeroConfMinFeeRateMsat, syncServiceUrl: syncServiceUrl, breezApiKey: breezApiKey, cacheDir: cacheDir, zeroConfMaxAmountSat: zeroConfMaxAmountSat, useDefaultExternalInputParsers: useDefaultExternalInputParsers, externalInputParsers: externalInputParsers, onchainFeeRateLeewaySatPerVbyte: onchainFeeRateLeewaySatPerVbyte) } static func dictionaryOf(config: Config) -> [String: Any?] { @@ -388,6 +391,7 @@ enum BreezSDKLiquidMapper { "network": valueOf(liquidNetwork: config.network), "paymentTimeoutSec": config.paymentTimeoutSec, "zeroConfMinFeeRateMsat": config.zeroConfMinFeeRateMsat, + "syncServiceUrl": config.syncServiceUrl, "breezApiKey": config.breezApiKey == nil ? nil : config.breezApiKey, "cacheDir": config.cacheDir == nil ? nil : config.cacheDir, "zeroConfMaxAmountSat": config.zeroConfMaxAmountSat == nil ? nil : config.zeroConfMaxAmountSat, @@ -1063,6 +1067,11 @@ enum BreezSDKLiquidMapper { filters = try asPaymentTypeList(arr: filtersTmp) } + var states: [PaymentState]? + if let statesTmp = listPaymentsRequest["states"] as? [String] { + states = try asPaymentStateList(arr: statesTmp) + } + var fromTimestamp: Int64? if hasNonNilKey(data: listPaymentsRequest, key: "fromTimestamp") { guard let fromTimestampTmp = listPaymentsRequest["fromTimestamp"] as? Int64 else { @@ -1096,12 +1105,13 @@ enum BreezSDKLiquidMapper { details = try asListPaymentDetails(listPaymentDetails: detailsTmp) } - return ListPaymentsRequest(filters: filters, fromTimestamp: fromTimestamp, toTimestamp: toTimestamp, offset: offset, limit: limit, details: details) + return ListPaymentsRequest(filters: filters, states: states, fromTimestamp: fromTimestamp, toTimestamp: toTimestamp, offset: offset, limit: limit, details: details) } static func dictionaryOf(listPaymentsRequest: ListPaymentsRequest) -> [String: Any?] { return [ "filters": listPaymentsRequest.filters == nil ? nil : arrayOf(paymentTypeList: listPaymentsRequest.filters!), + "states": listPaymentsRequest.states == nil ? nil : arrayOf(paymentStateList: listPaymentsRequest.states!), "fromTimestamp": listPaymentsRequest.fromTimestamp == nil ? nil : listPaymentsRequest.fromTimestamp, "toTimestamp": listPaymentsRequest.toTimestamp == nil ? nil : listPaymentsRequest.toTimestamp, "offset": listPaymentsRequest.offset == nil ? nil : listPaymentsRequest.offset, @@ -1236,6 +1246,85 @@ enum BreezSDKLiquidMapper { return lnUrlErrorDataList.map { v -> [String: Any?] in return dictionaryOf(lnUrlErrorData: v) } } + static func asLnUrlInfo(lnUrlInfo: [String: Any?]) throws -> LnUrlInfo { + var lnAddress: String? + if hasNonNilKey(data: lnUrlInfo, key: "lnAddress") { + guard let lnAddressTmp = lnUrlInfo["lnAddress"] as? String else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "lnAddress")) + } + lnAddress = lnAddressTmp + } + var lnurlPayComment: String? + if hasNonNilKey(data: lnUrlInfo, key: "lnurlPayComment") { + guard let lnurlPayCommentTmp = lnUrlInfo["lnurlPayComment"] as? String else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "lnurlPayComment")) + } + lnurlPayComment = lnurlPayCommentTmp + } + var lnurlPayDomain: String? + if hasNonNilKey(data: lnUrlInfo, key: "lnurlPayDomain") { + guard let lnurlPayDomainTmp = lnUrlInfo["lnurlPayDomain"] as? String else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "lnurlPayDomain")) + } + lnurlPayDomain = lnurlPayDomainTmp + } + var lnurlPayMetadata: String? + if hasNonNilKey(data: lnUrlInfo, key: "lnurlPayMetadata") { + guard let lnurlPayMetadataTmp = lnUrlInfo["lnurlPayMetadata"] as? String else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "lnurlPayMetadata")) + } + lnurlPayMetadata = lnurlPayMetadataTmp + } + var lnurlPaySuccessAction: SuccessActionProcessed? + if let lnurlPaySuccessActionTmp = lnUrlInfo["lnurlPaySuccessAction"] as? [String: Any?] { + lnurlPaySuccessAction = try asSuccessActionProcessed(successActionProcessed: lnurlPaySuccessActionTmp) + } + + var lnurlPayUnprocessedSuccessAction: SuccessAction? + if let lnurlPayUnprocessedSuccessActionTmp = lnUrlInfo["lnurlPayUnprocessedSuccessAction"] as? [String: Any?] { + lnurlPayUnprocessedSuccessAction = try asSuccessAction(successAction: lnurlPayUnprocessedSuccessActionTmp) + } + + var lnurlWithdrawEndpoint: String? + if hasNonNilKey(data: lnUrlInfo, key: "lnurlWithdrawEndpoint") { + guard let lnurlWithdrawEndpointTmp = lnUrlInfo["lnurlWithdrawEndpoint"] as? String else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "lnurlWithdrawEndpoint")) + } + lnurlWithdrawEndpoint = lnurlWithdrawEndpointTmp + } + + return LnUrlInfo(lnAddress: lnAddress, lnurlPayComment: lnurlPayComment, lnurlPayDomain: lnurlPayDomain, lnurlPayMetadata: lnurlPayMetadata, lnurlPaySuccessAction: lnurlPaySuccessAction, lnurlPayUnprocessedSuccessAction: lnurlPayUnprocessedSuccessAction, lnurlWithdrawEndpoint: lnurlWithdrawEndpoint) + } + + static func dictionaryOf(lnUrlInfo: LnUrlInfo) -> [String: Any?] { + return [ + "lnAddress": lnUrlInfo.lnAddress == nil ? nil : lnUrlInfo.lnAddress, + "lnurlPayComment": lnUrlInfo.lnurlPayComment == nil ? nil : lnUrlInfo.lnurlPayComment, + "lnurlPayDomain": lnUrlInfo.lnurlPayDomain == nil ? nil : lnUrlInfo.lnurlPayDomain, + "lnurlPayMetadata": lnUrlInfo.lnurlPayMetadata == nil ? nil : lnUrlInfo.lnurlPayMetadata, + "lnurlPaySuccessAction": lnUrlInfo.lnurlPaySuccessAction == nil ? nil : dictionaryOf(successActionProcessed: lnUrlInfo.lnurlPaySuccessAction!), + "lnurlPayUnprocessedSuccessAction": lnUrlInfo.lnurlPayUnprocessedSuccessAction == nil ? nil : dictionaryOf(successAction: lnUrlInfo.lnurlPayUnprocessedSuccessAction!), + "lnurlWithdrawEndpoint": lnUrlInfo.lnurlWithdrawEndpoint == nil ? nil : lnUrlInfo.lnurlWithdrawEndpoint, + ] + } + + static func asLnUrlInfoList(arr: [Any]) throws -> [LnUrlInfo] { + var list = [LnUrlInfo]() + for value in arr { + if let val = value as? [String: Any?] { + var lnUrlInfo = try asLnUrlInfo(lnUrlInfo: val) + list.append(lnUrlInfo) + } else { + throw SdkError.Generic(message: errUnexpectedType(typeName: "LnUrlInfo")) + } + } + return list + } + + static func arrayOf(lnUrlInfoList: [LnUrlInfo]) -> [Any] { + return lnUrlInfoList.map { v -> [String: Any?] in return dictionaryOf(lnUrlInfo: v) } + } + static func asLnUrlPayErrorData(lnUrlPayErrorData: [String: Any?]) throws -> LnUrlPayErrorData { guard let paymentHash = lnUrlPayErrorData["paymentHash"] as? String else { throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "paymentHash", typeName: "LnUrlPayErrorData")) @@ -1976,18 +2065,32 @@ enum BreezSDKLiquidMapper { guard let feesSat = prepareLnUrlPayResponse["feesSat"] as? UInt64 else { throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "feesSat", typeName: "PrepareLnUrlPayResponse")) } + guard let dataTmp = prepareLnUrlPayResponse["data"] as? [String: Any?] else { + throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "data", typeName: "PrepareLnUrlPayResponse")) + } + let data = try asLnUrlPayRequestData(lnUrlPayRequestData: dataTmp) + + var comment: String? + if hasNonNilKey(data: prepareLnUrlPayResponse, key: "comment") { + guard let commentTmp = prepareLnUrlPayResponse["comment"] as? String else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "comment")) + } + comment = commentTmp + } var successAction: SuccessAction? if let successActionTmp = prepareLnUrlPayResponse["successAction"] as? [String: Any?] { successAction = try asSuccessAction(successAction: successActionTmp) } - return PrepareLnUrlPayResponse(destination: destination, feesSat: feesSat, successAction: successAction) + return PrepareLnUrlPayResponse(destination: destination, feesSat: feesSat, data: data, comment: comment, successAction: successAction) } static func dictionaryOf(prepareLnUrlPayResponse: PrepareLnUrlPayResponse) -> [String: Any?] { return [ "destination": dictionaryOf(sendDestination: prepareLnUrlPayResponse.destination), "feesSat": prepareLnUrlPayResponse.feesSat, + "data": dictionaryOf(lnUrlPayRequestData: prepareLnUrlPayResponse.data), + "comment": prepareLnUrlPayResponse.comment == nil ? nil : prepareLnUrlPayResponse.comment, "successAction": prepareLnUrlPayResponse.successAction == nil ? nil : dictionaryOf(successAction: prepareLnUrlPayResponse.successAction!), ] } @@ -3764,11 +3867,16 @@ enum BreezSDKLiquidMapper { let _paymentHash = paymentDetails["paymentHash"] as? String + var _lnurlInfo: LnUrlInfo? + if let lnurlInfoTmp = paymentDetails["lnurlInfo"] as? [String: Any?] { + _lnurlInfo = try asLnUrlInfo(lnUrlInfo: lnurlInfoTmp) + } + let _refundTxId = paymentDetails["refundTxId"] as? String let _refundTxAmountSat = paymentDetails["refundTxAmountSat"] as? UInt64 - return PaymentDetails.lightning(swapId: _swapId, description: _description, preimage: _preimage, bolt11: _bolt11, bolt12Offer: _bolt12Offer, paymentHash: _paymentHash, refundTxId: _refundTxId, refundTxAmountSat: _refundTxAmountSat) + return PaymentDetails.lightning(swapId: _swapId, description: _description, preimage: _preimage, bolt11: _bolt11, bolt12Offer: _bolt12Offer, paymentHash: _paymentHash, lnurlInfo: _lnurlInfo, refundTxId: _refundTxId, refundTxAmountSat: _refundTxAmountSat) } if type == "liquid" { guard let _destination = paymentDetails["destination"] as? String else { @@ -3799,7 +3907,7 @@ enum BreezSDKLiquidMapper { static func dictionaryOf(paymentDetails: PaymentDetails) -> [String: Any?] { switch paymentDetails { case let .lightning( - swapId, description, preimage, bolt11, bolt12Offer, paymentHash, refundTxId, refundTxAmountSat + swapId, description, preimage, bolt11, bolt12Offer, paymentHash, lnurlInfo, refundTxId, refundTxAmountSat ): return [ "type": "lightning", @@ -3809,6 +3917,7 @@ enum BreezSDKLiquidMapper { "bolt11": bolt11 == nil ? nil : bolt11, "bolt12Offer": bolt12Offer == nil ? nil : bolt12Offer, "paymentHash": paymentHash == nil ? nil : paymentHash, + "lnurlInfo": lnurlInfo == nil ? nil : dictionaryOf(lnUrlInfo: lnurlInfo!), "refundTxId": refundTxId == nil ? nil : refundTxId, "refundTxAmountSat": refundTxAmountSat == nil ? nil : refundTxAmountSat, ]