bright-ln-models 0.1.0

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

use super::OnchainAddressType;

#[derive(Debug, thiserror::Error)]
pub enum LndInvoiceError {
    #[error("Base64Error: {0}")]
    Base64Error(#[from] base64::DecodeError),
    #[error("String Error: {0}")]
    FormatError(#[from] std::fmt::Error),
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "UPPERCASE")]
pub enum LndInvoiceState {
    Open,
    Settled,
    Canceled,
    Accepted,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct LndPaymentInvoice {
    pub r_hash: String,
    pub payment_request: String,
    pub add_index: String,
    pub payment_addr: String,
}
impl std::str::FromStr for LndPaymentInvoice {
    type Err = serde_json::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}
impl TryFrom<LndPaymentInvoice> for String {
    type Error = serde_json::Error;
    fn try_from(value: LndPaymentInvoice) -> Result<Self, Self::Error> {
        serde_json::to_string(&value)
    }
}
impl LndPaymentInvoice {
    /// Returns the `r_hash` as a base64 url safe string, by decoding the `base_64` string and then encoding it again
    /// as base64 url safe
    ///
    /// # Errors
    ///
    /// Will return an error if the base64 string is not valid
    pub fn r_hash_url_safe(&self) -> Result<String, base64::DecodeError> {
        BASE64_STANDARD
            .decode(&self.r_hash)
            .map(|unsafe_str| BASE64_URL_SAFE.encode(unsafe_str))
    }
    /// Returns the `r_hash` as a hex string, by decoding the `base_64` string and then encoding it again
    /// as hex
    ///
    /// # Errors
    ///
    /// Will return an error if the base64 string is not valid
    pub fn r_hash_hex(&self) -> Result<String, LndInvoiceError> {
        use std::fmt::Write;
        BASE64_STANDARD.decode(&self.r_hash).map(|unsafe_str| {
            unsafe_str.iter().try_fold(String::new(), |mut acc, b| {
                write!(acc, "{b:02x}")?;
                Ok(acc)
            })
        })?
    }

    /// Returns the payment hash as a byte vector
    ///
    /// # Errors
    ///
    /// Will return an error if the base64 string is not valid
    pub fn payment_hash(&self) -> Result<Vec<u8>, LndInvoiceError> {
        Ok(BASE64_STANDARD.decode(&self.payment_addr)?)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct LndInvoice {
    pub r_preimage: String,
    pub r_hash: String,
    pub payment_request: String,
    pub add_index: String,
    pub payment_addr: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub memo: Option<String>,
    pub value: String,
    pub value_msat: String,
    pub settled: bool,
    pub creation_date: String,
    pub settle_date: String,
    pub state: LndInvoiceState,
}
impl std::str::FromStr for LndInvoice {
    type Err = serde_json::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}
impl TryFrom<LndInvoice> for String {
    type Error = serde_json::Error;
    fn try_from(value: LndInvoice) -> Result<Self, Self::Error> {
        serde_json::to_string(&value)
    }
}
impl LndInvoice {
    #[must_use]
    pub fn r_hash_url_safe(&self) -> String {
        let unsafe_str = BASE64_STANDARD.decode(&self.r_hash).unwrap_or_default();

        BASE64_URL_SAFE.encode(unsafe_str)
    }
    /// Returns the `r_hash` as a hex string, by decoding the `base_64` string and then encoding it again
    /// as hex
    ///
    /// # Errors
    ///
    /// Will return an error if the base64 string is not valid
    pub fn r_hash_hex(&self) -> Result<String, LndInvoiceError> {
        use std::fmt::Write;
        BASE64_STANDARD.decode(&self.r_hash).map(|unsafe_str| {
            unsafe_str.iter().try_fold(String::new(), |mut acc, b| {
                write!(acc, "{b:02x}")?;
                Ok(acc)
            })
        })?
    }
    #[must_use]
    pub fn payment_hash(&self) -> Vec<u8> {
        BASE64_STANDARD
            .decode(&self.payment_addr)
            .unwrap_or_default()
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct LndInvoiceList {
    pub invoices: Vec<LndInvoice>,
    pub last_index_offset: String,
    pub first_index_offset: String,
}
impl std::str::FromStr for LndInvoiceList {
    type Err = serde_json::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}
impl TryFrom<LndInvoiceList> for String {
    type Error = serde_json::Error;
    fn try_from(value: LndInvoiceList) -> Result<Self, Self::Error> {
        serde_json::to_string(&value)
    }
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct LndNewAddress {
    pub addr: String,
}
impl std::str::FromStr for LndNewAddress {
    type Err = serde_json::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}
impl TryFrom<LndNewAddress> for String {
    type Error = serde_json::Error;
    fn try_from(value: LndNewAddress) -> Result<Self, Self::Error> {
        serde_json::to_string(&value)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct LndNextAddressRequest {
    account: String,
    #[serde(rename = "type")]
    address_type: OnchainAddressType,
    change: bool,
}
impl std::str::FromStr for LndNextAddressRequest {
    type Err = serde_json::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}
impl TryFrom<LndNextAddressRequest> for String {
    type Error = serde_json::Error;
    fn try_from(value: LndNextAddressRequest) -> Result<Self, Self::Error> {
        serde_json::to_string(&value)
    }
}
impl Default for LndNextAddressRequest {
    fn default() -> Self {
        Self {
            account: String::new(),
            address_type: OnchainAddressType::TaprootPubkey,
            change: false,
        }
    }
}