bright_lightning/lnd/models/
hodl_invoice.rs

1use base64::prelude::*;
2use lightning_invoice::Bolt11Invoice;
3use serde::{Deserialize, Serialize};
4use std::fmt::Display;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
7pub struct LndHodlInvoice {
8    payment_addr: String,
9    payment_request: String,
10    add_index: String,
11}
12impl LndHodlInvoice {
13    #[must_use] pub fn payment_hash(&self) -> Vec<u8> {
14        self.payment_addr.as_bytes().to_vec()
15    }
16    #[must_use] pub fn payment_request(&self) -> String {
17        self.payment_request.clone()
18    }
19    pub fn r_hash_url_safe(&self) -> anyhow::Result<String> {
20        let r_hash = self
21            .payment_request
22            .parse::<Bolt11Invoice>()
23            .map_err(|e| anyhow::anyhow!(e.to_string()))?;
24        let url_safe = BASE64_URL_SAFE.encode(r_hash.payment_hash());
25        Ok(url_safe)
26    }
27    #[must_use] pub fn sat_amount(&self) -> u64 {
28        let bolt11 = self.payment_request.clone();
29        let bolt11 = bolt11.parse::<Bolt11Invoice>().unwrap();
30        bolt11.amount_milli_satoshis().unwrap() / 1000
31    }
32}
33impl TryFrom<String> for LndHodlInvoice {
34    type Error = anyhow::Error;
35    fn try_from(value: String) -> Result<Self, Self::Error> {
36        Ok(serde_json::from_str(&value)?)
37    }
38}
39impl TryInto<String> for LndHodlInvoice {
40    type Error = anyhow::Error;
41    fn try_into(self) -> Result<String, Self::Error> {
42        Ok(serde_json::to_string(&self)?)
43    }
44}
45impl Display for LndHodlInvoice {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        write!(f, "{}", serde_json::to_string_pretty(self).unwrap())
48    }
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
52pub enum HodlState {
53    OPEN,
54    ACCEPTED,
55    CANCELED,
56    SETTLED,
57}
58impl TryFrom<String> for HodlState {
59    type Error = anyhow::Error;
60    fn try_from(value: String) -> Result<Self, Self::Error> {
61        match value.as_str() {
62            "OPEN" => Ok(Self::OPEN),
63            "ACCEPTED" => Ok(Self::ACCEPTED),
64            "CANCELED" => Ok(Self::CANCELED),
65            "SETTLED" => Ok(Self::SETTLED),
66            _ => Err(anyhow::anyhow!("Invalid HodlState")),
67        }
68    }
69}
70impl TryInto<String> for HodlState {
71    type Error = anyhow::Error;
72    fn try_into(self) -> Result<String, Self::Error> {
73        match self {
74            Self::OPEN => Ok("OPEN".to_string()),
75            Self::ACCEPTED => Ok("ACCEPTED".to_string()),
76            Self::CANCELED => Ok("CANCELED".to_string()),
77            Self::SETTLED => Ok("SETTLED".to_string()),
78        }
79    }
80}
81
82impl Display for HodlState {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        write!(f, "{}", serde_json::to_string_pretty(self).unwrap())
85    }
86}
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct LndHodlInvoiceState {
89    settled: bool,
90    state: HodlState,
91    r_hash: String,
92    payment_request: String,
93}
94impl TryFrom<String> for LndHodlInvoiceState {
95    type Error = anyhow::Error;
96    fn try_from(value: String) -> Result<Self, Self::Error> {
97        Ok(serde_json::from_str(&value)?)
98    }
99}
100impl TryInto<String> for LndHodlInvoiceState {
101    type Error = anyhow::Error;
102    fn try_into(self) -> Result<String, Self::Error> {
103        Ok(serde_json::to_string(&self)?)
104    }
105}
106impl Display for LndHodlInvoiceState {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        write!(f, "{}", serde_json::to_string_pretty(self).unwrap())
109    }
110}
111impl LndHodlInvoiceState {
112    #[must_use] pub const fn settled(&self) -> bool {
113        self.settled
114    }
115    #[must_use] pub fn state(&self) -> HodlState {
116        self.state.clone()
117    }
118    #[must_use] pub fn r_hash(&self) -> String {
119        self.r_hash.clone()
120    }
121    #[must_use] pub fn r_hash_url_safe(&self) -> String {
122        let url_safe = BASE64_URL_SAFE.encode(self.r_hash.as_bytes());
123        url_safe
124    }
125    #[must_use] pub fn payment_request(&self) -> String {
126        self.payment_request.clone()
127    }
128}