Skip to main content

cdk_common/database/
mod.rs

1//! CDK Database
2
3mod kvstore;
4
5#[cfg(feature = "mint")]
6pub mod mint;
7#[cfg(feature = "wallet")]
8pub mod wallet;
9
10// Re-export shared KVStore types at the top level for both mint and wallet
11pub use kvstore::{
12    validate_kvstore_params, validate_kvstore_string, KVStore, KVStoreDatabase, KVStoreTransaction,
13    KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN,
14};
15
16/// Arc-wrapped KV store for shared ownership
17pub type DynKVStore = std::sync::Arc<dyn KVStore<Err = Error> + Send + Sync>;
18
19#[cfg(feature = "mint")]
20pub use mint::{
21    Database as MintDatabase, DynMintDatabase, DynMintTransaction,
22    KeysDatabase as MintKeysDatabase, KeysDatabaseTransaction as MintKeyDatabaseTransaction,
23    ProofsDatabase as MintProofsDatabase, ProofsTransaction as MintProofsTransaction,
24    QuotesDatabase as MintQuotesDatabase, QuotesTransaction as MintQuotesTransaction,
25    SignaturesDatabase as MintSignaturesDatabase,
26    SignaturesTransaction as MintSignatureTransaction, Transaction as MintTransaction,
27};
28#[cfg(feature = "mint")]
29pub use mint::{DynMintAuthDatabase, MintAuthDatabase, MintAuthTransaction};
30#[cfg(feature = "wallet")]
31pub use wallet::Database as WalletDatabase;
32
33/// Data conversion error
34#[derive(thiserror::Error, Debug)]
35pub enum ConversionError {
36    /// Missing columns
37    #[error("Not enough elements: expected {0}, got {1}")]
38    MissingColumn(usize, usize),
39
40    /// Missing parameter
41    #[error("Missing parameter {0}")]
42    MissingParameter(String),
43
44    /// Invalid db type
45    #[error("Invalid type from db, expected {0} got {1}")]
46    InvalidType(String, String),
47
48    /// Invalid data conversion in column
49    #[error("Error converting {1}, expecting type {0}")]
50    InvalidConversion(String, String),
51
52    /// Mint Url Error
53    #[error(transparent)]
54    MintUrl(#[from] crate::mint_url::Error),
55
56    /// NUT00 Error
57    #[error(transparent)]
58    CDKNUT00(#[from] crate::nuts::nut00::Error),
59
60    /// NUT01 Error
61    #[error(transparent)]
62    CDKNUT01(#[from] crate::nuts::nut01::Error),
63
64    /// NUT02 Error
65    #[error(transparent)]
66    CDKNUT02(#[from] crate::nuts::nut02::Error),
67
68    /// NUT04 Error
69    #[error(transparent)]
70    CDKNUT04(#[from] crate::nuts::nut04::Error),
71
72    /// NUT05 Error
73    #[error(transparent)]
74    CDKNUT05(#[from] crate::nuts::nut05::Error),
75
76    /// NUT07 Error
77    #[error(transparent)]
78    CDKNUT07(#[from] crate::nuts::nut07::Error),
79
80    /// NUT23 Error
81    #[error(transparent)]
82    CDKNUT23(#[from] crate::nuts::nut23::Error),
83
84    /// Secret Error
85    #[error(transparent)]
86    CDKSECRET(#[from] crate::secret::Error),
87
88    /// Serde Error
89    #[error(transparent)]
90    Serde(#[from] serde_json::Error),
91
92    /// BIP32 Error
93    #[error(transparent)]
94    BIP32(#[from] bitcoin::bip32::Error),
95
96    /// Generic error
97    #[error(transparent)]
98    Generic(#[from] Box<crate::Error>),
99}
100
101impl From<crate::Error> for ConversionError {
102    fn from(err: crate::Error) -> Self {
103        ConversionError::Generic(Box::new(err))
104    }
105}
106
107/// CDK_database error
108#[derive(Debug, thiserror::Error)]
109pub enum Error {
110    /// Database Error
111    #[error(transparent)]
112    Database(Box<dyn std::error::Error + Send + Sync>),
113
114    /// Duplicate entry
115    #[error("Duplicate entry")]
116    Duplicate,
117
118    /// Locked resource
119    #[error("Locked resource")]
120    Locked,
121
122    /// Amount overflow
123    #[error("Amount overflow")]
124    AmountOverflow,
125    /// Amount zero
126    #[error("Amount zero")]
127    AmountZero,
128
129    /// DHKE error
130    #[error(transparent)]
131    DHKE(#[from] crate::dhke::Error),
132    /// NUT00 Error
133    #[error(transparent)]
134    NUT00(#[from] crate::nuts::nut00::Error),
135    /// NUT01 Error
136    #[error(transparent)]
137    NUT01(#[from] crate::nuts::nut01::Error),
138    /// NUT02 Error
139    #[error(transparent)]
140    NUT02(#[from] crate::nuts::nut02::Error),
141    /// NUT22 Error
142    #[error(transparent)]
143    NUT22(#[from] crate::nuts::nut22::Error),
144    /// NUT04 Error
145    #[error(transparent)]
146    NUT04(#[from] crate::nuts::nut04::Error),
147    /// Quote ID Error
148    #[error(transparent)]
149    #[cfg(feature = "mint")]
150    QuoteId(#[from] crate::quote_id::QuoteIdError),
151    /// Serde Error
152    #[error(transparent)]
153    Serde(#[from] serde_json::Error),
154    /// Unknown Quote
155    #[error("Unknown Quote")]
156    UnknownQuote,
157    /// Attempt to remove spent proof
158    #[error("Attempt to remove spent proof")]
159    AttemptRemoveSpentProof,
160    /// Attempt to update state of spent proof
161    #[error("Attempt to update state of spent proof")]
162    AttemptUpdateSpentProof,
163    /// Proof not found
164    #[error("Proof not found")]
165    ProofNotFound,
166    /// Proof not in unspent state (may be reserved, pending, or spent)
167    #[error("Proof not in unspent state")]
168    ProofNotUnspent,
169    /// Quote is already in use by another operation
170    #[error("Quote already in use by another operation")]
171    QuoteAlreadyInUse,
172    /// Invalid keyset
173    #[error("Unknown or invalid keyset")]
174    InvalidKeysetId,
175    #[cfg(feature = "mint")]
176    /// Invalid state transition
177    #[error("Invalid state transition")]
178    InvalidStateTransition(crate::state::Error),
179
180    /// Invalid connection settings
181    #[error("Invalid credentials {0}")]
182    InvalidConnectionSettings(String),
183
184    /// Unexpected database response
185    #[error("Invalid database response")]
186    InvalidDbResponse,
187
188    /// Internal error
189    #[error("Internal {0}")]
190    Internal(String),
191
192    /// Data conversion error
193    #[error(transparent)]
194    Conversion(#[from] ConversionError),
195
196    /// Missing Placeholder value
197    #[error("Missing placeholder value {0}")]
198    MissingPlaceholder(String),
199
200    /// Empty IN clause
201    #[error("Empty IN clause for placeholder: {0}")]
202    EmptyInClause(String),
203
204    /// Unknown quote ttl
205    #[error("Unknown quote ttl")]
206    UnknownQuoteTTL,
207
208    /// Invalid UUID
209    #[error("Invalid UUID: {0}")]
210    InvalidUuid(String),
211
212    /// QuoteNotFound
213    #[error("Quote not found")]
214    QuoteNotFound,
215
216    /// KV Store invalid key or namespace
217    #[error("Invalid KV store key or namespace: {0}")]
218    KVStoreInvalidKey(String),
219
220    /// Concurrent update detected
221    #[error("Concurrent update detected")]
222    ConcurrentUpdate,
223}
224
225#[cfg(feature = "mint")]
226impl From<crate::state::Error> for Error {
227    fn from(state: crate::state::Error) -> Self {
228        match state {
229            crate::state::Error::AlreadySpent => Error::AttemptUpdateSpentProof,
230            _ => Error::InvalidStateTransition(state),
231        }
232    }
233}
234
235#[async_trait::async_trait]
236/// Commit and Rollback
237pub trait DbTransactionFinalizer {
238    /// Mint Signature Database Error
239    type Err: Into<Error> + From<Error>;
240
241    /// Commits all the changes into the database
242    async fn commit(self: Box<Self>) -> Result<(), Self::Err>;
243
244    /// Rollbacks the write transaction
245    async fn rollback(self: Box<Self>) -> Result<(), Self::Err>;
246}