lwk/
invoice.rs

1use std::{fmt::Display, str::FromStr, sync::Arc};
2
3use crate::LwkError;
4
5/// Represents a syntactically and semantically correct lightning BOLT11 invoice.
6#[derive(uniffi::Object, PartialEq, Eq, Debug, Clone)]
7#[uniffi::export(Display)]
8pub struct Bolt11Invoice {
9    pub(crate) inner: lwk_boltz::Bolt11Invoice,
10}
11
12impl From<lwk_boltz::Bolt11Invoice> for Bolt11Invoice {
13    fn from(inner: lwk_boltz::Bolt11Invoice) -> Self {
14        Self { inner }
15    }
16}
17
18impl From<Bolt11Invoice> for lwk_boltz::Bolt11Invoice {
19    fn from(invoice: Bolt11Invoice) -> Self {
20        invoice.inner
21    }
22}
23
24impl From<&Bolt11Invoice> for lwk_boltz::Bolt11Invoice {
25    fn from(invoice: &Bolt11Invoice) -> Self {
26        invoice.inner.clone()
27    }
28}
29
30impl AsRef<lwk_boltz::Bolt11Invoice> for Bolt11Invoice {
31    fn as_ref(&self) -> &lwk_boltz::Bolt11Invoice {
32        &self.inner
33    }
34}
35
36impl Display for Bolt11Invoice {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{}", self.inner)
39    }
40}
41
42#[uniffi::export]
43impl Bolt11Invoice {
44    /// Construct a Bolt11Invoice from a string
45    #[uniffi::constructor]
46    pub fn new(s: &str) -> Result<Arc<Self>, LwkError> {
47        let inner = lwk_boltz::Bolt11Invoice::from_str(s).map_err(lwk_boltz::Error::from)?;
48        Ok(Arc::new(Self { inner }))
49    }
50
51    /// Returns the amount in millisatoshis if present, None if it's an "any amount" invoice
52    pub fn amount_milli_satoshis(&self) -> Option<u64> {
53        self.inner.amount_milli_satoshis()
54    }
55
56    /// Returns the payment hash as a hex string
57    pub fn payment_hash(&self) -> String {
58        format!("{}", self.inner.payment_hash())
59    }
60
61    /// Returns the invoice description as a string
62    pub fn invoice_description(&self) -> String {
63        format!("{}", self.inner.description())
64    }
65
66    /// Returns the payee's public key if present as a hex string
67    pub fn payee_pub_key(&self) -> Option<String> {
68        self.inner.payee_pub_key().map(|pk| pk.to_string())
69    }
70
71    /// Returns the invoice timestamp as seconds since Unix epoch
72    pub fn timestamp(&self) -> u64 {
73        self.inner.duration_since_epoch().as_secs()
74    }
75
76    /// Returns the expiry time in seconds (default is 3600 seconds / 1 hour if not specified)
77    pub fn expiry_time(&self) -> u64 {
78        self.inner.expiry_time().as_secs()
79    }
80
81    /// Returns the minimum CLTV expiry delta
82    pub fn min_final_cltv_expiry_delta(&self) -> u64 {
83        self.inner.min_final_cltv_expiry_delta()
84    }
85
86    /// Returns the network (bitcoin, testnet, signet, regtest)
87    pub fn network(&self) -> String {
88        format!("{:?}", self.inner.network())
89    }
90
91    /// Returns the payment secret as a debug string
92    pub fn payment_secret(&self) -> String {
93        format!("{:?}", self.inner.payment_secret())
94    }
95}
96
97/// Represents a lightning payment (bolt11 invoice or bolt12 offer)
98#[derive(uniffi::Object)]
99pub struct LightningPayment {
100    inner: lwk_boltz::LightningPayment,
101}
102
103impl AsRef<lwk_boltz::LightningPayment> for LightningPayment {
104    fn as_ref(&self) -> &lwk_boltz::LightningPayment {
105        &self.inner
106    }
107}
108
109impl From<lwk_boltz::LightningPayment> for LightningPayment {
110    fn from(inner: lwk_boltz::LightningPayment) -> Self {
111        Self { inner }
112    }
113}
114
115impl Display for LightningPayment {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        write!(f, "{}", self.inner)
118    }
119}
120
121#[uniffi::export]
122impl LightningPayment {
123    /// Construct a lightning payment (bolt11 invoice or bolt12 offer) from a string
124    #[uniffi::constructor]
125    pub fn new(s: &str) -> Result<Arc<Self>, LwkError> {
126        let inner =
127            lwk_boltz::LightningPayment::from_str(s).map_err(|(e1, e2, e3)| LwkError::Generic {
128                msg: format!("Failed to create lightning payment: {e1:?}, {e2:?}, {e3:?}"),
129            })?;
130        Ok(Arc::new(Self { inner }))
131    }
132
133    /// Construct a lightning payment (bolt11 invoice or bolt12 offer) from a bolt11 invoice
134    #[uniffi::constructor]
135    pub fn from_bolt11_invoice(invoice: Arc<Bolt11Invoice>) -> Arc<Self> {
136        Arc::new(Self {
137            inner: lwk_boltz::LightningPayment::Bolt11(Box::new(invoice.as_ref().clone().into())),
138        })
139    }
140
141    /// Returns the bolt11 invoice if the lightning payment is a bolt11 invoice
142    pub fn bolt11_invoice(&self) -> Option<Arc<Bolt11Invoice>> {
143        match &self.inner {
144            lwk_boltz::LightningPayment::Bolt11(invoice) => {
145                Some(Arc::new(Bolt11Invoice::from((**invoice).clone())))
146            }
147            lwk_boltz::LightningPayment::Bolt12(_) => None,
148            lwk_boltz::LightningPayment::LnUrl(_) => None,
149        }
150    }
151}