nodeless_rs/
store.rs

1//! Store
2use std::collections::HashMap;
3
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use url::Url;
6
7use crate::error::NodelessError;
8use crate::serde_utils::{opt_serde_timestamp, opt_serde_url, serde_timestamp, serde_url};
9use crate::Nodeless;
10
11/// Store
12#[derive(Clone, Debug, Deserialize, Serialize)]
13#[serde(rename_all = "camelCase")]
14pub struct Store {
15    pub id: String,
16    pub name: String,
17    #[serde(with = "opt_serde_url")]
18    pub url: Option<Url>,
19    pub email: Option<String>,
20    #[serde(with = "serde_timestamp")]
21    pub created_at: i64,
22}
23
24/// Invoice Request
25#[derive(Clone, Debug, Deserialize, Serialize)]
26#[serde(rename_all = "camelCase")]
27pub struct InvoiceRequest {
28    pub amount: f64,
29    pub currency: String,
30    pub buyer_email: String,
31    #[serde(with = "serde_url")]
32    pub redirect_url: Url,
33    pub metadata: Option<HashMap<String, String>>,
34}
35
36/// Invoice
37#[derive(Clone, Debug, Deserialize, Serialize)]
38#[serde(rename_all = "camelCase")]
39pub struct Invoice {
40    pub id: Option<String>,
41    #[serde(with = "opt_serde_url")]
42    #[serde(rename = "checkoutLink")]
43    pub checkout_link: Option<Url>,
44    pub sats_amount: u64,
45    pub status: InvoiceStatus,
46    pub buyer_email: String,
47    #[serde(with = "serde_url")]
48    pub redirect_url: Url,
49    pub metadata: Option<HashMap<String, String>>,
50    #[serde(with = "serde_timestamp")]
51    pub created_at: i64,
52    #[serde(with = "opt_serde_timestamp")]
53    pub paid_at: Option<i64>,
54    pub onchain_address: String,
55    pub lightning_invoice: String,
56    pub store: Store,
57    pub qr_codes: QrCodes,
58}
59
60/// Invoice Status
61#[derive(Clone, Debug, PartialEq, Eq)]
62pub enum InvoiceStatus {
63    New,
64    Paid,
65    Expired,
66    Unknown(String),
67}
68
69impl<'de> Deserialize<'de> for InvoiceStatus {
70    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
71    where
72        D: Deserializer<'de>,
73    {
74        let status_str = String::deserialize(deserializer)?;
75        match status_str.as_str() {
76            "new" => Ok(InvoiceStatus::New),
77            "paid" => Ok(InvoiceStatus::Paid),
78            "expired" => Ok(InvoiceStatus::Expired),
79            _ => Ok(InvoiceStatus::Unknown(status_str)),
80        }
81    }
82}
83
84impl Serialize for InvoiceStatus {
85    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86    where
87        S: Serializer,
88    {
89        match self {
90            InvoiceStatus::New => serializer.serialize_str("new"),
91            InvoiceStatus::Paid => serializer.serialize_str("paid"),
92            InvoiceStatus::Expired => serializer.serialize_str("expired"),
93            InvoiceStatus::Unknown(status_str) => serializer.serialize_str(status_str),
94        }
95    }
96}
97
98// QR Code
99#[derive(Clone, Debug, Deserialize, Serialize)]
100#[serde(rename_all = "camelCase")]
101pub struct QrCodes {
102    pub unified: String,
103    pub onchain: String,
104    pub lightning: String,
105}
106
107impl Nodeless {
108    /// Get Stores
109    pub async fn get_stores(&self) -> Result<Vec<Store>, NodelessError> {
110        let url = self.base_url.join("api/v1/store")?;
111
112        let res = self.make_get(url).await?;
113        Ok(serde_json::from_value(res["data"].clone())?)
114    }
115
116    /// Get Store
117    pub async fn get_store(&self, id: &str) -> Result<Store, NodelessError> {
118        let url = self.base_url.join(&format!("api/v1/store/{}", id))?;
119
120        let res = self.make_get(url).await?;
121        Ok(serde_json::from_value(res["data"].clone())?)
122    }
123
124    /// Create Store Invoice
125    pub async fn create_store_invoice(
126        &self,
127        store_id: &str,
128        invoice: InvoiceRequest,
129    ) -> Result<Invoice, NodelessError> {
130        let url = self
131            .base_url
132            .join(&format!("api/v1/store/{}/invoice", store_id))?;
133
134        let res = self
135            .make_post(url, Some(serde_json::to_value(invoice)?))
136            .await?;
137        Ok(serde_json::from_value(res["data"].to_owned())?)
138    }
139
140    /// Get Invoice
141    pub async fn get_store_invoice(
142        &self,
143        store_id: &str,
144        invoice_id: &str,
145    ) -> Result<Invoice, NodelessError> {
146        let url = self
147            .base_url
148            .join(&format!("api/v1/store/{}/invoice/{}", store_id, invoice_id))?;
149
150        let res = self.make_get(url).await?;
151        Ok(serde_json::from_value(res["data"].to_owned())?)
152    }
153
154    /// Get Store Invoice Status
155    pub async fn get_store_invoice_status(
156        &self,
157        store_id: &str,
158        invoice_id: &str,
159    ) -> Result<InvoiceStatus, NodelessError> {
160        let url = self.base_url.join(&format!(
161            "api/v1/store/{}/invoice/{}/status",
162            store_id, invoice_id
163        ))?;
164        let res = self.make_get(url).await?;
165        Ok(serde_json::from_value(res["status"].to_owned())?)
166    }
167}