bright-ln-models 0.1.0

Models for the working with LND nodes
Documentation
use base64::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, thiserror::Error)]
pub enum LndHodlInvoiceError {
    #[error("Invalid HodlState")]
    InvalidHodlState,
    #[error("Invalid LndHodlInvoice")]
    InvalidLndHodlInvoice,
    #[error("InvoiceError: {0}")]
    InvoiceError(lightning_invoice::ParseOrSemanticError),
    #[error("Base64Error: {0}")]
    Base64Error(#[from] base64::DecodeError),
    #[error("SerdeJsonError: {0}")]
    SerdeJsonError(#[from] serde_json::Error),
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct LndHodlInvoice {
    payment_addr: String,
    payment_request: String,
    add_index: String,
}
impl LndHodlInvoice {
    #[must_use]
    pub fn payment_hash(&self) -> Vec<u8> {
        self.payment_addr.as_bytes().to_vec()
    }
    #[must_use]
    pub fn payment_request(&self) -> String {
        self.payment_request.clone()
    }
    #[must_use]
    pub fn payment_hash_url_safe(&self) -> String {
        let payment_hash = self.payment_hash();
        BASE64_URL_SAFE.encode(payment_hash)
    }
    /// Returns the payment request as a base64 url safe string
    ///
    /// # Errors
    ///
    /// Will return an error if the payment request is not a valid bolt11 invoice
    pub fn r_hash_url_safe(&self) -> Result<String, LndHodlInvoiceError> {
        let r_hash = self
            .payment_request
            .parse::<lightning_invoice::Bolt11Invoice>()
            .map_err(LndHodlInvoiceError::InvoiceError)?;
        Ok(BASE64_URL_SAFE.encode(r_hash.payment_hash()))
    }
    /// Returns the satoshi amount of the invoice
    ///
    /// # Errors
    ///
    /// Will return an error if the payment request is not a valid bolt11 invoice
    pub fn sat_amount(&self) -> Result<u64, LndHodlInvoiceError> {
        let bolt11 = self.payment_request.clone();
        let bolt11 = bolt11
            .parse::<lightning_invoice::Bolt11Invoice>()
            .map_err(LndHodlInvoiceError::InvoiceError)?;
        Ok(bolt11.amount_milli_satoshis().unwrap_or_default() / 1000)
    }
}
impl std::str::FromStr for LndHodlInvoice {
    type Err = LndHodlInvoiceError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(serde_json::from_str(s)?)
    }
}
impl TryFrom<LndHodlInvoice> for String {
    type Error = LndHodlInvoiceError;
    fn try_from(value: LndHodlInvoice) -> Result<Self, Self::Error> {
        Ok(serde_json::to_string(&value)?)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")]
pub enum HodlState {
    Open,
    Accepted,
    Canceled,
    Settled,
}
impl std::str::FromStr for HodlState {
    type Err = LndHodlInvoiceError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(serde_json::from_str(s)?)
    }
}
impl AsRef<str> for HodlState {
    fn as_ref(&self) -> &str {
        match self {
            Self::Open => "OPEN",
            Self::Accepted => "ACCEPTED",
            Self::Canceled => "CANCELED",
            Self::Settled => "SETTLED",
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LndHodlInvoiceState {
    settled: bool,
    state: HodlState,
    r_hash: String,
    payment_request: String,
}
impl std::str::FromStr for LndHodlInvoiceState {
    type Err = LndHodlInvoiceError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(serde_json::from_str::<Self>(s)?)
    }
}
impl TryInto<String> for LndHodlInvoiceState {
    type Error = LndHodlInvoiceError;
    fn try_into(self) -> Result<String, Self::Error> {
        Ok(serde_json::to_string(&self)?)
    }
}
impl LndHodlInvoiceState {
    #[must_use]
    pub const fn settled(&self) -> bool {
        self.settled
    }
    #[must_use]
    pub fn state(&self) -> HodlState {
        self.state.clone()
    }
    #[must_use]
    pub fn r_hash(&self) -> String {
        self.r_hash.clone()
    }
    #[must_use]
    pub fn r_hash_url_safe(&self) -> String {
        BASE64_URL_SAFE.encode(self.r_hash.as_bytes())
    }
    #[must_use]
    pub fn payment_request(&self) -> String {
        self.payment_request.clone()
    }
}