use std::{fmt::Display, str::FromStr, sync::Arc};
use crate::{blockdata::address::BitcoinAddress, types::AssetId, Address, LwkError};
#[derive(uniffi::Enum, Clone, Copy, Debug, PartialEq, Eq)]
pub enum PaymentKind {
BitcoinAddress,
LiquidAddress,
LightningInvoice,
LightningOffer,
LnUrl,
Bip353,
Bip21,
Bip321,
LiquidBip21,
}
impl From<lwk_payment_instructions::PaymentKind> for PaymentKind {
fn from(kind: lwk_payment_instructions::PaymentKind) -> Self {
match kind {
lwk_payment_instructions::PaymentKind::BitcoinAddress => PaymentKind::BitcoinAddress,
lwk_payment_instructions::PaymentKind::LiquidAddress => PaymentKind::LiquidAddress,
lwk_payment_instructions::PaymentKind::LightningInvoice => {
PaymentKind::LightningInvoice
}
lwk_payment_instructions::PaymentKind::LightningOffer => PaymentKind::LightningOffer,
lwk_payment_instructions::PaymentKind::LnUrl => PaymentKind::LnUrl,
lwk_payment_instructions::PaymentKind::Bip353 => PaymentKind::Bip353,
lwk_payment_instructions::PaymentKind::Bip21 => PaymentKind::Bip21,
lwk_payment_instructions::PaymentKind::Bip321 => PaymentKind::Bip321,
lwk_payment_instructions::PaymentKind::LiquidBip21 => PaymentKind::LiquidBip21,
_ => unreachable!("Unknown PaymentCategoryKind variant"),
}
}
}
#[derive(uniffi::Record, Clone)]
pub struct LiquidBip21 {
pub address: Arc<Address>,
pub asset: AssetId,
pub amount: u64,
}
#[derive(uniffi::Object)]
pub struct Payment {
inner: lwk_payment_instructions::Payment,
}
impl Display for Payment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use lwk_payment_instructions::Payment as P;
match &self.inner {
P::BitcoinAddress(addr) => write!(f, "{}", addr.clone().assume_checked()),
P::LiquidAddress(addr) => write!(f, "{addr}"),
P::LightningInvoice(invoice) => write!(f, "{invoice}"),
P::LightningOffer(offer) => write!(f, "{offer}"),
P::LnUrlCat(lnurl) => write!(f, "{lnurl}"),
P::Bip353(s) => write!(f, "{s}"),
P::Bip21(s) => write!(f, "{s}"),
P::Bip321(s) => write!(f, "{s}"),
P::LiquidBip21(bip21) => write!(f, "{}", bip21.address),
_ => write!(f, "{:?}", self.inner),
}
}
}
#[uniffi::export]
impl Payment {
#[uniffi::constructor]
pub fn new(s: &str) -> Result<Arc<Self>, LwkError> {
let inner = lwk_payment_instructions::Payment::from_str(s)
.map_err(|e| LwkError::Generic { msg: e })?;
Ok(Arc::new(Self { inner }))
}
pub fn kind(&self) -> PaymentKind {
self.inner.kind().into()
}
pub fn bitcoin_address(&self) -> Option<Arc<BitcoinAddress>> {
self.inner
.bitcoin_address()
.map(|addr| Arc::new(addr.clone().into()))
}
pub fn liquid_address(&self) -> Option<Arc<Address>> {
self.inner
.liquid_address()
.map(|addr| Arc::new(Address::from(addr.clone())))
}
#[cfg(feature = "lightning")]
pub fn lightning_invoice(&self) -> Option<Arc<crate::Bolt11Invoice>> {
self.inner
.lightning_invoice()
.and_then(|inv| crate::Bolt11Invoice::new(&inv.to_string()).ok())
}
pub fn lightning_offer(&self) -> Option<String> {
self.inner.lightning_offer().map(|offer| offer.to_string())
}
pub fn lnurl(&self) -> Option<String> {
self.inner.lnurl().map(|lnurl| lnurl.to_string())
}
pub fn bip353(&self) -> Option<String> {
self.inner.bip353().map(|s| s.to_string())
}
pub fn bip21(&self) -> Option<Arc<crate::bip21::Bip21>> {
self.inner
.bip21()
.map(|bip21| Arc::new(crate::bip21::Bip21::from(bip21.clone())))
}
pub fn bip321(&self) -> Option<Arc<crate::bip321::Bip321>> {
self.inner
.bip321()
.map(|bip321| Arc::new(crate::bip321::Bip321::from(bip321.clone())))
}
pub fn liquid_bip21(&self) -> Option<LiquidBip21> {
self.inner.liquid_bip21().map(|bip21| LiquidBip21 {
address: Arc::new(Address::from(bip21.address.clone())),
asset: bip21.asset.into(),
amount: bip21.amount,
})
}
#[cfg(feature = "lightning")]
pub fn lightning_payment(&self) -> Option<Arc<crate::LightningPayment>> {
use lwk_payment_instructions::Payment as P;
match &self.inner {
P::LightningInvoice(invoice) => crate::LightningPayment::new(&invoice.to_string()).ok(),
P::LightningOffer(offer) => crate::LightningPayment::new(&offer.to_string()).ok(),
P::LnUrlCat(lnurl) => crate::LightningPayment::new(&lnurl.to_string()).ok(),
_ => None,
}
}
}