Skip to main content

breez_sdk_spark/common/
models.rs

1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
5#[macros::derive_from(breez_sdk_common::network::BitcoinNetwork)]
6#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
7pub enum BitcoinNetwork {
8    /// Mainnet
9    Bitcoin,
10    Testnet3,
11    Testnet4,
12    Signet,
13    Regtest,
14}
15
16#[derive(Clone, Debug, Error)]
17#[macros::derive_from(breez_sdk_common::input::ParseError)]
18pub enum ParseError {
19    #[error("empty input")]
20    EmptyInput,
21    #[error(
22        "input is longer than {} bytes",
23        breez_sdk_common::input::MAX_INPUT_LENGTH
24    )]
25    InputTooLong,
26    #[error("Bip-21 error: {0}")]
27    Bip21Error(Bip21Error),
28    #[error("invalid input")]
29    InvalidInput,
30    #[error("Lnurl error: {0}")]
31    LnurlError(LnurlError),
32    #[error("Service connectivity error: {0}")]
33    ServiceConnectivity(ServiceConnectivityError),
34    #[error("Invalid external input parser: {0}")]
35    InvalidExternalInputParser(String),
36}
37
38#[derive(Clone, Debug, Error)]
39#[macros::derive_from(breez_sdk_common::input::Bip21Error)]
40pub enum Bip21Error {
41    #[error("bip21 contains invalid address")]
42    InvalidAddress,
43    #[error("bip21 contains invalid amount")]
44    InvalidAmount,
45    #[error("bip21 contains invalid parameter value for '{0}'")]
46    InvalidParameter(String),
47    #[error("bip21 contains parameter '{0}' multiple times")]
48    MultipleParams(String),
49    #[error("bip21 contains unknown required parameter '{0}'")]
50    UnknownRequiredParameter(String),
51    #[error("bip21 does not contain any payment methods")]
52    NoPaymentMethods,
53    #[error(
54        "bip21 contains more than {} payment methods",
55        breez_sdk_common::input::MAX_PAYMENT_METHODS
56    )]
57    TooManyPaymentMethods,
58}
59
60#[derive(Clone, Debug, Error)]
61#[macros::derive_from(breez_sdk_common::lnurl::error::LnurlError)]
62pub enum LnurlError {
63    #[error("lnurl missing k1 parameter")]
64    MissingK1,
65    #[error("lnurl contains invalid k1 parameter")]
66    InvalidK1,
67    #[error("lnurl contains unsupported action")]
68    UnsupportedAction,
69    #[error("lnurl missing domain")]
70    MissingDomain,
71    #[error("error calling lnurl endpoint: {0}")]
72    ServiceConnectivity(#[from] ServiceConnectivityError),
73    #[error("endpoint error: {0}")]
74    EndpointError(String),
75    #[error("lnurl has http scheme without onion domain")]
76    HttpSchemeWithoutOnionDomain,
77    #[error("lnurl has https scheme with onion domain")]
78    HttpsSchemeWithOnionDomain,
79    #[error("lnurl error: {0}")]
80    General(String),
81    #[error("lnurl has unknown scheme")]
82    UnknownScheme,
83    #[error("lnurl has invalid uri: {0}")]
84    InvalidUri(String),
85    #[error("lnurl has invalid invoice: {0}")]
86    InvalidInvoice(String),
87    #[error("lnurl has invalid response: {0}")]
88    InvalidResponse(String),
89}
90
91#[derive(Clone, Debug, Error)]
92#[macros::derive_from(breez_sdk_common::error::ServiceConnectivityError)]
93#[macros::derive_into(breez_sdk_common::error::ServiceConnectivityError)]
94#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
95pub enum ServiceConnectivityError {
96    #[error("Builder error: {0}")]
97    Builder(String),
98    #[error("Redirect error: {0}")]
99    Redirect(String),
100    #[error("Status error: {status} - {body}")]
101    Status { status: u16, body: String },
102    #[error("Timeout error: {0}")]
103    Timeout(String),
104    #[error("Request error: {0}")]
105    Request(String),
106    #[error("Connect error: {0}")]
107    Connect(String),
108    #[error("Body error: {0}")]
109    Body(String),
110    #[error("Decode error: {0}")]
111    Decode(String),
112    #[error("Json error: {0}")]
113    Json(String),
114    #[error("Other error: {0}")]
115    Other(String),
116}
117
118#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
119#[macros::derive_from(breez_sdk_common::input::Amount)]
120#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
121pub enum Amount {
122    Bitcoin {
123        amount_msat: u64,
124    },
125    /// An amount of currency specified using ISO 4712.
126    Currency {
127        /// The currency that the amount is denominated in.
128        iso4217_code: String,
129        /// The amount in the currency unit adjusted by the ISO 4712 exponent (e.g., USD cents).
130        fractional_amount: u64,
131    },
132}
133
134#[derive(Clone, Debug, Default, Deserialize, Serialize)]
135#[macros::derive_from(breez_sdk_common::input::Bip21Details)]
136#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
137pub struct Bip21Details {
138    pub amount_sat: Option<u64>,
139    pub asset_id: Option<String>,
140    pub uri: String,
141    pub extras: Vec<Bip21Extra>,
142    pub label: Option<String>,
143    pub message: Option<String>,
144    pub payment_methods: Vec<InputType>,
145}
146
147#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
148#[macros::derive_from(breez_sdk_common::input::Bip21Extra)]
149#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
150pub struct Bip21Extra {
151    pub key: String,
152    pub value: String,
153}
154
155#[derive(Clone, Debug, Deserialize, Serialize)]
156#[macros::derive_from(breez_sdk_common::input::BitcoinAddressDetails)]
157#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
158pub struct BitcoinAddressDetails {
159    pub address: String,
160    pub network: BitcoinNetwork,
161    pub source: PaymentRequestSource,
162}
163
164#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
165#[macros::derive_from(breez_sdk_common::input::Bolt11Invoice)]
166#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
167pub struct Bolt11Invoice {
168    pub bolt11: String,
169    pub source: PaymentRequestSource,
170}
171
172#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
173#[macros::derive_from(breez_sdk_common::input::Bolt11RouteHint)]
174#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
175pub struct Bolt11RouteHint {
176    pub hops: Vec<Bolt11RouteHintHop>,
177}
178
179#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
180#[macros::derive_from(breez_sdk_common::input::Bolt11RouteHintHop)]
181#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
182pub struct Bolt11RouteHintHop {
183    /// The `node_id` of the non-target end of the route
184    pub src_node_id: String,
185    /// The `short_channel_id` of this channel
186    pub short_channel_id: String,
187    /// The fees which must be paid to use this channel
188    pub fees_base_msat: u32,
189    pub fees_proportional_millionths: u32,
190
191    /// The difference in CLTV values between this node and the next node.
192    pub cltv_expiry_delta: u16,
193    /// The minimum value, in msat, which must be relayed to the next hop.
194    pub htlc_minimum_msat: Option<u64>,
195    /// The maximum value in msat available for routing with a single HTLC.
196    pub htlc_maximum_msat: Option<u64>,
197}
198
199#[derive(Clone, Debug, Deserialize, Serialize)]
200#[macros::derive_from(breez_sdk_common::input::Bolt12Invoice)]
201#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
202pub struct Bolt12Invoice {
203    pub invoice: String,
204    pub source: PaymentRequestSource,
205}
206
207#[derive(Clone, Debug, Deserialize, Serialize)]
208#[macros::derive_from(breez_sdk_common::input::Bolt12InvoiceRequestDetails)]
209#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
210pub struct Bolt12InvoiceRequestDetails {
211    // TODO: Fill fields
212}
213
214#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
215#[macros::derive_from(breez_sdk_common::input::Bolt12OfferBlindedPath)]
216#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
217pub struct Bolt12OfferBlindedPath {
218    pub blinded_hops: Vec<String>,
219}
220
221#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
222#[macros::derive_from(breez_sdk_common::input::Bolt11InvoiceDetails)]
223#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
224pub struct Bolt11InvoiceDetails {
225    pub amount_msat: Option<u64>,
226    pub description: Option<String>,
227    pub description_hash: Option<String>,
228    pub expiry: u64,
229    pub invoice: Bolt11Invoice,
230    pub min_final_cltv_expiry_delta: u64,
231    pub network: BitcoinNetwork,
232    pub payee_pubkey: String,
233    pub payment_hash: String,
234    pub payment_secret: String,
235    pub routing_hints: Vec<Bolt11RouteHint>,
236    pub timestamp: u64,
237}
238
239#[derive(Clone, Debug, Deserialize, Serialize)]
240#[macros::derive_from(breez_sdk_common::input::Bolt12InvoiceDetails)]
241#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
242pub struct Bolt12InvoiceDetails {
243    pub amount_msat: u64,
244    pub invoice: Bolt12Invoice,
245}
246
247#[derive(Clone, Debug, Deserialize, Serialize)]
248#[macros::derive_from(breez_sdk_common::input::Bolt12Offer)]
249#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
250pub struct Bolt12Offer {
251    pub offer: String,
252    pub source: PaymentRequestSource,
253}
254
255#[derive(Clone, Debug, Deserialize, Serialize)]
256#[macros::derive_from(breez_sdk_common::input::Bolt12OfferDetails)]
257#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
258pub struct Bolt12OfferDetails {
259    pub absolute_expiry: Option<u64>,
260    pub chains: Vec<String>,
261    pub description: Option<String>,
262    pub issuer: Option<String>,
263    pub min_amount: Option<Amount>,
264    pub offer: Bolt12Offer,
265    pub paths: Vec<Bolt12OfferBlindedPath>,
266    pub signing_pubkey: Option<String>,
267}
268
269#[derive(Clone, Debug, Deserialize, Serialize)]
270#[macros::derive_from(breez_sdk_common::input::InputType)]
271#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
272pub enum InputType {
273    BitcoinAddress(BitcoinAddressDetails),
274    Bolt11Invoice(Bolt11InvoiceDetails),
275    Bolt12Invoice(Bolt12InvoiceDetails),
276    Bolt12Offer(Bolt12OfferDetails),
277    LightningAddress(LightningAddressDetails),
278    LnurlPay(LnurlPayRequestDetails),
279    SilentPaymentAddress(BitcoinAddressDetails),
280    LnurlAuth(LnurlAuthRequestDetails),
281    Url(String),
282    Bip21(Bip21Details),
283    Bolt12InvoiceRequest(Bolt12InvoiceRequestDetails),
284    LnurlWithdraw(LnurlWithdrawRequestDetails),
285    SparkAddress(SparkAddressDetails),
286    SparkInvoice(SparkInvoiceDetails),
287    CrossChainAddress(CrossChainAddressDetails),
288}
289
290#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
291#[macros::derive_from(breez_sdk_common::input::CrossChainAddressFamily)]
292#[macros::derive_into(breez_sdk_common::input::CrossChainAddressFamily)]
293#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
294#[serde(rename_all = "snake_case")]
295pub enum CrossChainAddressFamily {
296    Evm,
297    Solana,
298    Tron,
299}
300
301#[derive(Clone, Debug, Deserialize, Serialize)]
302#[macros::derive_from(breez_sdk_common::input::CrossChainAddressDetails)]
303#[macros::derive_into(breez_sdk_common::input::CrossChainAddressDetails)]
304#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
305pub struct CrossChainAddressDetails {
306    pub address: String,
307    pub address_family: CrossChainAddressFamily,
308    pub contract_address: Option<String>,
309    pub chain_id: Option<u64>,
310    pub amount: Option<u128>,
311}
312
313#[derive(Clone, Debug, Deserialize, Serialize)]
314#[macros::derive_from(breez_sdk_common::lnurl::pay::LnurlPayRequestDetails)]
315#[macros::derive_into(breez_sdk_common::lnurl::pay::LnurlPayRequestDetails)]
316#[serde(rename_all = "camelCase")]
317#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
318pub struct LnurlPayRequestDetails {
319    pub callback: String,
320    /// The minimum amount, in millisats, that this LNURL-pay endpoint accepts
321    pub min_sendable: u64,
322    /// The maximum amount, in millisats, that this LNURL-pay endpoint accepts
323    pub max_sendable: u64,
324    /// As per LUD-06, `metadata` is a raw string (e.g. a json representation of the inner map).
325    /// Use `metadata_vec()` to get the parsed items.
326    #[serde(rename(deserialize = "metadata"))]
327    pub metadata_str: String,
328    /// The comment length accepted by this endpoint
329    ///
330    /// See <https://github.com/lnurl/luds/blob/luds/12.md>
331    #[serde(default)]
332    pub comment_allowed: u16,
333
334    /// Indicates the domain of the LNURL-pay service, to be shown to the user when asking for
335    /// payment input, as per LUD-06 spec.
336    ///
337    /// Note: this is not the domain of the callback, but the domain of the LNURL-pay endpoint.
338    #[serde(skip)]
339    pub domain: String,
340
341    #[serde(skip)]
342    pub url: String,
343
344    /// Optional lightning address if that was used to resolve the lnurl.
345    #[serde(skip)]
346    pub address: Option<String>,
347
348    /// Value indicating whether the recipient supports Nostr Zaps through NIP-57.
349    ///
350    /// See <https://github.com/nostr-protocol/nips/blob/master/57.md>
351    pub allows_nostr: Option<bool>,
352    /// Optional recipient's lnurl provider's Nostr pubkey for NIP-57. If it exists it should be a
353    /// valid BIP 340 public key in hex.
354    ///
355    /// See <https://github.com/nostr-protocol/nips/blob/master/57.md>
356    /// See <https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki>
357    pub nostr_pubkey: Option<String>,
358}
359
360/// Wrapped in a [`InputType::LnurlAuth`], this is the result of parsing a LNURL-auth endpoint.
361///
362/// It represents the endpoint's parameters for the LNURL workflow.
363///
364/// See <https://github.com/lnurl/luds/blob/luds/04.md>
365#[derive(Clone, Debug, Deserialize, Serialize)]
366#[macros::derive_from(breez_sdk_common::lnurl::auth::LnurlAuthRequestDetails)]
367#[macros::derive_into(breez_sdk_common::lnurl::auth::LnurlAuthRequestDetails)]
368#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
369pub struct LnurlAuthRequestDetails {
370    /// Hex encoded 32 bytes of challenge
371    pub k1: String,
372
373    /// When available, one of: register, login, link, auth
374    pub action: Option<String>,
375
376    /// Indicates the domain of the LNURL-auth service, to be shown to the user when asking for
377    /// auth confirmation, as per LUD-04 spec.
378    #[serde(skip_serializing, skip_deserializing)]
379    pub domain: String,
380
381    /// Indicates the URL of the LNURL-auth service, including the query arguments. This will be
382    /// extended with the signed challenge and the linking key, then called in the second step of the workflow.
383    #[serde(skip_serializing, skip_deserializing)]
384    pub url: String,
385}
386
387/// LNURL error details
388#[derive(Clone, Debug, Deserialize, Serialize)]
389#[macros::derive_from(breez_sdk_common::lnurl::LnurlErrorDetails)]
390#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
391pub struct LnurlErrorDetails {
392    pub reason: String,
393}
394
395/// The response from a LNURL-auth callback, indicating success or failure.
396#[derive(Clone, Debug, Deserialize, Serialize)]
397#[macros::derive_from(breez_sdk_common::lnurl::LnurlCallbackStatus)]
398#[serde(rename_all = "UPPERCASE")]
399#[serde(tag = "status")]
400#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
401pub enum LnurlCallbackStatus {
402    /// On-wire format is: `{"status": "OK"}`
403    Ok,
404    /// On-wire format is: `{"status": "ERROR", "reason": "error details..."}`
405    #[serde(rename = "ERROR")]
406    ErrorStatus {
407        #[serde(flatten)]
408        error_details: LnurlErrorDetails,
409    },
410}
411
412#[derive(Clone, Debug, Deserialize, Serialize)]
413#[macros::derive_from(breez_sdk_common::lnurl::withdraw::LnurlWithdrawRequestDetails)]
414#[macros::derive_into(breez_sdk_common::lnurl::withdraw::LnurlWithdrawRequestDetails)]
415#[serde(rename_all = "camelCase")]
416#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
417pub struct LnurlWithdrawRequestDetails {
418    pub callback: String,
419    pub k1: String,
420    pub default_description: String,
421    /// The minimum amount, in millisats, that this LNURL-withdraw endpoint accepts
422    pub min_withdrawable: u64,
423    /// The maximum amount, in millisats, that this LNURL-withdraw endpoint accepts
424    pub max_withdrawable: u64,
425    /// The URL of the LNURL-withdraw endpoint these details were fetched from.
426    /// Set when the details come from parsing an input; determines how far the
427    /// withdraw flow trusts the endpoint-chosen `callback`. Absent or empty
428    /// means no exemption: the callback is held to the public-host rules.
429    #[serde(default)]
430    #[cfg_attr(feature = "uniffi", uniffi(default = ""))]
431    pub url: String,
432}
433
434#[derive(Clone, Debug, Deserialize, Serialize)]
435#[macros::derive_from(breez_sdk_common::input::SparkAddressDetails)]
436#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
437pub struct SparkAddressDetails {
438    /// The raw address string
439    pub address: String,
440    /// The identity public key of the address owner
441    pub identity_public_key: String,
442    pub network: BitcoinNetwork,
443    pub source: PaymentRequestSource,
444}
445
446#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
447#[macros::derive_from(breez_sdk_common::input::SparkInvoiceDetails)]
448#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
449pub struct SparkInvoiceDetails {
450    /// The raw invoice string
451    pub invoice: String,
452    /// The identity public key of the invoice issuer
453    pub identity_public_key: String,
454    pub network: BitcoinNetwork,
455    /// Optional amount denominated in sats if `token_identifier` is absent, otherwise in the token base units
456    pub amount: Option<u128>,
457    /// The token identifier of the token payment. Absence indicates a Bitcoin payment.
458    pub token_identifier: Option<String>,
459    /// Optional expiry time as a unix timestamp in seconds. If not provided, the invoice will never expire.
460    pub expiry_time: Option<u64>,
461    /// Optional description.
462    pub description: Option<String>,
463    /// If set, the invoice may only be fulfilled by a payer with this public key.
464    pub sender_public_key: Option<String>,
465}
466
467#[derive(Clone, Debug, Deserialize, Serialize)]
468#[macros::derive_from(breez_sdk_common::input::LightningAddressDetails)]
469#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
470pub struct LightningAddressDetails {
471    pub address: String,
472    pub pay_request: LnurlPayRequestDetails,
473}
474
475#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
476#[macros::derive_from(breez_sdk_common::input::PaymentRequestSource)]
477#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
478pub struct PaymentRequestSource {
479    pub bip_21_uri: Option<String>,
480    pub bip_353_address: Option<String>,
481}
482
483/// Configuration for an external input parser
484#[derive(Debug, Clone, Serialize)]
485#[macros::derive_from(breez_sdk_common::input::ExternalInputParser)]
486#[macros::derive_into(breez_sdk_common::input::ExternalInputParser)]
487#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
488pub struct ExternalInputParser {
489    /// An arbitrary parser provider id
490    pub provider_id: String,
491    /// The external parser will be used when an input conforms to this regex
492    pub input_regex: String,
493    /// The URL of the parser containing a placeholder `<input>` that will be replaced with the
494    /// input to be parsed. The input is sanitized using percent encoding.
495    pub parser_url: String,
496}
497
498/// Supported success action types
499///
500/// Receiving any other (unsupported) success action type will result in a failed parsing,
501/// which will abort the LNURL-pay workflow, as per LUD-09.
502#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
503#[macros::derive_from(breez_sdk_common::lnurl::pay::SuccessAction)]
504#[macros::derive_into(breez_sdk_common::lnurl::pay::SuccessAction)]
505#[serde(rename_all = "camelCase")]
506#[serde(tag = "tag")]
507#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
508pub enum SuccessAction {
509    /// AES type, described in LUD-10
510    Aes {
511        #[serde(flatten)]
512        data: AesSuccessActionData,
513    },
514
515    /// Message type, described in LUD-09
516    Message {
517        #[serde(flatten)]
518        data: MessageSuccessActionData,
519    },
520
521    /// URL type, described in LUD-09
522    Url {
523        #[serde(flatten)]
524        data: UrlSuccessActionData,
525    },
526}
527
528/// [`SuccessAction`] where contents are ready to be consumed by the caller
529///
530/// Contents are identical to [`SuccessAction`], except for AES where the ciphertext is decrypted.
531#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
532#[macros::derive_from(breez_sdk_common::lnurl::pay::SuccessActionProcessed)]
533#[macros::derive_into(breez_sdk_common::lnurl::pay::SuccessActionProcessed)]
534#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
535pub enum SuccessActionProcessed {
536    /// See [`SuccessAction::Aes`] for received payload
537    ///
538    /// See [`AesSuccessActionDataDecrypted`] for decrypted payload
539    Aes { result: AesSuccessActionDataResult },
540
541    /// See [`SuccessAction::Message`]
542    Message { data: MessageSuccessActionData },
543
544    /// See [`SuccessAction::Url`]
545    Url { data: UrlSuccessActionData },
546}
547
548/// Payload of the AES success action, as received from the LNURL endpoint
549///
550/// See [`AesSuccessActionDataDecrypted`] for a similar wrapper containing the decrypted payload
551#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
552#[macros::derive_from(breez_sdk_common::lnurl::pay::AesSuccessActionData)]
553#[macros::derive_into(breez_sdk_common::lnurl::pay::AesSuccessActionData)]
554#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
555pub struct AesSuccessActionData {
556    /// Contents description, up to 144 characters
557    pub description: String,
558
559    /// Base64, AES-encrypted data where encryption key is payment preimage, up to 4kb of characters
560    pub ciphertext: String,
561
562    /// Base64, initialization vector, exactly 24 characters
563    pub iv: String,
564}
565
566/// Result of decryption of [`AesSuccessActionData`] payload
567#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
568#[macros::derive_from(breez_sdk_common::lnurl::pay::AesSuccessActionDataResult)]
569#[macros::derive_into(breez_sdk_common::lnurl::pay::AesSuccessActionDataResult)]
570#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
571pub enum AesSuccessActionDataResult {
572    Decrypted { data: AesSuccessActionDataDecrypted },
573    ErrorStatus { reason: String },
574}
575
576/// Wrapper for the decrypted [`AesSuccessActionData`] payload
577#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
578#[macros::derive_from(breez_sdk_common::lnurl::pay::AesSuccessActionDataDecrypted)]
579#[macros::derive_into(breez_sdk_common::lnurl::pay::AesSuccessActionDataDecrypted)]
580#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
581pub struct AesSuccessActionDataDecrypted {
582    /// Contents description, up to 144 characters
583    pub description: String,
584
585    /// Decrypted content
586    pub plaintext: String,
587}
588
589#[derive(PartialEq, Eq, Debug, Clone, Deserialize, Serialize)]
590#[macros::derive_from(breez_sdk_common::lnurl::pay::MessageSuccessActionData)]
591#[macros::derive_into(breez_sdk_common::lnurl::pay::MessageSuccessActionData)]
592#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
593pub struct MessageSuccessActionData {
594    pub message: String,
595}
596
597#[derive(PartialEq, Eq, Debug, Clone, Deserialize, Serialize)]
598#[macros::derive_from(breez_sdk_common::lnurl::pay::UrlSuccessActionData)]
599#[macros::derive_into(breez_sdk_common::lnurl::pay::UrlSuccessActionData)]
600#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
601pub struct UrlSuccessActionData {
602    /// Contents description, up to 144 characters
603    pub description: String,
604
605    /// URL of the success action
606    pub url: String,
607
608    /// Indicates the success URL domain matches the LNURL callback domain.
609    ///
610    /// See <https://github.com/lnurl/luds/blob/luds/09.md>
611    pub matches_callback_domain: bool,
612}
613
614#[cfg(test)]
615mod tests {
616    use super::LnurlWithdrawRequestDetails;
617
618    /// Withdraw details stored by older SDK versions carry no `url`; they must
619    /// keep deserializing, with the empty url falling back to strict callback
620    /// rules.
621    #[test]
622    fn withdraw_details_deserialize_without_url() {
623        let details: LnurlWithdrawRequestDetails = serde_json::from_str(
624            r#"{
625                "callback": "https://service.com/cb",
626                "k1": "abc",
627                "defaultDescription": "d",
628                "minWithdrawable": 1000,
629                "maxWithdrawable": 2000
630            }"#,
631        )
632        .unwrap();
633        assert_eq!(details.url, "");
634    }
635}