Skip to main content

cdk_common/database/wallet/
mod.rs

1//! CDK Database
2
3use std::collections::HashMap;
4use std::fmt::Debug;
5
6use async_trait::async_trait;
7use bitcoin::bip32::DerivationPath;
8use cashu::KeySet;
9
10use super::Error;
11use crate::mint_url::MintUrl;
12use crate::nuts::{
13    CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State,
14};
15use crate::wallet::{
16    self, MintQuote as WalletMintQuote, ProofInfo, Transaction, TransactionDirection, TransactionId,
17};
18
19#[cfg(feature = "test")]
20pub mod test;
21
22/// Wallet Database trait
23#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
24#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
25pub trait Database<Err>: Debug
26where
27    Err: Into<Error> + From<Error>,
28{
29    /// Get mint from storage
30    async fn get_mint(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, Err>;
31
32    /// Get all mints from storage
33    async fn get_mints(&self) -> Result<HashMap<MintUrl, Option<MintInfo>>, Err>;
34
35    /// Get mint keysets for mint url
36    async fn get_mint_keysets(&self, mint_url: MintUrl) -> Result<Option<Vec<KeySetInfo>>, Err>;
37
38    /// Get mint keyset by id
39    async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Err>;
40
41    /// Get mint quote from storage
42    async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<WalletMintQuote>, Err>;
43
44    /// Get mint quotes from storage
45    async fn get_mint_quotes(&self) -> Result<Vec<WalletMintQuote>, Err>;
46    /// Get unissued mint quotes from storage
47    /// Returns bolt11 quotes where nothing has been issued yet (amount_issued = 0) and all bolt12 quotes.
48    /// Includes unpaid bolt11 quotes to allow checking with the mint if they've been paid (wallet state may be outdated).
49    async fn get_unissued_mint_quotes(&self) -> Result<Vec<WalletMintQuote>, Err>;
50
51    /// Get melt quote from storage
52    async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<wallet::MeltQuote>, Err>;
53
54    /// Get melt quotes from storage
55    async fn get_melt_quotes(&self) -> Result<Vec<wallet::MeltQuote>, Err>;
56
57    /// Get [`Keys`] from storage
58    async fn get_keys(&self, id: &Id) -> Result<Option<Keys>, Err>;
59
60    /// Get proofs from storage
61    async fn get_proofs(
62        &self,
63        mint_url: Option<MintUrl>,
64        unit: Option<CurrencyUnit>,
65        state: Option<Vec<State>>,
66        spending_conditions: Option<Vec<SpendingConditions>>,
67    ) -> Result<Vec<ProofInfo>, Err>;
68
69    /// Get proofs by Y values
70    async fn get_proofs_by_ys(&self, ys: Vec<PublicKey>) -> Result<Vec<ProofInfo>, Err>;
71
72    /// Get balance
73    async fn get_balance(
74        &self,
75        mint_url: Option<MintUrl>,
76        unit: Option<CurrencyUnit>,
77        state: Option<Vec<State>>,
78    ) -> Result<u64, Err>;
79
80    /// Get transaction from storage
81    async fn get_transaction(
82        &self,
83        transaction_id: TransactionId,
84    ) -> Result<Option<Transaction>, Err>;
85
86    /// List transactions from storage
87    async fn list_transactions(
88        &self,
89        mint_url: Option<MintUrl>,
90        direction: Option<TransactionDirection>,
91        unit: Option<CurrencyUnit>,
92    ) -> Result<Vec<Transaction>, Err>;
93
94    /// Update the proofs in storage by adding new proofs or removing proofs by
95    /// their Y value
96    async fn update_proofs(
97        &self,
98        added: Vec<ProofInfo>,
99        removed_ys: Vec<PublicKey>,
100    ) -> Result<(), Err>;
101
102    /// Update proofs state in storage
103    async fn update_proofs_state(&self, ys: Vec<PublicKey>, state: State) -> Result<(), Err>;
104
105    /// Add transaction to storage
106    async fn add_transaction(&self, transaction: Transaction) -> Result<(), Err>;
107
108    /// Update mint url
109    async fn update_mint_url(
110        &self,
111        old_mint_url: MintUrl,
112        new_mint_url: MintUrl,
113    ) -> Result<(), Err>;
114
115    /// Atomically increment Keyset counter and return new value
116    async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<u32, Err>;
117
118    /// Atomically increment a namespaced derivation counter and return its new value.
119    async fn increment_derivation_counter(&self, namespace: &str, count: u32) -> Result<u32, Err>;
120
121    /// Add Mint to storage
122    async fn add_mint(&self, mint_url: MintUrl, mint_info: Option<MintInfo>) -> Result<(), Err>;
123
124    /// Remove Mint from storage
125    async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), Err>;
126
127    /// Add mint keyset to storage
128    async fn add_mint_keysets(
129        &self,
130        mint_url: MintUrl,
131        keysets: Vec<KeySetInfo>,
132    ) -> Result<(), Err>;
133
134    /// Add mint quote to storage
135    async fn add_mint_quote(&self, quote: WalletMintQuote) -> Result<(), Err>;
136
137    /// Remove mint quote from storage
138    async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Err>;
139
140    /// Add melt quote to storage
141    async fn add_melt_quote(&self, quote: wallet::MeltQuote) -> Result<(), Err>;
142
143    /// Remove melt quote from storage
144    async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Err>;
145
146    /// Add [`Keys`] to storage
147    async fn add_keys(&self, keyset: KeySet) -> Result<(), Err>;
148
149    /// Remove [`Keys`] from storage
150    async fn remove_keys(&self, id: &Id) -> Result<(), Err>;
151
152    /// Remove transaction from storage
153    async fn remove_transaction(&self, transaction_id: TransactionId) -> Result<(), Err>;
154
155    /// Add a wallet saga to storage.
156    ///
157    /// The saga should be created with `WalletSaga::new()` which initializes
158    /// `version = 0`. This is the starting point for optimistic locking.
159    async fn add_saga(&self, saga: wallet::WalletSaga) -> Result<(), Err>;
160
161    /// Get a wallet saga by ID.
162    async fn get_saga(&self, id: &uuid::Uuid) -> Result<Option<wallet::WalletSaga>, Err>;
163
164    /// Update a wallet saga with optimistic locking.
165    ///
166    /// Returns `Ok(true)` if the update succeeded (version match), or `Ok(false)`
167    /// if another instance modified the saga first (version mismatch).
168    async fn update_saga(&self, saga: wallet::WalletSaga) -> Result<bool, Err>;
169
170    /// Delete a wallet saga.
171    async fn delete_saga(&self, id: &uuid::Uuid) -> Result<(), Err>;
172
173    /// Get all incomplete sagas.
174    async fn get_incomplete_sagas(&self) -> Result<Vec<wallet::WalletSaga>, Err>;
175
176    /// Reserve proofs for an operation
177    async fn reserve_proofs(
178        &self,
179        ys: Vec<PublicKey>,
180        operation_id: &uuid::Uuid,
181    ) -> Result<(), Err>;
182
183    /// Release proofs reserved by an operation.
184    ///
185    /// Only proofs owned by `operation_id` in [`State::Reserved`] or
186    /// [`State::Pending`] may be changed to [`State::Unspent`]. Implementations
187    /// must preserve spent proofs and proofs owned by another operation.
188    async fn release_proofs(&self, operation_id: &uuid::Uuid) -> Result<(), Err>;
189
190    /// Get proofs reserved by an operation
191    async fn get_reserved_proofs(&self, operation_id: &uuid::Uuid) -> Result<Vec<ProofInfo>, Err>;
192
193    /// Reserve a melt quote for an operation.
194    async fn reserve_melt_quote(
195        &self,
196        quote_id: &str,
197        operation_id: &uuid::Uuid,
198    ) -> Result<(), Err>;
199
200    /// Release a melt quote reserved by an operation.
201    async fn release_melt_quote(&self, operation_id: &uuid::Uuid) -> Result<(), Err>;
202
203    /// Reserve a mint quote for an operation.
204    async fn reserve_mint_quote(
205        &self,
206        quote_id: &str,
207        operation_id: &uuid::Uuid,
208    ) -> Result<(), Err>;
209
210    /// Release a mint quote reserved by an operation.
211    async fn release_mint_quote(&self, operation_id: &uuid::Uuid) -> Result<(), Err>;
212
213    /// Read a value from the key-value store
214    async fn kv_read(
215        &self,
216        primary_namespace: &str,
217        secondary_namespace: &str,
218        key: &str,
219    ) -> Result<Option<Vec<u8>>, Err>;
220
221    /// List keys in a namespace
222    async fn kv_list(
223        &self,
224        primary_namespace: &str,
225        secondary_namespace: &str,
226    ) -> Result<Vec<String>, Err>;
227
228    /// Write a value to the key-value store
229    async fn kv_write(
230        &self,
231        primary_namespace: &str,
232        secondary_namespace: &str,
233        key: &str,
234        value: &[u8],
235    ) -> Result<(), Err>;
236
237    /// Remove a value from the key-value store
238    async fn kv_remove(
239        &self,
240        primary_namespace: &str,
241        secondary_namespace: &str,
242        key: &str,
243    ) -> Result<(), Err>;
244
245    // P2PK signing key methods
246
247    /// Store a P2PK signing key for the wallet
248    async fn add_p2pk_key(
249        &self,
250        pubkey: &PublicKey,
251        derivation_path: DerivationPath,
252        derivation_index: u32,
253    ) -> Result<(), Err>;
254
255    /// Get a stored P2PK signing key by pubkey.
256    async fn get_p2pk_key(&self, pubkey: &PublicKey)
257        -> Result<Option<wallet::P2PKSigningKey>, Err>;
258
259    /// List all stored P2PK signing keys.
260    async fn list_p2pk_keys(&self) -> Result<Vec<wallet::P2PKSigningKey>, Err>;
261
262    /// Tries to get the latest p2pk key generated
263    async fn latest_p2pk(&self) -> Result<Option<wallet::P2PKSigningKey>, Err>;
264}