Skip to main content

cdk_ffi/types/
invoice.rs

1//! Invoice decoding FFI types and functions
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::FfiError;
6
7/// Type of Lightning payment request
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, uniffi::Enum)]
9pub enum PaymentType {
10    /// Bolt11 invoice
11    Bolt11,
12    /// Bolt12 offer
13    Bolt12,
14}
15
16impl From<cdk::invoice::PaymentType> for PaymentType {
17    fn from(payment_type: cdk::invoice::PaymentType) -> Self {
18        match payment_type {
19            cdk::invoice::PaymentType::Bolt11 => Self::Bolt11,
20            cdk::invoice::PaymentType::Bolt12 => Self::Bolt12,
21        }
22    }
23}
24
25impl From<PaymentType> for cdk::invoice::PaymentType {
26    fn from(payment_type: PaymentType) -> Self {
27        match payment_type {
28            PaymentType::Bolt11 => Self::Bolt11,
29            PaymentType::Bolt12 => Self::Bolt12,
30        }
31    }
32}
33
34/// Decoded invoice or offer information
35#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
36pub struct DecodedInvoice {
37    /// Type of payment request (Bolt11 or Bolt12)
38    pub payment_type: PaymentType,
39    /// Amount in millisatoshis, if specified
40    pub amount_msat: Option<u64>,
41    /// Expiry timestamp (Unix timestamp), if specified
42    pub expiry: Option<u64>,
43    /// Description or offer description, if specified
44    pub description: Option<String>,
45}
46
47impl From<cdk::invoice::DecodedInvoice> for DecodedInvoice {
48    fn from(decoded: cdk::invoice::DecodedInvoice) -> Self {
49        Self {
50            payment_type: decoded.payment_type.into(),
51            amount_msat: decoded.amount_msat,
52            expiry: decoded.expiry,
53            description: decoded.description,
54        }
55    }
56}
57
58impl From<DecodedInvoice> for cdk::invoice::DecodedInvoice {
59    fn from(decoded: DecodedInvoice) -> Self {
60        Self {
61            payment_type: decoded.payment_type.into(),
62            amount_msat: decoded.amount_msat,
63            expiry: decoded.expiry,
64            description: decoded.description,
65        }
66    }
67}
68
69/// Decode a bolt11 invoice or bolt12 offer from a string
70///
71/// This function attempts to parse the input as a bolt11 invoice first,
72/// then as a bolt12 offer if bolt11 parsing fails.
73///
74/// # Arguments
75///
76/// * `invoice_str` - The invoice or offer string to decode
77///
78/// # Returns
79///
80/// * `Ok(DecodedInvoice)` - Successfully decoded invoice/offer information
81/// * `Err(FfiError)` - Failed to parse as either bolt11 or bolt12
82///
83/// # Example
84///
85/// ```kotlin
86/// val decoded = decodeInvoice("lnbc...")
87/// when (decoded.paymentType) {
88///     PaymentType.BOLT11 -> println("Bolt11 invoice")
89///     PaymentType.BOLT12 -> println("Bolt12 offer")
90/// }
91/// ```
92#[uniffi::export]
93pub fn decode_invoice(invoice_str: String) -> Result<DecodedInvoice, FfiError> {
94    let decoded = cdk::invoice::decode_invoice(&invoice_str)?;
95    Ok(decoded.into())
96}