1use std::collections::HashMap;
4use std::ops::{Deref, DerefMut};
5
6use async_trait::async_trait;
7use cashu::quote_id::QuoteId;
8use cashu::Amount;
9
10use super::{DbTransactionFinalizer, Error};
11use crate::mint::{
12 self, MeltQuote, MintKeySetInfo, MintQuote as MintMintQuote, Operation, ProofsWithState,
13};
14use crate::nuts::{
15 BlindSignature, BlindedMessage, CurrencyUnit, Id, MeltQuoteState, Proof, Proofs, PublicKey,
16 State,
17};
18use crate::payment::PaymentIdentifier;
19
20mod auth;
21
22#[cfg(feature = "test")]
23pub mod test;
24
25pub use auth::{DynMintAuthDatabase, MintAuthDatabase, MintAuthTransaction};
26
27pub use super::kvstore::{
29 validate_kvstore_params, validate_kvstore_string, KVStore, KVStoreDatabase, KVStoreTransaction,
30 KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN,
31};
32
33#[derive(Debug)]
62pub struct Acquired<T> {
63 inner: T,
64}
65
66impl<T> From<T> for Acquired<T> {
67 fn from(value: T) -> Self {
72 Acquired { inner: value }
73 }
74}
75
76impl<T> Acquired<T> {
77 pub fn inner(self) -> T {
83 self.inner
84 }
85}
86
87impl<T> Deref for Acquired<T> {
88 type Target = T;
89
90 fn deref(&self) -> &Self::Target {
92 &self.inner
93 }
94}
95
96impl<T> DerefMut for Acquired<T> {
97 fn deref_mut(&mut self) -> &mut Self::Target {
99 &mut self.inner
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq)]
105pub struct MeltRequestInfo {
106 pub inputs_amount: Amount<CurrencyUnit>,
108 pub inputs_fee: Amount<CurrencyUnit>,
110 pub change_outputs: Vec<BlindedMessage>,
112}
113
114#[derive(Debug)]
119pub struct LockedMeltQuotes {
120 pub target: Option<Acquired<MeltQuote>>,
122 pub all_related: Vec<Acquired<MeltQuote>>,
124}
125
126#[async_trait]
128pub trait KeysDatabaseTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
129 async fn set_active_keyset(&mut self, unit: CurrencyUnit, id: Id) -> Result<(), Error>;
131
132 async fn add_keyset_info(&mut self, keyset: MintKeySetInfo) -> Result<(), Error>;
134}
135
136#[async_trait]
138pub trait KeysDatabase {
139 type Err: Into<Error> + From<Error>;
141
142 async fn begin_transaction<'a>(
144 &'a self,
145 ) -> Result<Box<dyn KeysDatabaseTransaction<'a, Self::Err> + Send + Sync + 'a>, Error>;
146
147 async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err>;
149
150 async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err>;
152
153 async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err>;
155
156 async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
158}
159
160#[async_trait]
162pub trait QuotesTransaction {
163 type Err: Into<Error> + From<Error>;
165
166 async fn add_melt_request(
168 &mut self,
169 quote_id: &QuoteId,
170 inputs_amount: Amount<CurrencyUnit>,
171 inputs_fee: Amount<CurrencyUnit>,
172 ) -> Result<(), Self::Err>;
173
174 async fn add_blinded_messages(
176 &mut self,
177 quote_id: Option<&QuoteId>,
178 blinded_messages: &[BlindedMessage],
179 operation: &Operation,
180 ) -> Result<(), Self::Err>;
181
182 async fn delete_blinded_messages(
184 &mut self,
185 blinded_secrets: &[PublicKey],
186 ) -> Result<(), Self::Err>;
187
188 async fn get_melt_request_and_blinded_messages(
190 &mut self,
191 quote_id: &QuoteId,
192 ) -> Result<Option<MeltRequestInfo>, Self::Err>;
193
194 async fn delete_melt_request(&mut self, quote_id: &QuoteId) -> Result<(), Self::Err>;
196
197 async fn get_mint_quote(
199 &mut self,
200 quote_id: &QuoteId,
201 ) -> Result<Option<Acquired<MintMintQuote>>, Self::Err>;
202
203 async fn get_mint_quotes_by_ids(
208 &mut self,
209 quote_ids: &[QuoteId],
210 ) -> Result<Vec<Option<Acquired<MintMintQuote>>>, Self::Err>;
211
212 async fn add_mint_quote(
214 &mut self,
215 quote: MintMintQuote,
216 ) -> Result<Acquired<MintMintQuote>, Self::Err>;
217
218 async fn update_mint_quote(
238 &mut self,
239 quote: &mut Acquired<mint::MintQuote>,
240 ) -> Result<(), Self::Err>;
241
242 async fn get_melt_quote(
244 &mut self,
245 quote_id: &QuoteId,
246 ) -> Result<Option<Acquired<mint::MeltQuote>>, Self::Err>;
247
248 async fn add_melt_quote(&mut self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
250
251 async fn get_melt_quotes_by_request_lookup_id(
267 &mut self,
268 request_lookup_id: &PaymentIdentifier,
269 ) -> Result<Vec<Acquired<MeltQuote>>, Self::Err>;
270
271 async fn lock_melt_quote_and_related(
297 &mut self,
298 quote_id: &QuoteId,
299 ) -> Result<LockedMeltQuotes, Self::Err>;
300
301 async fn update_melt_quote_request_lookup_id(
305 &mut self,
306 quote: &mut Acquired<mint::MeltQuote>,
307 new_request_lookup_id: &PaymentIdentifier,
308 ) -> Result<(), Self::Err>;
309
310 async fn update_melt_quote_state(
315 &mut self,
316 quote: &mut Acquired<mint::MeltQuote>,
317 new_state: MeltQuoteState,
318 payment_proof: Option<String>,
319 ) -> Result<MeltQuoteState, Self::Err>;
320
321 async fn get_mint_quote_by_request(
323 &mut self,
324 request: &str,
325 ) -> Result<Option<Acquired<MintMintQuote>>, Self::Err>;
326
327 async fn get_mint_quote_by_request_lookup_id(
329 &mut self,
330 request_lookup_id: &PaymentIdentifier,
331 ) -> Result<Option<Acquired<MintMintQuote>>, Self::Err>;
332}
333
334#[async_trait]
336pub trait QuotesDatabase {
337 type Err: Into<Error> + From<Error>;
339
340 async fn get_mint_quote(&self, quote_id: &QuoteId) -> Result<Option<MintMintQuote>, Self::Err>;
342
343 async fn try_update_mint_quote_last_checked(
348 &self,
349 quote_id: &QuoteId,
350 last_checked: u64,
351 min_interval: u64,
352 ) -> Result<bool, Self::Err>;
353
354 async fn get_mint_quotes_by_ids(
358 &self,
359 quote_ids: &[QuoteId],
360 ) -> Result<Vec<Option<MintMintQuote>>, Self::Err>;
361
362 async fn get_mint_quote_by_request(
364 &self,
365 request: &str,
366 ) -> Result<Option<MintMintQuote>, Self::Err>;
367 async fn get_mint_quote_by_request_lookup_id(
369 &self,
370 request_lookup_id: &PaymentIdentifier,
371 ) -> Result<Option<MintMintQuote>, Self::Err>;
372 async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
374 async fn get_melt_quote(
376 &self,
377 quote_id: &QuoteId,
378 ) -> Result<Option<mint::MeltQuote>, Self::Err>;
379 async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
381}
382
383#[async_trait]
385pub trait ProofsTransaction {
386 type Err: Into<Error> + From<Error>;
388
389 async fn add_proofs(
394 &mut self,
395 proof: Proofs,
396 quote_id: Option<QuoteId>,
397 operation: &Operation,
398 ) -> Result<Acquired<ProofsWithState>, Self::Err>;
399
400 async fn update_proofs_state(
405 &mut self,
406 proofs: &mut Acquired<ProofsWithState>,
407 new_state: State,
408 ) -> Result<(), Self::Err>;
409
410 async fn get_proofs(
412 &mut self,
413 ys: &[PublicKey],
414 ) -> Result<Acquired<ProofsWithState>, Self::Err>;
415
416 async fn remove_proofs(
418 &mut self,
419 ys: &[PublicKey],
420 quote_id: Option<QuoteId>,
421 ) -> Result<(), Self::Err>;
422
423 async fn get_proof_ys_by_quote_id(
425 &mut self,
426 quote_id: &QuoteId,
427 ) -> Result<Vec<PublicKey>, Self::Err>;
428
429 async fn get_proof_ys_by_operation_id(
431 &mut self,
432 operation_id: &uuid::Uuid,
433 ) -> Result<Vec<PublicKey>, Self::Err>;
434}
435
436#[async_trait]
438pub trait ProofsDatabase {
439 type Err: Into<Error> + From<Error>;
441
442 async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
444 async fn get_proof_ys_by_quote_id(
446 &self,
447 quote_id: &QuoteId,
448 ) -> Result<Vec<PublicKey>, Self::Err>;
449 async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
451
452 async fn get_proofs_by_keyset_id(
454 &self,
455 keyset_id: &Id,
456 ) -> Result<(Proofs, Vec<Option<State>>), Self::Err>;
457
458 async fn get_total_redeemed(&self) -> Result<HashMap<Id, Amount>, Self::Err>;
460
461 async fn get_proof_ys_by_operation_id(
463 &self,
464 operation_id: &uuid::Uuid,
465 ) -> Result<Vec<PublicKey>, Self::Err>;
466}
467
468#[async_trait]
469pub trait SignaturesTransaction {
471 type Err: Into<Error> + From<Error>;
473
474 async fn add_blind_signatures(
476 &mut self,
477 blinded_messages: &[PublicKey],
478 blind_signatures: &[BlindSignature],
479 quote_id: Option<QuoteId>,
480 ) -> Result<(), Self::Err>;
481
482 async fn get_blind_signatures(
484 &mut self,
485 blinded_messages: &[PublicKey],
486 ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
487}
488
489#[async_trait]
490pub trait SignaturesDatabase {
492 type Err: Into<Error> + From<Error>;
494
495 async fn get_blind_signatures(
497 &self,
498 blinded_messages: &[PublicKey],
499 ) -> Result<Vec<Option<BlindSignature>>, Self::Err>;
500
501 async fn get_blind_signatures_for_keyset(
503 &self,
504 keyset_id: &Id,
505 ) -> Result<Vec<BlindSignature>, Self::Err>;
506
507 async fn get_blind_signatures_for_quote(
509 &self,
510 quote_id: &QuoteId,
511 ) -> Result<Vec<BlindSignature>, Self::Err>;
512
513 async fn get_total_issued(&self) -> Result<HashMap<Id, Amount>, Self::Err>;
515
516 async fn get_blinded_secrets_by_operation_id(
518 &self,
519 operation_id: &uuid::Uuid,
520 ) -> Result<Vec<PublicKey>, Self::Err>;
521}
522
523#[async_trait]
524pub trait SagaTransaction {
526 type Err: Into<Error> + From<Error>;
528
529 async fn get_saga(
531 &mut self,
532 operation_id: &uuid::Uuid,
533 ) -> Result<Option<mint::Saga>, Self::Err>;
534
535 async fn add_saga(&mut self, saga: &mint::Saga) -> Result<(), Self::Err>;
537
538 async fn update_saga(
540 &mut self,
541 operation_id: &uuid::Uuid,
542 new_state: mint::SagaStateEnum,
543 ) -> Result<(), Self::Err>;
544
545 async fn update_saga_with_finalization_data(
547 &mut self,
548 operation_id: &uuid::Uuid,
549 new_state: mint::SagaStateEnum,
550 finalization_data: Option<&mint::MeltFinalizationData>,
551 ) -> Result<(), Self::Err>;
552
553 async fn delete_saga(&mut self, operation_id: &uuid::Uuid) -> Result<(), Self::Err>;
555}
556
557#[async_trait]
558pub trait SagaDatabase {
560 type Err: Into<Error> + From<Error>;
562
563 async fn get_melt_saga_by_quote_id(
565 &self,
566 quote_id: &QuoteId,
567 ) -> Result<Option<mint::Saga>, Self::Err>;
568
569 async fn get_incomplete_sagas(
571 &self,
572 operation_kind: mint::OperationKind,
573 ) -> Result<Vec<mint::Saga>, Self::Err>;
574}
575
576#[async_trait]
577pub trait CompletedOperationsTransaction {
579 type Err: Into<Error> + From<Error>;
581
582 async fn add_completed_operation(
584 &mut self,
585 operation: &mint::Operation,
586 fee_by_keyset: &std::collections::HashMap<crate::nuts::Id, crate::Amount>,
587 ) -> Result<(), Self::Err>;
588}
589
590#[async_trait]
591pub trait CompletedOperationsDatabase {
593 type Err: Into<Error> + From<Error>;
595
596 async fn get_completed_operation(
598 &self,
599 operation_id: &uuid::Uuid,
600 ) -> Result<Option<mint::Operation>, Self::Err>;
601
602 async fn get_completed_operations_by_kind(
604 &self,
605 operation_kind: mint::OperationKind,
606 ) -> Result<Vec<mint::Operation>, Self::Err>;
607
608 async fn get_completed_operations(&self) -> Result<Vec<mint::Operation>, Self::Err>;
610}
611
612pub trait Transaction<Error>:
614 DbTransactionFinalizer<Err = Error>
615 + QuotesTransaction<Err = Error>
616 + SignaturesTransaction<Err = Error>
617 + ProofsTransaction<Err = Error>
618 + KVStoreTransaction<Error>
619 + SagaTransaction<Err = Error>
620 + CompletedOperationsTransaction<Err = Error>
621{
622}
623
624#[async_trait]
626pub trait Database<Error>:
627 KVStoreDatabase<Err = Error>
628 + QuotesDatabase<Err = Error>
629 + ProofsDatabase<Err = Error>
630 + SignaturesDatabase<Err = Error>
631 + SagaDatabase<Err = Error>
632 + CompletedOperationsDatabase<Err = Error>
633{
634 async fn begin_transaction(&self) -> Result<Box<dyn Transaction<Error> + Send + Sync>, Error>;
636}
637
638pub type DynMintDatabase = std::sync::Arc<dyn Database<Error> + Send + Sync>;
640
641pub type DynMintTransaction = Box<dyn Transaction<Error> + Send + Sync>;