breez_sdk_spark/
models.rs

1use breez_sdk_common::{
2    input::{self, BitcoinAddressDetails, Bolt11InvoiceDetails},
3    lnurl::pay::{LnurlPayRequestDetails, SuccessAction, SuccessActionProcessed},
4    network::BitcoinNetwork,
5};
6use core::fmt;
7use serde::{Deserialize, Serialize};
8use spark_wallet::{
9    CoopExitFeeQuote, CoopExitSpeedFeeQuote, ExitSpeed, LightningSendPayment, LightningSendStatus,
10    Network as SparkNetwork, SspUserRequest, TransferDirection, TransferStatus, TransferType,
11    WalletTransfer,
12};
13use std::time::UNIX_EPOCH;
14
15use crate::{SdkError, error::DepositClaimError};
16
17pub struct ConnectRequest {
18    pub config: Config,
19    pub mnemonic: String,
20    pub storage_dir: String,
21}
22
23/// The type of payment
24#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
25#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
26pub enum PaymentType {
27    /// Payment sent from this wallet
28    Send,
29    /// Payment received to this wallet
30    Receive,
31}
32
33impl fmt::Display for PaymentType {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        match self {
36            PaymentType::Send => write!(f, "send"),
37            PaymentType::Receive => write!(f, "receive"),
38        }
39    }
40}
41
42impl From<&str> for PaymentType {
43    fn from(s: &str) -> Self {
44        match s {
45            "receive" => PaymentType::Receive,
46            _ => PaymentType::Send, // Default to Send if unknown or 'send'
47        }
48    }
49}
50
51/// The status of a payment
52#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
53#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
54pub enum PaymentStatus {
55    /// Payment is completed successfully
56    Completed,
57    /// Payment is in progress
58    Pending,
59    /// Payment has failed
60    Failed,
61}
62
63impl fmt::Display for PaymentStatus {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        match self {
66            PaymentStatus::Completed => write!(f, "completed"),
67            PaymentStatus::Pending => write!(f, "pending"),
68            PaymentStatus::Failed => write!(f, "failed"),
69        }
70    }
71}
72
73impl From<&str> for PaymentStatus {
74    fn from(s: &str) -> Self {
75        match s {
76            "completed" => PaymentStatus::Completed,
77            "failed" => PaymentStatus::Failed,
78            _ => PaymentStatus::Pending, // Default to Pending if unknown or 'pending'
79        }
80    }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
84#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
85pub enum PaymentMethod {
86    Lightning,
87    Spark,
88    Deposit,
89    Withdraw,
90    Unknown,
91}
92
93impl From<TransferType> for PaymentMethod {
94    fn from(value: TransferType) -> Self {
95        match value {
96            TransferType::PreimageSwap => PaymentMethod::Lightning,
97            TransferType::CooperativeExit => PaymentMethod::Withdraw,
98            TransferType::Transfer => PaymentMethod::Spark,
99            TransferType::UtxoSwap => PaymentMethod::Deposit,
100            _ => PaymentMethod::Unknown,
101        }
102    }
103}
104/// Represents a payment (sent or received)
105#[derive(Debug, Clone, Serialize, Deserialize)]
106#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
107pub struct Payment {
108    /// Unique identifier for the payment
109    pub id: String,
110    /// Type of payment (send or receive)
111    pub payment_type: PaymentType,
112    /// Status of the payment
113    pub status: PaymentStatus,
114    /// Amount in satoshis
115    pub amount: u64,
116    /// Fee paid in satoshis
117    pub fees: u64,
118    /// Timestamp of when the payment was created
119    pub timestamp: u64,
120    /// Method of payment. Sometimes the payment details is empty so this field
121    /// is used to determine the payment method.
122    pub method: PaymentMethod,
123    /// Details of the payment
124    pub details: Option<PaymentDetails>,
125}
126
127// TODO: fix large enum variant lint - may be done by boxing lnurl_pay_info but that requires
128//  some changes to the wasm bindgen macro
129#[allow(clippy::large_enum_variant)]
130#[derive(Debug, Clone, Serialize, Deserialize)]
131#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
132pub enum PaymentDetails {
133    Spark,
134    Lightning {
135        /// Represents the invoice description
136        description: Option<String>,
137        /// The preimage of the paid invoice (proof of payment).
138        preimage: Option<String>,
139        /// Represents the Bolt11/Bolt12 invoice associated with a payment
140        /// In the case of a Send payment, this is the invoice paid by the user
141        /// In the case of a Receive payment, this is the invoice paid to the user
142        invoice: String,
143
144        /// The payment hash of the invoice
145        payment_hash: String,
146
147        /// The invoice destination/payee pubkey
148        destination_pubkey: String,
149
150        /// Lnurl payment information if this was an lnurl payment.
151        lnurl_pay_info: Option<LnurlPayInfo>,
152    },
153    Withdraw {
154        tx_id: String,
155    },
156    Deposit {
157        tx_id: String,
158    },
159}
160
161impl TryFrom<SspUserRequest> for PaymentDetails {
162    type Error = SdkError;
163    fn try_from(user_request: SspUserRequest) -> Result<Self, Self::Error> {
164        let details = match user_request {
165            SspUserRequest::CoopExitRequest(request) => PaymentDetails::Withdraw {
166                tx_id: request.coop_exit_txid,
167            },
168            SspUserRequest::LeavesSwapRequest(_) => PaymentDetails::Spark,
169            SspUserRequest::LightningReceiveRequest(request) => {
170                let invoice_details = input::parse_invoice(&request.invoice.encoded_invoice)
171                    .ok_or(SdkError::Generic(
172                        "Invalid invoice in SspUserRequest::LightningReceiveRequest".to_string(),
173                    ))?;
174                PaymentDetails::Lightning {
175                    description: invoice_details.description,
176                    preimage: request.lightning_receive_payment_preimage,
177                    invoice: request.invoice.encoded_invoice,
178                    payment_hash: request.invoice.payment_hash,
179                    destination_pubkey: invoice_details.payee_pubkey,
180                    lnurl_pay_info: None,
181                }
182            }
183            SspUserRequest::LightningSendRequest(request) => {
184                let invoice_details =
185                    input::parse_invoice(&request.encoded_invoice).ok_or(SdkError::Generic(
186                        "Invalid invoice in SspUserRequest::LightningSendRequest".to_string(),
187                    ))?;
188                PaymentDetails::Lightning {
189                    description: invoice_details.description,
190                    preimage: request.lightning_send_payment_preimage,
191                    invoice: request.encoded_invoice,
192                    payment_hash: invoice_details.payment_hash,
193                    destination_pubkey: invoice_details.payee_pubkey,
194                    lnurl_pay_info: None,
195                }
196            }
197            SspUserRequest::ClaimStaticDeposit(request) => PaymentDetails::Deposit {
198                tx_id: request.transaction_id,
199            },
200        };
201        Ok(details)
202    }
203}
204
205impl TryFrom<WalletTransfer> for Payment {
206    type Error = SdkError;
207    fn try_from(transfer: WalletTransfer) -> Result<Self, Self::Error> {
208        let payment_type = match transfer.direction {
209            TransferDirection::Incoming => PaymentType::Receive,
210            TransferDirection::Outgoing => PaymentType::Send,
211        };
212        let mut status = match transfer.status {
213            TransferStatus::Completed => PaymentStatus::Completed,
214            TransferStatus::SenderKeyTweaked
215                if transfer.direction == TransferDirection::Outgoing =>
216            {
217                PaymentStatus::Completed
218            }
219            TransferStatus::Expired | TransferStatus::Returned => PaymentStatus::Failed,
220            _ => PaymentStatus::Pending,
221        };
222        let (fees_sat, mut amount_sat): (u64, u64) = match transfer.clone().user_request {
223            Some(user_request) => match user_request {
224                SspUserRequest::LightningSendRequest(r) => {
225                    // TODO: if we have the preimage it is not pending. This is a workaround
226                    // until spark will implement incremental syncing based on updated time.
227                    if r.lightning_send_payment_preimage.is_some() {
228                        status = PaymentStatus::Completed;
229                    }
230                    let fee_sat = r.fee.as_sats().unwrap_or(0);
231                    (fee_sat, transfer.total_value_sat.saturating_sub(fee_sat))
232                }
233                SspUserRequest::CoopExitRequest(r) => {
234                    let fee_sat = r
235                        .fee
236                        .as_sats()
237                        .unwrap_or(0)
238                        .saturating_add(r.l1_broadcast_fee.as_sats().unwrap_or(0));
239                    (fee_sat, transfer.total_value_sat.saturating_sub(fee_sat))
240                }
241                SspUserRequest::ClaimStaticDeposit(r) => {
242                    let fee_sat = r.max_fee.as_sats().unwrap_or(0);
243                    (fee_sat, transfer.total_value_sat)
244                }
245                _ => (0, transfer.total_value_sat),
246            },
247            None => (0, transfer.total_value_sat),
248        };
249
250        let details: Option<PaymentDetails> = if let Some(user_request) = transfer.user_request {
251            Some(user_request.try_into()?)
252        } else {
253            // in case we have a completed status without user object we want
254            // to keep syncing this payment
255            if status == PaymentStatus::Completed
256                && [
257                    TransferType::CooperativeExit,
258                    TransferType::PreimageSwap,
259                    TransferType::UtxoSwap,
260                ]
261                .contains(&transfer.transfer_type)
262            {
263                status = PaymentStatus::Pending;
264            }
265            amount_sat = transfer.total_value_sat;
266            None
267        };
268
269        Ok(Payment {
270            id: transfer.id.to_string(),
271            payment_type,
272            status,
273            amount: amount_sat,
274            fees: fees_sat,
275            timestamp: match transfer.created_at.map(|t| t.duration_since(UNIX_EPOCH)) {
276                Some(Ok(duration)) => duration.as_secs(),
277                _ => 0,
278            },
279            method: transfer.transfer_type.into(),
280            details,
281        })
282    }
283}
284
285impl Payment {
286    pub fn from_lightning(
287        payment: LightningSendPayment,
288        amount_sat: u64,
289    ) -> Result<Self, SdkError> {
290        let status = match payment.status {
291            LightningSendStatus::LightningPaymentSucceeded => PaymentStatus::Completed,
292            LightningSendStatus::LightningPaymentFailed => PaymentStatus::Failed,
293            _ => PaymentStatus::Pending,
294        };
295
296        let invoice_details = input::parse_invoice(&payment.encoded_invoice).ok_or(
297            SdkError::Generic("Invalid invoice in LightnintSendPayment".to_string()),
298        )?;
299        let details = PaymentDetails::Lightning {
300            description: invoice_details.description,
301            preimage: payment.payment_preimage,
302            invoice: payment.encoded_invoice,
303            payment_hash: invoice_details.payment_hash,
304            destination_pubkey: invoice_details.payee_pubkey,
305            lnurl_pay_info: None,
306        };
307
308        Ok(Payment {
309            id: payment.id,
310            payment_type: PaymentType::Send,
311            status,
312            amount: amount_sat,
313            fees: payment.fee_sat,
314            timestamp: payment.created_at.cast_unsigned(),
315            method: PaymentMethod::Lightning,
316            details: Some(details),
317        })
318    }
319}
320
321#[derive(Debug, Clone, Copy)]
322#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
323pub enum Network {
324    Mainnet,
325    Regtest,
326}
327
328impl std::fmt::Display for Network {
329    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
330        match self {
331            Network::Mainnet => write!(f, "Mainnet"),
332            Network::Regtest => write!(f, "Regtest"),
333        }
334    }
335}
336
337impl From<Network> for SparkNetwork {
338    fn from(network: Network) -> Self {
339        match network {
340            Network::Mainnet => SparkNetwork::Mainnet,
341            Network::Regtest => SparkNetwork::Regtest,
342        }
343    }
344}
345
346impl From<Network> for BitcoinNetwork {
347    fn from(network: Network) -> Self {
348        match network {
349            Network::Mainnet => BitcoinNetwork::Bitcoin,
350            Network::Regtest => BitcoinNetwork::Regtest,
351        }
352    }
353}
354
355#[derive(Debug, Clone)]
356#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
357pub struct Config {
358    pub api_key: Option<String>,
359    pub network: Network,
360    pub sync_interval_secs: u32,
361
362    // The maximum fee that can be paid for a static deposit claim
363    // If not set then any fee is allowed
364    pub max_deposit_claim_fee: Option<Fee>,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
368#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
369pub enum Fee {
370    // Fixed fee amount in sats
371    Fixed { amount: u64 },
372    // Relative fee rate in satoshis per vbyte
373    Rate { sat_per_vbyte: u64 },
374}
375
376impl Fee {
377    pub fn to_sats(&self, vbytes: u64) -> u64 {
378        match self {
379            Fee::Fixed { amount } => *amount,
380            Fee::Rate { sat_per_vbyte } => sat_per_vbyte.saturating_mul(vbytes),
381        }
382    }
383}
384
385impl From<Fee> for spark_wallet::Fee {
386    fn from(fee: Fee) -> Self {
387        match fee {
388            Fee::Fixed { amount } => spark_wallet::Fee::Fixed { amount },
389            Fee::Rate { sat_per_vbyte } => spark_wallet::Fee::Rate { sat_per_vbyte },
390        }
391    }
392}
393
394#[derive(Debug, Clone, Serialize, Deserialize)]
395#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
396pub struct DepositInfo {
397    pub txid: String,
398    pub vout: u32,
399    pub amount_sats: u64,
400    pub refund_tx: Option<String>,
401    pub refund_tx_id: Option<String>,
402    pub claim_error: Option<DepositClaimError>,
403}
404
405#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
406pub struct ClaimDepositRequest {
407    pub txid: String,
408    pub vout: u32,
409    pub max_fee: Option<Fee>,
410}
411
412#[derive(Debug, Clone, Serialize)]
413#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
414pub struct ClaimDepositResponse {
415    pub payment: Payment,
416}
417
418#[derive(Debug, Clone, Serialize)]
419#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
420pub struct RefundDepositRequest {
421    pub txid: String,
422    pub vout: u32,
423    pub destination_address: String,
424    pub fee: Fee,
425}
426
427#[derive(Debug, Clone, Serialize)]
428#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
429pub struct RefundDepositResponse {
430    pub tx_id: String,
431    pub tx_hex: String,
432}
433
434#[derive(Debug, Clone, Serialize)]
435#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
436pub struct ListUnclaimedDepositsRequest {}
437
438#[derive(Debug, Clone, Serialize)]
439#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
440pub struct ListUnclaimedDepositsResponse {
441    pub deposits: Vec<DepositInfo>,
442}
443
444impl std::fmt::Display for Fee {
445    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
446        match self {
447            Fee::Fixed { amount } => write!(f, "Fixed: {amount}"),
448            Fee::Rate { sat_per_vbyte } => write!(f, "Rate: {sat_per_vbyte}"),
449        }
450    }
451}
452
453#[derive(Debug, Clone)]
454#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
455pub struct Credentials {
456    pub username: String,
457    pub password: String,
458}
459
460/// Request to get the balance of the wallet
461#[derive(Debug, Clone)]
462#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
463pub struct GetInfoRequest {}
464
465/// Response containing the balance of the wallet
466#[derive(Debug, Clone, Serialize)]
467#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
468pub struct GetInfoResponse {
469    /// The balance in satoshis
470    pub balance_sats: u64,
471}
472
473/// Request to sync the wallet with the Spark network
474#[derive(Debug, Clone)]
475#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
476pub struct SyncWalletRequest {}
477
478/// Response from synchronizing the wallet
479#[derive(Debug, Clone, Serialize)]
480#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
481pub struct SyncWalletResponse {}
482
483#[derive(Debug, Clone, Serialize)]
484#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
485pub enum ReceivePaymentMethod {
486    SparkAddress,
487    BitcoinAddress,
488    Bolt11Invoice {
489        description: String,
490        amount_sats: Option<u64>,
491    },
492}
493
494#[derive(Debug, Clone, Serialize)]
495#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
496pub enum SendPaymentMethod {
497    BitcoinAddress {
498        address: BitcoinAddressDetails,
499        fee_quote: SendOnchainFeeQuote,
500    },
501    Bolt11Invoice {
502        invoice_details: Bolt11InvoiceDetails,
503        spark_transfer_fee_sats: Option<u64>,
504        lightning_fee_sats: u64,
505    }, // should be replaced with the parsed invoice
506    SparkAddress {
507        address: String,
508        fee_sats: u64,
509    },
510}
511
512#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
513#[derive(Debug, Clone, Serialize)]
514pub struct SendOnchainFeeQuote {
515    pub id: String,
516    pub expires_at: u64,
517    pub speed_fast: SendOnchainSpeedFeeQuote,
518    pub speed_medium: SendOnchainSpeedFeeQuote,
519    pub speed_slow: SendOnchainSpeedFeeQuote,
520}
521
522impl From<CoopExitFeeQuote> for SendOnchainFeeQuote {
523    fn from(value: CoopExitFeeQuote) -> Self {
524        Self {
525            id: value.id,
526            expires_at: value.expires_at,
527            speed_fast: value.speed_fast.into(),
528            speed_medium: value.speed_medium.into(),
529            speed_slow: value.speed_slow.into(),
530        }
531    }
532}
533
534impl From<SendOnchainFeeQuote> for CoopExitFeeQuote {
535    fn from(value: SendOnchainFeeQuote) -> Self {
536        Self {
537            id: value.id,
538            expires_at: value.expires_at,
539            speed_fast: value.speed_fast.into(),
540            speed_medium: value.speed_medium.into(),
541            speed_slow: value.speed_slow.into(),
542        }
543    }
544}
545#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
546#[derive(Debug, Clone, Serialize)]
547pub struct SendOnchainSpeedFeeQuote {
548    pub user_fee_sat: u64,
549    pub l1_broadcast_fee_sat: u64,
550}
551
552impl SendOnchainSpeedFeeQuote {
553    pub fn total_fee_sat(&self) -> u64 {
554        self.user_fee_sat.saturating_add(self.l1_broadcast_fee_sat)
555    }
556}
557
558impl From<CoopExitSpeedFeeQuote> for SendOnchainSpeedFeeQuote {
559    fn from(value: CoopExitSpeedFeeQuote) -> Self {
560        Self {
561            user_fee_sat: value.user_fee_sat,
562            l1_broadcast_fee_sat: value.l1_broadcast_fee_sat,
563        }
564    }
565}
566
567impl From<SendOnchainSpeedFeeQuote> for CoopExitSpeedFeeQuote {
568    fn from(value: SendOnchainSpeedFeeQuote) -> Self {
569        Self {
570            user_fee_sat: value.user_fee_sat,
571            l1_broadcast_fee_sat: value.l1_broadcast_fee_sat,
572        }
573    }
574}
575
576#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
577pub struct ReceivePaymentRequest {
578    pub payment_method: ReceivePaymentMethod,
579}
580
581#[derive(Debug, Clone, Serialize)]
582#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
583pub struct ReceivePaymentResponse {
584    pub payment_request: String,
585    pub fee_sats: u64,
586}
587
588#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
589pub struct PrepareLnurlPayRequest {
590    pub amount_sats: u64,
591    pub comment: Option<String>,
592    pub pay_request: LnurlPayRequestDetails,
593    pub validate_success_action_url: Option<bool>,
594}
595
596#[derive(Debug)]
597#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
598pub struct PrepareLnurlPayResponse {
599    pub amount_sats: u64,
600    pub comment: Option<String>,
601    pub pay_request: LnurlPayRequestDetails,
602    pub fee_sats: u64,
603    pub invoice_details: Bolt11InvoiceDetails,
604    pub success_action: Option<SuccessAction>,
605}
606
607#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
608pub struct LnurlPayRequest {
609    pub prepare_response: PrepareLnurlPayResponse,
610}
611
612#[derive(Debug, Serialize)]
613#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
614pub struct LnurlPayResponse {
615    pub payment: Payment,
616    pub success_action: Option<SuccessActionProcessed>,
617}
618
619/// Represents the payment LNURL info
620#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
621#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
622pub struct LnurlPayInfo {
623    pub ln_address: Option<String>,
624    pub comment: Option<String>,
625    pub domain: Option<String>,
626    pub metadata: Option<String>,
627    pub processed_success_action: Option<SuccessActionProcessed>,
628    pub raw_success_action: Option<SuccessAction>,
629}
630
631#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
632#[derive(Debug, Clone, Serialize)]
633pub enum OnchainConfirmationSpeed {
634    Fast,
635    Medium,
636    Slow,
637}
638
639impl From<OnchainConfirmationSpeed> for ExitSpeed {
640    fn from(speed: OnchainConfirmationSpeed) -> Self {
641        match speed {
642            OnchainConfirmationSpeed::Fast => ExitSpeed::Fast,
643            OnchainConfirmationSpeed::Medium => ExitSpeed::Medium,
644            OnchainConfirmationSpeed::Slow => ExitSpeed::Slow,
645        }
646    }
647}
648
649impl From<ExitSpeed> for OnchainConfirmationSpeed {
650    fn from(speed: ExitSpeed) -> Self {
651        match speed {
652            ExitSpeed::Fast => OnchainConfirmationSpeed::Fast,
653            ExitSpeed::Medium => OnchainConfirmationSpeed::Medium,
654            ExitSpeed::Slow => OnchainConfirmationSpeed::Slow,
655        }
656    }
657}
658
659#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
660pub struct PrepareSendPaymentRequest {
661    pub payment_request: String,
662    pub amount_sats: Option<u64>,
663}
664
665#[derive(Debug, Clone, Serialize)]
666#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
667pub struct PrepareSendPaymentResponse {
668    pub payment_method: SendPaymentMethod,
669    pub amount_sats: u64,
670}
671
672#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
673pub enum SendPaymentOptions {
674    BitcoinAddress {
675        confirmation_speed: OnchainConfirmationSpeed,
676    },
677    Bolt11Invoice {
678        use_spark: bool,
679    },
680}
681
682#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
683pub struct SendPaymentRequest {
684    pub prepare_response: PrepareSendPaymentResponse,
685    pub options: Option<SendPaymentOptions>,
686}
687
688#[derive(Debug, Clone, Serialize)]
689#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
690pub struct SendPaymentResponse {
691    pub payment: Payment,
692}
693
694/// Request to list payments with pagination
695#[derive(Debug, Clone)]
696#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
697pub struct ListPaymentsRequest {
698    /// Number of records to skip
699    pub offset: Option<u32>,
700    /// Maximum number of records to return
701    pub limit: Option<u32>,
702}
703
704/// Response from listing payments
705#[derive(Debug, Clone, Serialize)]
706#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
707pub struct ListPaymentsResponse {
708    /// The list of payments
709    pub payments: Vec<Payment>,
710}
711
712#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
713pub struct GetPaymentRequest {
714    pub payment_id: String,
715}
716
717#[derive(Debug, Clone, Serialize)]
718#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
719pub struct GetPaymentResponse {
720    pub payment: Payment,
721}
722
723#[cfg_attr(feature = "uniffi", uniffi::export(callback_interface))]
724pub trait Logger: Send + Sync {
725    fn log(&self, l: LogEntry);
726}
727
728#[derive(Debug, Clone, Serialize)]
729#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
730pub struct LogEntry {
731    pub line: String,
732    pub level: String,
733}