From deb9ed1b098083b92d1787adf886a904d1aacca7 Mon Sep 17 00:00:00 2001 From: Ross Savage <551697+dangeross@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:17:10 +0200 Subject: [PATCH] Add description hash to receive payment (#440) * Add option to hash description * Fix Flutter gen * Switch to upstream boltz-rust * Address feedback --- cli/Cargo.lock | 2 +- cli/src/commands.rs | 6 + lib/Cargo.lock | 2 +- .../include/breez_sdk_liquid.h | 8 +- lib/bindings/src/breez_sdk_liquid.udl | 2 + lib/core/Cargo.toml | 2 +- lib/core/src/error.rs | 3 + lib/core/src/frb_generated.io.rs | 6 + lib/core/src/frb_generated.rs | 132 +++++++++++------- lib/core/src/model.rs | 5 +- lib/core/src/sdk.rs | 27 +++- packages/dart/lib/src/error.dart | 3 + packages/dart/lib/src/error.freezed.dart | 81 +++++++++++ packages/dart/lib/src/frb_generated.dart | 90 +++++++----- packages/dart/lib/src/frb_generated.io.dart | 45 ++++-- packages/dart/lib/src/model.dart | 15 +- ...utter_breez_liquid_bindings_generated.dart | 10 +- .../breezsdkliquid/BreezSDKLiquidMapper.kt | 13 +- .../ios/BreezSDKLiquidMapper.swift | 10 +- packages/react-native/src/index.ts | 1 + 20 files changed, 344 insertions(+), 119 deletions(-) diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 27d4705..e7a89d3 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "boltz-client" version = "0.1.3" -source = "git+https://github.com/dangeross/boltz-rust?branch=savage-breez-20240807#7e3ebb1fc43b8b9bda041d76a07fb85bd7251085" +source = "git+https://github.com/SatoshiPortal/boltz-rust?rev=c140193dab075093e1cfdcc1dd608be8e828d1ef#c140193dab075093e1cfdcc1dd608be8e828d1ef" dependencies = [ "bip39", "bitcoin 0.31.2", diff --git a/cli/src/commands.rs b/cli/src/commands.rs index e3cc2df..8867802 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -68,6 +68,10 @@ pub(crate) enum Command { /// Optional description for the invoice #[clap(short = 'd', long = "description")] description: Option, + + /// Optional if true uses the hash of the description + #[clap(name = "use_description_hash", short = 's', long = "desc_hash")] + use_description_hash: Option, }, /// Generates an URL to buy bitcoin from a 3rd party provider BuyBitcoin { @@ -218,6 +222,7 @@ pub(crate) async fn handle_command( payment_method, payer_amount_sat, description, + use_description_hash, } => { let prepare_response = sdk .prepare_receive_payment(&PrepareReceiveRequest { @@ -238,6 +243,7 @@ pub(crate) async fn handle_command( .receive_payment(&ReceivePaymentRequest { prepare_response, description, + use_description_hash, }) .await?; diff --git a/lib/Cargo.lock b/lib/Cargo.lock index d53ca99..f2fc52e 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "boltz-client" version = "0.1.3" -source = "git+https://github.com/dangeross/boltz-rust?branch=savage-breez-20240807#7e3ebb1fc43b8b9bda041d76a07fb85bd7251085" +source = "git+https://github.com/SatoshiPortal/boltz-rust?rev=c140193dab075093e1cfdcc1dd608be8e828d1ef#c140193dab075093e1cfdcc1dd608be8e828d1ef" dependencies = [ "bip39", "bitcoin 0.31.2", 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 8a3f99e..8bf9d23 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 @@ -155,8 +155,9 @@ typedef struct wire_cst_prepare_receive_response { } wire_cst_prepare_receive_response; typedef struct wire_cst_receive_payment_request { - struct wire_cst_list_prim_u_8_strict *description; struct wire_cst_prepare_receive_response prepare_response; + struct wire_cst_list_prim_u_8_strict *description; + bool *use_description_hash; } wire_cst_receive_payment_request; typedef struct wire_cst_refund_request { @@ -777,6 +778,10 @@ typedef struct wire_cst_PaymentError_Generic { struct wire_cst_list_prim_u_8_strict *err; } wire_cst_PaymentError_Generic; +typedef struct wire_cst_PaymentError_InvalidDescription { + struct wire_cst_list_prim_u_8_strict *err; +} wire_cst_PaymentError_InvalidDescription; + typedef struct wire_cst_PaymentError_InvalidInvoice { struct wire_cst_list_prim_u_8_strict *err; } wire_cst_PaymentError_InvalidInvoice; @@ -806,6 +811,7 @@ typedef union PaymentErrorKind { struct wire_cst_PaymentError_AmountMissing AmountMissing; struct wire_cst_PaymentError_InvalidNetwork InvalidNetwork; struct wire_cst_PaymentError_Generic Generic; + struct wire_cst_PaymentError_InvalidDescription InvalidDescription; struct wire_cst_PaymentError_InvalidInvoice InvalidInvoice; struct wire_cst_PaymentError_LwkError LwkError; struct wire_cst_PaymentError_ReceiveError ReceiveError; diff --git a/lib/bindings/src/breez_sdk_liquid.udl b/lib/bindings/src/breez_sdk_liquid.udl index 8b58507..cf238ae 100644 --- a/lib/bindings/src/breez_sdk_liquid.udl +++ b/lib/bindings/src/breez_sdk_liquid.udl @@ -282,6 +282,7 @@ enum PaymentError { "Generic", "InvalidOrExpiredFees", "InsufficientFunds", + "InvalidDescription", "InvalidInvoice", "InvalidNetwork", "InvalidPreimage", @@ -368,6 +369,7 @@ dictionary PrepareReceiveResponse { dictionary ReceivePaymentRequest { PrepareReceiveResponse prepare_response; string? description = null; + boolean? use_description_hash = null; }; dictionary ReceivePaymentResponse { diff --git a/lib/core/Cargo.toml b/lib/core/Cargo.toml index 79f2910..86010e9 100644 --- a/lib/core/Cargo.toml +++ b/lib/core/Cargo.toml @@ -14,7 +14,7 @@ frb = ["dep:flutter_rust_bridge"] [dependencies] anyhow = { workspace = true } bip39 = "2.0.0" -boltz-client = { git = "https://github.com/dangeross/boltz-rust", branch = "savage-breez-20240807" } +boltz-client = { git = "https://github.com/SatoshiPortal/boltz-rust", rev = "c140193dab075093e1cfdcc1dd608be8e828d1ef" } chrono = "0.4" env_logger = "0.11" flutter_rust_bridge = { version = "=2.2.0", features = [ diff --git a/lib/core/src/error.rs b/lib/core/src/error.rs index 70371ba..6c2e622 100644 --- a/lib/core/src/error.rs +++ b/lib/core/src/error.rs @@ -85,6 +85,9 @@ pub enum PaymentError { #[error("Cannot pay: not enough funds")] InsufficientFunds, + #[error("Invalid description: {err}")] + InvalidDescription { err: String }, + #[error("The specified invoice is not valid: {err}")] InvalidInvoice { err: String }, diff --git a/lib/core/src/frb_generated.io.rs b/lib/core/src/frb_generated.io.rs index 97b4ea9..70d898d 100644 --- a/lib/core/src/frb_generated.io.rs +++ b/lib/core/src/frb_generated.io.rs @@ -3927,6 +3927,7 @@ pub union PaymentErrorKind { AmountMissing: wire_cst_PaymentError_AmountMissing, NetworkMismatch: wire_cst_PaymentError_NetworkMismatch, Generic: wire_cst_PaymentError_Generic, + InvalidDescription: wire_cst_PaymentError_InvalidDescription, InvalidInvoice: wire_cst_PaymentError_InvalidInvoice, LwkError: wire_cst_PaymentError_LwkError, ReceiveError: wire_cst_PaymentError_ReceiveError, @@ -3952,6 +3953,11 @@ pub struct wire_cst_PaymentError_Generic { } #[repr(C)] #[derive(Clone, Copy)] +pub struct wire_cst_PaymentError_InvalidDescription { + err: *mut wire_cst_list_prim_u_8_strict, +} +#[repr(C)] +#[derive(Clone, Copy)] pub struct wire_cst_PaymentError_InvalidInvoice { err: *mut wire_cst_list_prim_u_8_strict, } diff --git a/lib/core/src/frb_generated.rs b/lib/core/src/frb_generated.rs index 2396bb4..d692bb8 100644 --- a/lib/core/src/frb_generated.rs +++ b/lib/core/src/frb_generated.rs @@ -3097,29 +3097,33 @@ impl SseDecode for crate::error::PaymentError { } 9 => { let mut var_err = ::sse_decode(deserializer); - return crate::error::PaymentError::InvalidInvoice { err: var_err }; + return crate::error::PaymentError::InvalidDescription { err: var_err }; } 10 => { - return crate::error::PaymentError::InvalidPreimage; + let mut var_err = ::sse_decode(deserializer); + return crate::error::PaymentError::InvalidInvoice { err: var_err }; } 11 => { + return crate::error::PaymentError::InvalidPreimage; + } + 12 => { let mut var_err = ::sse_decode(deserializer); return crate::error::PaymentError::LwkError { err: var_err }; } - 12 => { + 13 => { return crate::error::PaymentError::PairsNotFound; } - 13 => { + 14 => { return crate::error::PaymentError::PaymentTimeout; } - 14 => { + 15 => { return crate::error::PaymentError::PersistError; } - 15 => { + 16 => { let mut var_err = ::sse_decode(deserializer); return crate::error::PaymentError::ReceiveError { err: var_err }; } - 16 => { + 17 => { let mut var_err = ::sse_decode(deserializer); let mut var_refundTxId = ::sse_decode(deserializer); return crate::error::PaymentError::Refunded { @@ -3127,14 +3131,14 @@ impl SseDecode for crate::error::PaymentError { refund_tx_id: var_refundTxId, }; } - 17 => { + 18 => { return crate::error::PaymentError::SelfTransferNotSupported; } - 18 => { + 19 => { let mut var_err = ::sse_decode(deserializer); return crate::error::PaymentError::SendError { err: var_err }; } - 19 => { + 20 => { let mut var_err = ::sse_decode(deserializer); return crate::error::PaymentError::SignerError { err: var_err }; } @@ -3332,12 +3336,14 @@ impl SseDecode for crate::bindings::Rate { impl SseDecode for crate::model::ReceivePaymentRequest { // 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_description = >::sse_decode(deserializer); let mut var_prepareResponse = ::sse_decode(deserializer); + let mut var_description = >::sse_decode(deserializer); + let mut var_useDescriptionHash = >::sse_decode(deserializer); return crate::model::ReceivePaymentRequest { - description: var_description, prepare_response: var_prepareResponse, + description: var_description, + use_description_hash: var_useDescriptionHash, }; } } @@ -4794,31 +4800,34 @@ impl flutter_rust_bridge::IntoDart for crate::error::PaymentError { } crate::error::PaymentError::InvalidOrExpiredFees => [7.into_dart()].into_dart(), crate::error::PaymentError::InsufficientFunds => [8.into_dart()].into_dart(), - crate::error::PaymentError::InvalidInvoice { err } => { + crate::error::PaymentError::InvalidDescription { err } => { [9.into_dart(), err.into_into_dart().into_dart()].into_dart() } - crate::error::PaymentError::InvalidPreimage => [10.into_dart()].into_dart(), - crate::error::PaymentError::LwkError { err } => { - [11.into_dart(), err.into_into_dart().into_dart()].into_dart() + crate::error::PaymentError::InvalidInvoice { err } => { + [10.into_dart(), err.into_into_dart().into_dart()].into_dart() } - crate::error::PaymentError::PairsNotFound => [12.into_dart()].into_dart(), - crate::error::PaymentError::PaymentTimeout => [13.into_dart()].into_dart(), - crate::error::PaymentError::PersistError => [14.into_dart()].into_dart(), + crate::error::PaymentError::InvalidPreimage => [11.into_dart()].into_dart(), + crate::error::PaymentError::LwkError { err } => { + [12.into_dart(), err.into_into_dart().into_dart()].into_dart() + } + crate::error::PaymentError::PairsNotFound => [13.into_dart()].into_dart(), + crate::error::PaymentError::PaymentTimeout => [14.into_dart()].into_dart(), + crate::error::PaymentError::PersistError => [15.into_dart()].into_dart(), crate::error::PaymentError::ReceiveError { err } => { - [15.into_dart(), err.into_into_dart().into_dart()].into_dart() + [16.into_dart(), err.into_into_dart().into_dart()].into_dart() } crate::error::PaymentError::Refunded { err, refund_tx_id } => [ - 16.into_dart(), + 17.into_dart(), err.into_into_dart().into_dart(), refund_tx_id.into_into_dart().into_dart(), ] .into_dart(), - crate::error::PaymentError::SelfTransferNotSupported => [17.into_dart()].into_dart(), + crate::error::PaymentError::SelfTransferNotSupported => [18.into_dart()].into_dart(), crate::error::PaymentError::SendError { err } => { - [18.into_dart(), err.into_into_dart().into_dart()].into_dart() + [19.into_dart(), err.into_into_dart().into_dart()].into_dart() } crate::error::PaymentError::SignerError { err } => { - [19.into_dart(), err.into_into_dart().into_dart()].into_dart() + [20.into_dart(), err.into_into_dart().into_dart()].into_dart() } _ => { unimplemented!(""); @@ -5128,8 +5137,9 @@ impl flutter_rust_bridge::IntoIntoDart> impl flutter_rust_bridge::IntoDart for crate::model::ReceivePaymentRequest { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.description.into_into_dart().into_dart(), self.prepare_response.into_into_dart().into_dart(), + self.description.into_into_dart().into_dart(), + self.use_description_hash.into_into_dart().into_dart(), ] .into_dart() } @@ -6439,44 +6449,48 @@ impl SseEncode for crate::error::PaymentError { crate::error::PaymentError::InsufficientFunds => { ::sse_encode(8, serializer); } - crate::error::PaymentError::InvalidInvoice { err } => { + crate::error::PaymentError::InvalidDescription { err } => { ::sse_encode(9, serializer); ::sse_encode(err, serializer); } - crate::error::PaymentError::InvalidPreimage => { + crate::error::PaymentError::InvalidInvoice { err } => { ::sse_encode(10, serializer); + ::sse_encode(err, serializer); + } + crate::error::PaymentError::InvalidPreimage => { + ::sse_encode(11, serializer); } crate::error::PaymentError::LwkError { err } => { - ::sse_encode(11, serializer); + ::sse_encode(12, serializer); ::sse_encode(err, serializer); } crate::error::PaymentError::PairsNotFound => { - ::sse_encode(12, serializer); - } - crate::error::PaymentError::PaymentTimeout => { ::sse_encode(13, serializer); } - crate::error::PaymentError::PersistError => { + crate::error::PaymentError::PaymentTimeout => { ::sse_encode(14, serializer); } - crate::error::PaymentError::ReceiveError { err } => { + crate::error::PaymentError::PersistError => { ::sse_encode(15, serializer); + } + crate::error::PaymentError::ReceiveError { err } => { + ::sse_encode(16, serializer); ::sse_encode(err, serializer); } crate::error::PaymentError::Refunded { err, refund_tx_id } => { - ::sse_encode(16, serializer); + ::sse_encode(17, serializer); ::sse_encode(err, serializer); ::sse_encode(refund_tx_id, serializer); } crate::error::PaymentError::SelfTransferNotSupported => { - ::sse_encode(17, serializer); + ::sse_encode(18, serializer); } crate::error::PaymentError::SendError { err } => { - ::sse_encode(18, serializer); + ::sse_encode(19, serializer); ::sse_encode(err, serializer); } crate::error::PaymentError::SignerError { err } => { - ::sse_encode(19, serializer); + ::sse_encode(20, serializer); ::sse_encode(err, serializer); } _ => { @@ -6636,8 +6650,9 @@ impl SseEncode for crate::bindings::Rate { impl SseEncode for crate::model::ReceivePaymentRequest { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.description, serializer); ::sse_encode(self.prepare_response, serializer); + >::sse_encode(self.description, serializer); + >::sse_encode(self.use_description_hash, serializer); } } @@ -8075,42 +8090,48 @@ mod io { 7 => crate::error::PaymentError::InvalidOrExpiredFees, 8 => crate::error::PaymentError::InsufficientFunds, 9 => { + let ans = unsafe { self.kind.InvalidDescription }; + crate::error::PaymentError::InvalidDescription { + err: ans.err.cst_decode(), + } + } + 10 => { let ans = unsafe { self.kind.InvalidInvoice }; crate::error::PaymentError::InvalidInvoice { err: ans.err.cst_decode(), } } - 10 => crate::error::PaymentError::InvalidPreimage, - 11 => { + 11 => crate::error::PaymentError::InvalidPreimage, + 12 => { let ans = unsafe { self.kind.LwkError }; crate::error::PaymentError::LwkError { err: ans.err.cst_decode(), } } - 12 => crate::error::PaymentError::PairsNotFound, - 13 => crate::error::PaymentError::PaymentTimeout, - 14 => crate::error::PaymentError::PersistError, - 15 => { + 13 => crate::error::PaymentError::PairsNotFound, + 14 => crate::error::PaymentError::PaymentTimeout, + 15 => crate::error::PaymentError::PersistError, + 16 => { let ans = unsafe { self.kind.ReceiveError }; crate::error::PaymentError::ReceiveError { err: ans.err.cst_decode(), } } - 16 => { + 17 => { let ans = unsafe { self.kind.Refunded }; crate::error::PaymentError::Refunded { err: ans.err.cst_decode(), refund_tx_id: ans.refund_tx_id.cst_decode(), } } - 17 => crate::error::PaymentError::SelfTransferNotSupported, - 18 => { + 18 => crate::error::PaymentError::SelfTransferNotSupported, + 19 => { let ans = unsafe { self.kind.SendError }; crate::error::PaymentError::SendError { err: ans.err.cst_decode(), } } - 19 => { + 20 => { let ans = unsafe { self.kind.SignerError }; crate::error::PaymentError::SignerError { err: ans.err.cst_decode(), @@ -8228,8 +8249,9 @@ mod io { // Codec=Cst (C-struct based), see doc to use other codecs fn cst_decode(self) -> crate::model::ReceivePaymentRequest { crate::model::ReceivePaymentRequest { - description: self.description.cst_decode(), prepare_response: self.prepare_response.cst_decode(), + description: self.description.cst_decode(), + use_description_hash: self.use_description_hash.cst_decode(), } } } @@ -9197,8 +9219,9 @@ mod io { impl NewWithNullPtr for wire_cst_receive_payment_request { fn new_with_null_ptr() -> Self { Self { - description: core::ptr::null_mut(), prepare_response: Default::default(), + description: core::ptr::null_mut(), + use_description_hash: core::ptr::null_mut(), } } } @@ -10839,6 +10862,7 @@ mod io { AmountMissing: wire_cst_PaymentError_AmountMissing, InvalidNetwork: wire_cst_PaymentError_InvalidNetwork, Generic: wire_cst_PaymentError_Generic, + InvalidDescription: wire_cst_PaymentError_InvalidDescription, InvalidInvoice: wire_cst_PaymentError_InvalidInvoice, LwkError: wire_cst_PaymentError_LwkError, ReceiveError: wire_cst_PaymentError_ReceiveError, @@ -10864,6 +10888,11 @@ mod io { } #[repr(C)] #[derive(Clone, Copy)] + pub struct wire_cst_PaymentError_InvalidDescription { + err: *mut wire_cst_list_prim_u_8_strict, + } + #[repr(C)] + #[derive(Clone, Copy)] pub struct wire_cst_PaymentError_InvalidInvoice { err: *mut wire_cst_list_prim_u_8_strict, } @@ -10967,8 +10996,9 @@ mod io { #[repr(C)] #[derive(Clone, Copy)] pub struct wire_cst_receive_payment_request { - description: *mut wire_cst_list_prim_u_8_strict, prepare_response: wire_cst_prepare_receive_response, + description: *mut wire_cst_list_prim_u_8_strict, + use_description_hash: *mut bool, } #[repr(C)] #[derive(Clone, Copy)] diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs index 371efb1..9706c2a 100644 --- a/lib/core/src/model.rs +++ b/lib/core/src/model.rs @@ -224,8 +224,11 @@ pub struct PrepareReceiveResponse { /// An argument when calling [crate::sdk::LiquidSdk::receive_payment]. #[derive(Debug, Serialize)] pub struct ReceivePaymentRequest { - pub description: Option, pub prepare_response: PrepareReceiveResponse, + /// The description for this payment request. + pub description: Option, + /// If set to true, then the hash of the description will be used. + pub use_description_hash: Option, } /// Returned when calling [crate::sdk::LiquidSdk::receive_payment]. diff --git a/lib/core/src/sdk.rs b/lib/core/src/sdk.rs index f2a9cf2..cb85ccd 100644 --- a/lib/core/src/sdk.rs +++ b/lib/core/src/sdk.rs @@ -1400,8 +1400,9 @@ impl LiquidSdk { /// # Arguments /// /// * `req` - the [ReceivePaymentRequest] containing: - /// * `description` - the optional payment description /// * `prepare_response` - the [PrepareReceiveResponse] from calling [LiquidSdk::prepare_receive_payment] + /// * `description` - the optional payment description + /// * `use_description_hash` - optional if true uses the hash of the description /// /// # Returns /// @@ -1424,7 +1425,22 @@ impl LiquidSdk { let Some(amount_sat) = amount_sat else { return Err(PaymentError::AmountMissing { err: "`amount_sat` must be specified when `PaymentMethod::Lightning` is used.".to_string() }); }; - self.create_receive_swap(*amount_sat, *fees_sat, req.description.clone()) + let (description, description_hash) = match ( + req.description.clone(), + req.use_description_hash.unwrap_or_default(), + ) { + (Some(description), true) => ( + None, + Some(sha256::Hash::hash(description.as_bytes()).to_hex()), + ), + (_, false) => (req.description.clone(), None), + _ => { + return Err(PaymentError::InvalidDescription { + err: "Missing payment description to hash".to_string(), + }) + } + }; + self.create_receive_swap(*amount_sat, *fees_sat, description, description_hash) .await } PaymentMethod::BitcoinAddress => { @@ -1464,6 +1480,7 @@ impl LiquidSdk { payer_amount_sat: u64, fees_sat: u64, description: Option, + description_hash: Option, ) -> Result { let reverse_pair = self .swapper @@ -1507,6 +1524,7 @@ impl LiquidSdk { preimage_hash: preimage.sha256, claim_public_key: keypair.public_key().into(), description, + description_hash, address: Some(mrh_addr_str.clone()), address_signature: Some(mrh_addr_hash_sig.to_hex()), referral_id: None, @@ -1551,7 +1569,7 @@ impl LiquidSdk { &swap_id, &invoice.to_string(), )?; - let description = match invoice.description() { + let invoice_description = match invoice.description() { Bolt11InvoiceDescription::Direct(msg) => Some(msg.to_string()), Bolt11InvoiceDescription::Hash(_) => None, }; @@ -1562,7 +1580,7 @@ impl LiquidSdk { create_response_json, claim_private_key: keypair.display_secret().to_string(), invoice: invoice.to_string(), - description, + description: invoice_description, payer_amount_sat, receiver_amount_sat, claim_fees_sat: reverse_pair.fees.claim_estimate(), @@ -2094,6 +2112,7 @@ impl LiquidSdk { .receive_payment(&ReceivePaymentRequest { prepare_response, description: None, + use_description_hash: Some(false), }) .await?; diff --git a/packages/dart/lib/src/error.dart b/packages/dart/lib/src/error.dart index 0ac0cb2..ceb24ab 100644 --- a/packages/dart/lib/src/error.dart +++ b/packages/dart/lib/src/error.dart @@ -27,6 +27,9 @@ sealed class PaymentError with _$PaymentError implements FrbException { }) = PaymentError_Generic; const factory PaymentError.invalidOrExpiredFees() = PaymentError_InvalidOrExpiredFees; const factory PaymentError.insufficientFunds() = PaymentError_InsufficientFunds; + const factory PaymentError.invalidDescription({ + required String err, + }) = PaymentError_InvalidDescription; const factory PaymentError.invalidInvoice({ required String err, }) = PaymentError_InvalidInvoice; diff --git a/packages/dart/lib/src/error.freezed.dart b/packages/dart/lib/src/error.freezed.dart index 4df3bc2..5efacc7 100644 --- a/packages/dart/lib/src/error.freezed.dart +++ b/packages/dart/lib/src/error.freezed.dart @@ -537,6 +537,87 @@ abstract class PaymentError_InsufficientFunds extends PaymentError { const PaymentError_InsufficientFunds._() : super._(); } +/// @nodoc +abstract class _$$PaymentError_InvalidDescriptionImplCopyWith<$Res> { + factory _$$PaymentError_InvalidDescriptionImplCopyWith(_$PaymentError_InvalidDescriptionImpl value, + $Res Function(_$PaymentError_InvalidDescriptionImpl) then) = + __$$PaymentError_InvalidDescriptionImplCopyWithImpl<$Res>; + @useResult + $Res call({String err}); +} + +/// @nodoc +class __$$PaymentError_InvalidDescriptionImplCopyWithImpl<$Res> + extends _$PaymentErrorCopyWithImpl<$Res, _$PaymentError_InvalidDescriptionImpl> + implements _$$PaymentError_InvalidDescriptionImplCopyWith<$Res> { + __$$PaymentError_InvalidDescriptionImplCopyWithImpl(_$PaymentError_InvalidDescriptionImpl _value, + $Res Function(_$PaymentError_InvalidDescriptionImpl) _then) + : super(_value, _then); + + /// Create a copy of PaymentError + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? err = null, + }) { + return _then(_$PaymentError_InvalidDescriptionImpl( + err: null == err + ? _value.err + : err // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$PaymentError_InvalidDescriptionImpl extends PaymentError_InvalidDescription { + const _$PaymentError_InvalidDescriptionImpl({required this.err}) : super._(); + + @override + final String err; + + @override + String toString() { + return 'PaymentError.invalidDescription(err: $err)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentError_InvalidDescriptionImpl && + (identical(other.err, err) || other.err == err)); + } + + @override + int get hashCode => Object.hash(runtimeType, err); + + /// Create a copy of PaymentError + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentError_InvalidDescriptionImplCopyWith<_$PaymentError_InvalidDescriptionImpl> get copyWith => + __$$PaymentError_InvalidDescriptionImplCopyWithImpl<_$PaymentError_InvalidDescriptionImpl>( + this, _$identity); +} + +abstract class PaymentError_InvalidDescription extends PaymentError { + const factory PaymentError_InvalidDescription({required final String err}) = + _$PaymentError_InvalidDescriptionImpl; + const PaymentError_InvalidDescription._() : super._(); + + String get err; + + /// Create a copy of PaymentError + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentError_InvalidDescriptionImplCopyWith<_$PaymentError_InvalidDescriptionImpl> get copyWith => + throw _privateConstructorUsedError; +} + /// @nodoc abstract class _$$PaymentError_InvalidInvoiceImplCopyWith<$Res> { factory _$$PaymentError_InvalidInvoiceImplCopyWith( diff --git a/packages/dart/lib/src/frb_generated.dart b/packages/dart/lib/src/frb_generated.dart index 22b1700..26e8218 100644 --- a/packages/dart/lib/src/frb_generated.dart +++ b/packages/dart/lib/src/frb_generated.dart @@ -2196,37 +2196,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 8: return PaymentError_InsufficientFunds(); case 9: - return PaymentError_InvalidInvoice( + return PaymentError_InvalidDescription( err: dco_decode_String(raw[1]), ); case 10: - return PaymentError_InvalidPreimage(); + return PaymentError_InvalidInvoice( + err: dco_decode_String(raw[1]), + ); case 11: + return PaymentError_InvalidPreimage(); + case 12: return PaymentError_LwkError( err: dco_decode_String(raw[1]), ); - case 12: - return PaymentError_PairsNotFound(); case 13: - return PaymentError_PaymentTimeout(); + return PaymentError_PairsNotFound(); case 14: - return PaymentError_PersistError(); + return PaymentError_PaymentTimeout(); case 15: + return PaymentError_PersistError(); + case 16: return PaymentError_ReceiveError( err: dco_decode_String(raw[1]), ); - case 16: + case 17: return PaymentError_Refunded( err: dco_decode_String(raw[1]), refundTxId: dco_decode_String(raw[2]), ); - case 17: - return PaymentError_SelfTransferNotSupported(); case 18: + return PaymentError_SelfTransferNotSupported(); + case 19: return PaymentError_SendError( err: dco_decode_String(raw[1]), ); - case 19: + case 20: return PaymentError_SignerError( err: dco_decode_String(raw[1]), ); @@ -2383,10 +2387,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ReceivePaymentRequest dco_decode_receive_payment_request(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return ReceivePaymentRequest( - description: dco_decode_opt_String(arr[0]), - prepareResponse: dco_decode_prepare_receive_response(arr[1]), + prepareResponse: dco_decode_prepare_receive_response(arr[0]), + description: dco_decode_opt_String(arr[1]), + useDescriptionHash: dco_decode_opt_box_autoadd_bool(arr[2]), ); } @@ -3860,31 +3865,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return PaymentError_InsufficientFunds(); case 9: var var_err = sse_decode_String(deserializer); - return PaymentError_InvalidInvoice(err: var_err); + return PaymentError_InvalidDescription(err: var_err); case 10: - return PaymentError_InvalidPreimage(); + var var_err = sse_decode_String(deserializer); + return PaymentError_InvalidInvoice(err: var_err); case 11: + return PaymentError_InvalidPreimage(); + case 12: var var_err = sse_decode_String(deserializer); return PaymentError_LwkError(err: var_err); - case 12: - return PaymentError_PairsNotFound(); case 13: - return PaymentError_PaymentTimeout(); + return PaymentError_PairsNotFound(); case 14: - return PaymentError_PersistError(); + return PaymentError_PaymentTimeout(); case 15: + return PaymentError_PersistError(); + case 16: var var_err = sse_decode_String(deserializer); return PaymentError_ReceiveError(err: var_err); - case 16: + case 17: var var_err = sse_decode_String(deserializer); var var_refundTxId = sse_decode_String(deserializer); return PaymentError_Refunded(err: var_err, refundTxId: var_refundTxId); - case 17: - return PaymentError_SelfTransferNotSupported(); case 18: + return PaymentError_SelfTransferNotSupported(); + case 19: var var_err = sse_decode_String(deserializer); return PaymentError_SendError(err: var_err); - case 19: + case 20: var var_err = sse_decode_String(deserializer); return PaymentError_SignerError(err: var_err); default: @@ -4014,9 +4022,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected ReceivePaymentRequest sse_decode_receive_payment_request(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - var var_description = sse_decode_opt_String(deserializer); var var_prepareResponse = sse_decode_prepare_receive_response(deserializer); - return ReceivePaymentRequest(description: var_description, prepareResponse: var_prepareResponse); + var var_description = sse_decode_opt_String(deserializer); + var var_useDescriptionHash = sse_decode_opt_box_autoadd_bool(deserializer); + return ReceivePaymentRequest( + prepareResponse: var_prepareResponse, + description: var_description, + useDescriptionHash: var_useDescriptionHash); } @protected @@ -5414,34 +5426,37 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_32(7, serializer); case PaymentError_InsufficientFunds(): sse_encode_i_32(8, serializer); - case PaymentError_InvalidInvoice(err: final err): + case PaymentError_InvalidDescription(err: final err): sse_encode_i_32(9, serializer); sse_encode_String(err, serializer); - case PaymentError_InvalidPreimage(): + case PaymentError_InvalidInvoice(err: final err): sse_encode_i_32(10, serializer); - case PaymentError_LwkError(err: final err): + sse_encode_String(err, serializer); + case PaymentError_InvalidPreimage(): sse_encode_i_32(11, serializer); + case PaymentError_LwkError(err: final err): + sse_encode_i_32(12, serializer); sse_encode_String(err, serializer); case PaymentError_PairsNotFound(): - sse_encode_i_32(12, serializer); - case PaymentError_PaymentTimeout(): sse_encode_i_32(13, serializer); - case PaymentError_PersistError(): + case PaymentError_PaymentTimeout(): sse_encode_i_32(14, serializer); - case PaymentError_ReceiveError(err: final err): + case PaymentError_PersistError(): sse_encode_i_32(15, serializer); + case PaymentError_ReceiveError(err: final err): + sse_encode_i_32(16, serializer); sse_encode_String(err, serializer); case PaymentError_Refunded(err: final err, refundTxId: final refundTxId): - sse_encode_i_32(16, serializer); + sse_encode_i_32(17, serializer); sse_encode_String(err, serializer); sse_encode_String(refundTxId, serializer); case PaymentError_SelfTransferNotSupported(): - sse_encode_i_32(17, serializer); - case PaymentError_SendError(err: final err): sse_encode_i_32(18, serializer); + case PaymentError_SendError(err: final err): + sse_encode_i_32(19, serializer); sse_encode_String(err, serializer); case PaymentError_SignerError(err: final err): - sse_encode_i_32(19, serializer); + sse_encode_i_32(20, serializer); sse_encode_String(err, serializer); default: throw UnimplementedError(''); @@ -5551,8 +5566,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_receive_payment_request(ReceivePaymentRequest self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_opt_String(self.description, serializer); sse_encode_prepare_receive_response(self.prepareResponse, serializer); + sse_encode_opt_String(self.description, serializer); + sse_encode_opt_box_autoadd_bool(self.useDescriptionHash, serializer); } @protected diff --git a/packages/dart/lib/src/frb_generated.io.dart b/packages/dart/lib/src/frb_generated.io.dart index dbf9f77..0758e7e 100644 --- a/packages/dart/lib/src/frb_generated.io.dart +++ b/packages/dart/lib/src/frb_generated.io.dart @@ -2308,61 +2308,67 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { wireObj.tag = 8; return; } - if (apiObj is PaymentError_InvalidInvoice) { + if (apiObj is PaymentError_InvalidDescription) { var pre_err = cst_encode_String(apiObj.err); wireObj.tag = 9; + wireObj.kind.InvalidDescription.err = pre_err; + return; + } + if (apiObj is PaymentError_InvalidInvoice) { + var pre_err = cst_encode_String(apiObj.err); + wireObj.tag = 10; wireObj.kind.InvalidInvoice.err = pre_err; return; } if (apiObj is PaymentError_InvalidPreimage) { - wireObj.tag = 10; + wireObj.tag = 11; return; } if (apiObj is PaymentError_LwkError) { var pre_err = cst_encode_String(apiObj.err); - wireObj.tag = 11; + wireObj.tag = 12; wireObj.kind.LwkError.err = pre_err; return; } if (apiObj is PaymentError_PairsNotFound) { - wireObj.tag = 12; - return; - } - if (apiObj is PaymentError_PaymentTimeout) { wireObj.tag = 13; return; } - if (apiObj is PaymentError_PersistError) { + if (apiObj is PaymentError_PaymentTimeout) { wireObj.tag = 14; return; } + if (apiObj is PaymentError_PersistError) { + wireObj.tag = 15; + return; + } if (apiObj is PaymentError_ReceiveError) { var pre_err = cst_encode_String(apiObj.err); - wireObj.tag = 15; + wireObj.tag = 16; wireObj.kind.ReceiveError.err = pre_err; return; } if (apiObj is PaymentError_Refunded) { var pre_err = cst_encode_String(apiObj.err); var pre_refund_tx_id = cst_encode_String(apiObj.refundTxId); - wireObj.tag = 16; + wireObj.tag = 17; wireObj.kind.Refunded.err = pre_err; wireObj.kind.Refunded.refund_tx_id = pre_refund_tx_id; return; } if (apiObj is PaymentError_SelfTransferNotSupported) { - wireObj.tag = 17; + wireObj.tag = 18; return; } if (apiObj is PaymentError_SendError) { var pre_err = cst_encode_String(apiObj.err); - wireObj.tag = 18; + wireObj.tag = 19; wireObj.kind.SendError.err = pre_err; return; } if (apiObj is PaymentError_SignerError) { var pre_err = cst_encode_String(apiObj.err); - wireObj.tag = 19; + wireObj.tag = 20; wireObj.kind.SignerError.err = pre_err; return; } @@ -2452,8 +2458,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void cst_api_fill_to_wire_receive_payment_request( ReceivePaymentRequest apiObj, wire_cst_receive_payment_request wireObj) { - wireObj.description = cst_encode_opt_String(apiObj.description); cst_api_fill_to_wire_prepare_receive_response(apiObj.prepareResponse, wireObj.prepare_response); + wireObj.description = cst_encode_opt_String(apiObj.description); + wireObj.use_description_hash = cst_encode_opt_box_autoadd_bool(apiObj.useDescriptionHash); } @protected @@ -4641,9 +4648,11 @@ final class wire_cst_prepare_receive_response extends ffi.Struct { } final class wire_cst_receive_payment_request extends ffi.Struct { + external wire_cst_prepare_receive_response prepare_response; + external ffi.Pointer description; - external wire_cst_prepare_receive_response prepare_response; + external ffi.Pointer use_description_hash; } final class wire_cst_refund_request extends ffi.Struct { @@ -5457,6 +5466,10 @@ final class wire_cst_PaymentError_Generic extends ffi.Struct { external ffi.Pointer err; } +final class wire_cst_PaymentError_InvalidDescription extends ffi.Struct { + external ffi.Pointer err; +} + final class wire_cst_PaymentError_InvalidInvoice extends ffi.Struct { external ffi.Pointer err; } @@ -5490,6 +5503,8 @@ final class PaymentErrorKind extends ffi.Union { external wire_cst_PaymentError_Generic Generic; + external wire_cst_PaymentError_InvalidDescription InvalidDescription; + external wire_cst_PaymentError_InvalidInvoice InvalidInvoice; external wire_cst_PaymentError_LwkError LwkError; diff --git a/packages/dart/lib/src/model.dart b/packages/dart/lib/src/model.dart index a47a1db..fb27a91 100644 --- a/packages/dart/lib/src/model.dart +++ b/packages/dart/lib/src/model.dart @@ -844,24 +844,31 @@ class PrepareSendResponse { /// An argument when calling [crate::sdk::LiquidSdk::receive_payment]. class ReceivePaymentRequest { - final String? description; final PrepareReceiveResponse prepareResponse; + /// The description for this payment request. + final String? description; + + /// If set to true, then the hash of the description will be used. + final bool? useDescriptionHash; + const ReceivePaymentRequest({ - this.description, required this.prepareResponse, + this.description, + this.useDescriptionHash, }); @override - int get hashCode => description.hashCode ^ prepareResponse.hashCode; + int get hashCode => prepareResponse.hashCode ^ description.hashCode ^ useDescriptionHash.hashCode; @override bool operator ==(Object other) => identical(this, other) || other is ReceivePaymentRequest && runtimeType == other.runtimeType && + prepareResponse == other.prepareResponse && description == other.description && - prepareResponse == other.prepareResponse; + useDescriptionHash == other.useDescriptionHash; } /// Returned when calling [crate::sdk::LiquidSdk::receive_payment]. diff --git a/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart b/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart index 293dfdc..0b65053 100644 --- a/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart +++ b/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart @@ -1559,9 +1559,11 @@ final class wire_cst_prepare_receive_response extends ffi.Struct { } final class wire_cst_receive_payment_request extends ffi.Struct { + external wire_cst_prepare_receive_response prepare_response; + external ffi.Pointer description; - external wire_cst_prepare_receive_response prepare_response; + external ffi.Pointer use_description_hash; } final class wire_cst_refund_request extends ffi.Struct { @@ -2375,6 +2377,10 @@ final class wire_cst_PaymentError_Generic extends ffi.Struct { external ffi.Pointer err; } +final class wire_cst_PaymentError_InvalidDescription extends ffi.Struct { + external ffi.Pointer err; +} + final class wire_cst_PaymentError_InvalidInvoice extends ffi.Struct { external ffi.Pointer err; } @@ -2408,6 +2414,8 @@ final class PaymentErrorKind extends ffi.Union { external wire_cst_PaymentError_Generic Generic; + external wire_cst_PaymentError_InvalidDescription InvalidDescription; + external wire_cst_PaymentError_InvalidInvoice InvalidInvoice; external wire_cst_PaymentError_LwkError LwkError; diff --git a/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt b/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt index 115d368..85160cd 100644 --- a/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt +++ b/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt @@ -1602,13 +1602,24 @@ fun asReceivePaymentRequest(receivePaymentRequest: ReadableMap): ReceivePaymentR } val prepareResponse = receivePaymentRequest.getMap("prepareResponse")?.let { asPrepareReceiveResponse(it) }!! val description = if (hasNonNullKey(receivePaymentRequest, "description")) receivePaymentRequest.getString("description") else null - return ReceivePaymentRequest(prepareResponse, description) + val useDescriptionHash = + if (hasNonNullKey( + receivePaymentRequest, + "useDescriptionHash", + ) + ) { + receivePaymentRequest.getBoolean("useDescriptionHash") + } else { + null + } + return ReceivePaymentRequest(prepareResponse, description, useDescriptionHash) } fun readableMapOf(receivePaymentRequest: ReceivePaymentRequest): ReadableMap = readableMapOf( "prepareResponse" to readableMapOf(receivePaymentRequest.prepareResponse), "description" to receivePaymentRequest.description, + "useDescriptionHash" to receivePaymentRequest.useDescriptionHash, ) fun asReceivePaymentRequestList(arr: ReadableArray): List { diff --git a/packages/react-native/ios/BreezSDKLiquidMapper.swift b/packages/react-native/ios/BreezSDKLiquidMapper.swift index 48ca642..6b97f25 100644 --- a/packages/react-native/ios/BreezSDKLiquidMapper.swift +++ b/packages/react-native/ios/BreezSDKLiquidMapper.swift @@ -1868,14 +1868,22 @@ enum BreezSDKLiquidMapper { } description = descriptionTmp } + var useDescriptionHash: Bool? + if hasNonNilKey(data: receivePaymentRequest, key: "useDescriptionHash") { + guard let useDescriptionHashTmp = receivePaymentRequest["useDescriptionHash"] as? Bool else { + throw SdkError.Generic(message: errUnexpectedValue(fieldName: "useDescriptionHash")) + } + useDescriptionHash = useDescriptionHashTmp + } - return ReceivePaymentRequest(prepareResponse: prepareResponse, description: description) + return ReceivePaymentRequest(prepareResponse: prepareResponse, description: description, useDescriptionHash: useDescriptionHash) } static func dictionaryOf(receivePaymentRequest: ReceivePaymentRequest) -> [String: Any?] { return [ "prepareResponse": dictionaryOf(prepareReceiveResponse: receivePaymentRequest.prepareResponse), "description": receivePaymentRequest.description == nil ? nil : receivePaymentRequest.description, + "useDescriptionHash": receivePaymentRequest.useDescriptionHash == nil ? nil : receivePaymentRequest.useDescriptionHash, ] } diff --git a/packages/react-native/src/index.ts b/packages/react-native/src/index.ts index 52bb7cf..b4d2876 100644 --- a/packages/react-native/src/index.ts +++ b/packages/react-native/src/index.ts @@ -285,6 +285,7 @@ export interface Rate { export interface ReceivePaymentRequest { prepareResponse: PrepareReceiveResponse description?: string + useDescriptionHash?: boolean } export interface ReceivePaymentResponse {