bright_ln_models/
hodl_invoice.rs1use base64::prelude::*;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, thiserror::Error)]
5pub enum LndHodlInvoiceError {
6 #[error("Invalid HodlState")]
7 InvalidHodlState,
8 #[error("Invalid LndHodlInvoice")]
9 InvalidLndHodlInvoice,
10 #[error("InvoiceError: {0}")]
11 InvoiceError(lightning_invoice::ParseOrSemanticError),
12 #[error("Base64Error: {0}")]
13 Base64Error(#[from] base64::DecodeError),
14 #[error("SerdeJsonError: {0}")]
15 SerdeJsonError(#[from] serde_json::Error),
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
19pub struct LndHodlInvoice {
20 payment_addr: String,
21 payment_request: String,
22 add_index: String,
23}
24impl LndHodlInvoice {
25 #[must_use]
26 pub fn payment_hash(&self) -> Vec<u8> {
27 self.payment_addr.as_bytes().to_vec()
28 }
29 #[must_use]
30 pub fn payment_request(&self) -> String {
31 self.payment_request.clone()
32 }
33 #[must_use]
34 pub fn payment_hash_url_safe(&self) -> String {
35 let payment_hash = self.payment_hash();
36 BASE64_URL_SAFE.encode(payment_hash)
37 }
38 pub fn r_hash_url_safe(&self) -> Result<String, LndHodlInvoiceError> {
44 let r_hash = self
45 .payment_request
46 .parse::<lightning_invoice::Bolt11Invoice>()
47 .map_err(LndHodlInvoiceError::InvoiceError)?;
48 Ok(BASE64_URL_SAFE.encode(r_hash.payment_hash()))
49 }
50 pub fn sat_amount(&self) -> Result<u64, LndHodlInvoiceError> {
56 let bolt11 = self.payment_request.clone();
57 let bolt11 = bolt11
58 .parse::<lightning_invoice::Bolt11Invoice>()
59 .map_err(LndHodlInvoiceError::InvoiceError)?;
60 Ok(bolt11.amount_milli_satoshis().unwrap_or_default() / 1000)
61 }
62}
63impl std::str::FromStr for LndHodlInvoice {
64 type Err = LndHodlInvoiceError;
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 Ok(serde_json::from_str(s)?)
67 }
68}
69impl TryFrom<LndHodlInvoice> for String {
70 type Error = LndHodlInvoiceError;
71 fn try_from(value: LndHodlInvoice) -> Result<Self, Self::Error> {
72 Ok(serde_json::to_string(&value)?)
73 }
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
77#[serde(rename_all = "UPPERCASE")]
78pub enum HodlState {
79 Open,
80 Accepted,
81 Canceled,
82 Settled,
83}
84impl std::str::FromStr for HodlState {
85 type Err = LndHodlInvoiceError;
86 fn from_str(s: &str) -> Result<Self, Self::Err> {
87 Ok(serde_json::from_str(s)?)
88 }
89}
90impl AsRef<str> for HodlState {
91 fn as_ref(&self) -> &str {
92 match self {
93 Self::Open => "OPEN",
94 Self::Accepted => "ACCEPTED",
95 Self::Canceled => "CANCELED",
96 Self::Settled => "SETTLED",
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct LndHodlInvoiceState {
103 settled: bool,
104 state: HodlState,
105 r_hash: String,
106 payment_request: String,
107}
108impl std::str::FromStr for LndHodlInvoiceState {
109 type Err = LndHodlInvoiceError;
110 fn from_str(s: &str) -> Result<Self, Self::Err> {
111 Ok(serde_json::from_str::<Self>(s)?)
112 }
113}
114impl TryInto<String> for LndHodlInvoiceState {
115 type Error = LndHodlInvoiceError;
116 fn try_into(self) -> Result<String, Self::Error> {
117 Ok(serde_json::to_string(&self)?)
118 }
119}
120impl LndHodlInvoiceState {
121 #[must_use]
122 pub const fn settled(&self) -> bool {
123 self.settled
124 }
125 #[must_use]
126 pub fn state(&self) -> HodlState {
127 self.state.clone()
128 }
129 #[must_use]
130 pub fn r_hash(&self) -> String {
131 self.r_hash.clone()
132 }
133 #[must_use]
134 pub fn r_hash_url_safe(&self) -> String {
135 BASE64_URL_SAFE.encode(self.r_hash.as_bytes())
136 }
137 #[must_use]
138 pub fn payment_request(&self) -> String {
139 self.payment_request.clone()
140 }
141}