lwk/
payment_instructions.rs1use std::{fmt::Display, str::FromStr, sync::Arc};
4
5use crate::{blockdata::address::BitcoinAddress, types::AssetId, Address, LwkError};
6
7#[derive(uniffi::Enum, Clone, Copy, Debug, PartialEq, Eq)]
9pub enum PaymentKind {
10 BitcoinAddress,
12 LiquidAddress,
14 LightningInvoice,
16 LightningOffer,
18 LnUrl,
20 Bip353,
22 Bip21,
24 Bip321,
26 LiquidBip21,
28}
29
30impl From<lwk_payment_instructions::PaymentKind> for PaymentKind {
31 fn from(kind: lwk_payment_instructions::PaymentKind) -> Self {
32 match kind {
33 lwk_payment_instructions::PaymentKind::BitcoinAddress => PaymentKind::BitcoinAddress,
34 lwk_payment_instructions::PaymentKind::LiquidAddress => PaymentKind::LiquidAddress,
35 lwk_payment_instructions::PaymentKind::LightningInvoice => {
36 PaymentKind::LightningInvoice
37 }
38 lwk_payment_instructions::PaymentKind::LightningOffer => PaymentKind::LightningOffer,
39 lwk_payment_instructions::PaymentKind::LnUrl => PaymentKind::LnUrl,
40 lwk_payment_instructions::PaymentKind::Bip353 => PaymentKind::Bip353,
41 lwk_payment_instructions::PaymentKind::Bip21 => PaymentKind::Bip21,
42 lwk_payment_instructions::PaymentKind::Bip321 => PaymentKind::Bip321,
43 lwk_payment_instructions::PaymentKind::LiquidBip21 => PaymentKind::LiquidBip21,
44 _ => unreachable!("Unknown PaymentCategoryKind variant"),
45 }
46 }
47}
48
49#[derive(uniffi::Record, Clone)]
51pub struct LiquidBip21 {
52 pub address: Arc<Address>,
54 pub asset: AssetId,
56 pub amount: u64,
58}
59
60#[derive(uniffi::Object)]
65pub struct Payment {
66 inner: lwk_payment_instructions::Payment,
67}
68
69impl Display for Payment {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 use lwk_payment_instructions::Payment as P;
72 match &self.inner {
73 P::BitcoinAddress(addr) => write!(f, "{}", addr.clone().assume_checked()),
74 P::LiquidAddress(addr) => write!(f, "{addr}"),
75 P::LightningInvoice(invoice) => write!(f, "{invoice}"),
76 P::LightningOffer(offer) => write!(f, "{offer}"),
77 P::LnUrlCat(lnurl) => write!(f, "{lnurl}"),
78 P::Bip353(s) => write!(f, "{s}"),
79 P::Bip21(s) => write!(f, "{s}"),
80 P::Bip321(s) => write!(f, "{s}"),
81 P::LiquidBip21(bip21) => write!(f, "{}", bip21.address),
82 _ => write!(f, "{:?}", self.inner),
83 }
84 }
85}
86
87#[uniffi::export]
88impl Payment {
89 #[uniffi::constructor]
91 pub fn new(s: &str) -> Result<Arc<Self>, LwkError> {
92 let inner = lwk_payment_instructions::Payment::from_str(s)
93 .map_err(|e| LwkError::Generic { msg: e })?;
94 Ok(Arc::new(Self { inner }))
95 }
96
97 pub fn kind(&self) -> PaymentKind {
99 self.inner.kind().into()
100 }
101
102 pub fn bitcoin_address(&self) -> Option<Arc<BitcoinAddress>> {
106 self.inner
107 .bitcoin_address()
108 .map(|addr| Arc::new(addr.clone().into()))
109 }
110
111 pub fn liquid_address(&self) -> Option<Arc<Address>> {
113 self.inner
114 .liquid_address()
115 .map(|addr| Arc::new(Address::from(addr.clone())))
116 }
117
118 #[cfg(feature = "lightning")]
120 pub fn lightning_invoice(&self) -> Option<Arc<crate::Bolt11Invoice>> {
121 self.inner
122 .lightning_invoice()
123 .and_then(|inv| crate::Bolt11Invoice::new(&inv.to_string()).ok())
124 }
125
126 pub fn lightning_offer(&self) -> Option<String> {
128 self.inner.lightning_offer().map(|offer| offer.to_string())
129 }
130
131 pub fn lnurl(&self) -> Option<String> {
133 self.inner.lnurl().map(|lnurl| lnurl.to_string())
134 }
135
136 pub fn bip353(&self) -> Option<String> {
138 self.inner.bip353().map(|s| s.to_string())
139 }
140
141 pub fn bip21(&self) -> Option<Arc<crate::bip21::Bip21>> {
143 self.inner
144 .bip21()
145 .map(|bip21| Arc::new(crate::bip21::Bip21::from(bip21.clone())))
146 }
147
148 pub fn bip321(&self) -> Option<Arc<crate::bip321::Bip321>> {
150 self.inner
151 .bip321()
152 .map(|bip321| Arc::new(crate::bip321::Bip321::from(bip321.clone())))
153 }
154
155 pub fn liquid_bip21(&self) -> Option<LiquidBip21> {
157 self.inner.liquid_bip21().map(|bip21| LiquidBip21 {
158 address: Arc::new(Address::from(bip21.address.clone())),
159 asset: bip21.asset.into(),
160 amount: bip21.amount,
161 })
162 }
163
164 #[cfg(feature = "lightning")]
169 pub fn lightning_payment(&self) -> Option<Arc<crate::LightningPayment>> {
170 use lwk_payment_instructions::Payment as P;
171 match &self.inner {
172 P::LightningInvoice(invoice) => crate::LightningPayment::new(&invoice.to_string()).ok(),
173 P::LightningOffer(offer) => crate::LightningPayment::new(&offer.to_string()).ok(),
174 P::LnUrlCat(lnurl) => crate::LightningPayment::new(&lnurl.to_string()).ok(),
175 _ => None,
176 }
177 }
178}