use bitcoin::{hashes::Hash, secp256k1::PublicKey};
use lightning_invoice::{Bolt11Invoice, RouteHint};
use thiserror::Error;
use crate::types::SwapNetwork;
#[derive(Debug, Error)]
pub enum InvoiceError {
#[error("invalid invoice: {0}")]
Invalid(String),
#[error("missing amount")]
MissingAmount,
#[error("expiry overflow")]
ExpiryOverflow,
#[error("no routes found for invoice payment")]
NoRoutesFound,
}
pub fn payment_hash(bolt11: &str) -> Result<[u8; 32], InvoiceError> {
let invoice = parse(bolt11)?;
Ok(invoice.payment_hash().to_byte_array())
}
pub fn amount_msat(bolt11: &str) -> Result<u64, InvoiceError> {
let invoice = parse(bolt11)?;
invoice
.amount_milli_satoshis()
.ok_or(InvoiceError::MissingAmount)
}
pub fn payment_secret(bolt11: &str) -> Result<[u8; 32], InvoiceError> {
let invoice = parse(bolt11)?;
Ok(invoice.payment_secret().0)
}
pub fn min_final_cltv_expiry_delta(bolt11: &str) -> Result<u64, InvoiceError> {
let invoice = parse(bolt11)?;
Ok(invoice.min_final_cltv_expiry_delta())
}
pub fn payee_pubkey(bolt11: &str) -> Result<PublicKey, InvoiceError> {
let invoice = parse(bolt11)?;
Ok(invoice.get_payee_pub_key())
}
pub fn route_hints(bolt11: &str) -> Result<Vec<RouteHint>, InvoiceError> {
let invoice = parse(bolt11)?;
Ok(invoice.route_hints())
}
pub fn expiry_at(bolt11: &str) -> Result<u64, InvoiceError> {
let invoice = parse(bolt11)?;
invoice
.expires_at()
.map(|d| d.as_secs())
.ok_or(InvoiceError::ExpiryOverflow)
}
pub fn network(bolt11: &str) -> Result<SwapNetwork, InvoiceError> {
let invoice = parse(bolt11)?;
Ok(invoice.network().into())
}
fn parse(bolt11: &str) -> Result<Bolt11Invoice, InvoiceError> {
bolt11
.parse::<Bolt11Invoice>()
.map_err(|e| InvoiceError::Invalid(e.to_string()))
}