cdk_common/
mint.rs

1//! Mint types
2
3use bitcoin::bip32::DerivationPath;
4use cashu::util::unix_time;
5use cashu::{MeltQuoteBolt11Response, MintQuoteBolt11Response};
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use crate::nuts::{MeltQuoteState, MintQuoteState};
10use crate::{Amount, CurrencyUnit, Id, KeySetInfo, PublicKey};
11
12/// Mint Quote Info
13#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
14pub struct MintQuote {
15    /// Quote id
16    pub id: Uuid,
17    /// Amount of quote
18    pub amount: Amount,
19    /// Unit of quote
20    pub unit: CurrencyUnit,
21    /// Quote payment request e.g. bolt11
22    pub request: String,
23    /// Quote state
24    pub state: MintQuoteState,
25    /// Expiration time of quote
26    pub expiry: u64,
27    /// Value used by ln backend to look up state of request
28    pub request_lookup_id: String,
29    /// Pubkey
30    pub pubkey: Option<PublicKey>,
31    /// Unix time quote was created
32    #[serde(default)]
33    pub created_time: u64,
34    /// Unix time quote was paid
35    pub paid_time: Option<u64>,
36    /// Unix time quote was issued
37    pub issued_time: Option<u64>,
38}
39
40impl MintQuote {
41    /// Create new [`MintQuote`]
42    pub fn new(
43        request: String,
44        unit: CurrencyUnit,
45        amount: Amount,
46        expiry: u64,
47        request_lookup_id: String,
48        pubkey: Option<PublicKey>,
49    ) -> Self {
50        let id = Uuid::new_v4();
51
52        Self {
53            id,
54            amount,
55            unit,
56            request,
57            state: MintQuoteState::Unpaid,
58            expiry,
59            request_lookup_id,
60            pubkey,
61            created_time: unix_time(),
62            paid_time: None,
63            issued_time: None,
64        }
65    }
66}
67
68/// Melt Quote Info
69#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
70pub struct MeltQuote {
71    /// Quote id
72    pub id: Uuid,
73    /// Quote unit
74    pub unit: CurrencyUnit,
75    /// Quote amount
76    pub amount: Amount,
77    /// Quote Payment request e.g. bolt11
78    pub request: String,
79    /// Quote fee reserve
80    pub fee_reserve: Amount,
81    /// Quote state
82    pub state: MeltQuoteState,
83    /// Expiration time of quote
84    pub expiry: u64,
85    /// Payment preimage
86    pub payment_preimage: Option<String>,
87    /// Value used by ln backend to look up state of request
88    pub request_lookup_id: String,
89    /// Msat to pay
90    ///
91    /// Used for an amountless invoice
92    pub msat_to_pay: Option<Amount>,
93    /// Unix time quote was created
94    #[serde(default)]
95    pub created_time: u64,
96    /// Unix time quote was paid
97    pub paid_time: Option<u64>,
98}
99
100impl MeltQuote {
101    /// Create new [`MeltQuote`]
102    pub fn new(
103        request: String,
104        unit: CurrencyUnit,
105        amount: Amount,
106        fee_reserve: Amount,
107        expiry: u64,
108        request_lookup_id: String,
109        msat_to_pay: Option<Amount>,
110    ) -> Self {
111        let id = Uuid::new_v4();
112
113        Self {
114            id,
115            amount,
116            unit,
117            request,
118            fee_reserve,
119            state: MeltQuoteState::Unpaid,
120            expiry,
121            payment_preimage: None,
122            request_lookup_id,
123            msat_to_pay,
124            created_time: unix_time(),
125            paid_time: None,
126        }
127    }
128}
129
130/// Mint Keyset Info
131#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
132pub struct MintKeySetInfo {
133    /// Keyset [`Id`]
134    pub id: Id,
135    /// Keyset [`CurrencyUnit`]
136    pub unit: CurrencyUnit,
137    /// Keyset active or inactive
138    /// Mint will only issue new signatures on active keysets
139    pub active: bool,
140    /// Starting unix time Keyset is valid from
141    pub valid_from: u64,
142    /// When the Keyset is valid to
143    /// This is not shown to the wallet and can only be used internally
144    pub valid_to: Option<u64>,
145    /// [`DerivationPath`] keyset
146    pub derivation_path: DerivationPath,
147    /// DerivationPath index of Keyset
148    pub derivation_path_index: Option<u32>,
149    /// Max order of keyset
150    pub max_order: u8,
151    /// Input Fee ppk
152    #[serde(default = "default_fee")]
153    pub input_fee_ppk: u64,
154}
155
156/// Default fee
157pub fn default_fee() -> u64 {
158    0
159}
160
161impl From<MintKeySetInfo> for KeySetInfo {
162    fn from(keyset_info: MintKeySetInfo) -> Self {
163        Self {
164            id: keyset_info.id,
165            unit: keyset_info.unit,
166            active: keyset_info.active,
167            input_fee_ppk: keyset_info.input_fee_ppk,
168        }
169    }
170}
171
172impl From<MintQuote> for MintQuoteBolt11Response<Uuid> {
173    fn from(mint_quote: crate::mint::MintQuote) -> MintQuoteBolt11Response<Uuid> {
174        MintQuoteBolt11Response {
175            quote: mint_quote.id,
176            request: mint_quote.request,
177            state: mint_quote.state,
178            expiry: Some(mint_quote.expiry),
179            pubkey: mint_quote.pubkey,
180            amount: Some(mint_quote.amount),
181            unit: Some(mint_quote.unit.clone()),
182        }
183    }
184}
185
186impl From<&MeltQuote> for MeltQuoteBolt11Response<Uuid> {
187    fn from(melt_quote: &MeltQuote) -> MeltQuoteBolt11Response<Uuid> {
188        MeltQuoteBolt11Response {
189            quote: melt_quote.id,
190            payment_preimage: None,
191            change: None,
192            state: melt_quote.state,
193            paid: Some(melt_quote.state == MeltQuoteState::Paid),
194            expiry: melt_quote.expiry,
195            amount: melt_quote.amount,
196            fee_reserve: melt_quote.fee_reserve,
197            request: None,
198            unit: Some(melt_quote.unit.clone()),
199        }
200    }
201}
202
203impl From<MeltQuote> for MeltQuoteBolt11Response<Uuid> {
204    fn from(melt_quote: MeltQuote) -> MeltQuoteBolt11Response<Uuid> {
205        let paid = melt_quote.state == MeltQuoteState::Paid;
206        MeltQuoteBolt11Response {
207            quote: melt_quote.id,
208            amount: melt_quote.amount,
209            fee_reserve: melt_quote.fee_reserve,
210            paid: Some(paid),
211            state: melt_quote.state,
212            expiry: melt_quote.expiry,
213            payment_preimage: melt_quote.payment_preimage,
214            change: None,
215            request: Some(melt_quote.request.clone()),
216            unit: Some(melt_quote.unit.clone()),
217        }
218    }
219}