diff --git a/crates/cashu/Cargo.toml b/crates/cashu/Cargo.toml index 93326e137..21ad030da 100644 --- a/crates/cashu/Cargo.toml +++ b/crates/cashu/Cargo.toml @@ -6,10 +6,14 @@ description = "Cashu shared types and crypto utilities, used as the foundation f rust-version = "1.63.0" # MSRV [features] +default = ["mint", "wallet"] swagger = ["dep:utoipa"] +mint = ["dep:uuid"] +wallet = [] bench = [] [dependencies] +uuid = { version = "1", features = ["v4", "serde"], optional = true } bitcoin = { version = "0.32.2", features = [ "base64", "serde", @@ -24,7 +28,6 @@ lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } thiserror = "2" tracing = "0.1" url = "2.3" -uuid = { version = "1", features = ["v4", "serde"] } utoipa = { version = "4", optional = true } serde_json = "1" serde_with = "3" diff --git a/crates/cashu/src/lib.rs b/crates/cashu/src/lib.rs index aa59f1d48..9ca087236 100644 --- a/crates/cashu/src/lib.rs +++ b/crates/cashu/src/lib.rs @@ -2,11 +2,14 @@ //! pub mod amount; pub mod dhke; +#[cfg(feature = "mint")] pub mod mint; pub mod mint_url; pub mod nuts; pub mod secret; pub mod util; +#[cfg(feature = "wallet")] +pub mod wallet; pub use lightning_invoice::{self, Bolt11Invoice}; diff --git a/crates/cashu/src/nuts/mod.rs b/crates/cashu/src/nuts/mod.rs index 3921beb33..933254f53 100644 --- a/crates/cashu/src/nuts/mod.rs +++ b/crates/cashu/src/nuts/mod.rs @@ -28,7 +28,9 @@ pub use nut00::{ Proofs, ProofsMethods, Token, TokenV3, TokenV4, Witness, }; pub use nut01::{Keys, KeysResponse, PublicKey, SecretKey}; -pub use nut02::{Id, KeySet, KeySetInfo, KeysetResponse, MintKeySet}; +#[cfg(feature = "mint")] +pub use nut02::MintKeySet; +pub use nut02::{Id, KeySet, KeySetInfo, KeysetResponse}; pub use nut03::{PreSwap, SwapRequest, SwapResponse}; pub use nut04::{ MintBolt11Request, MintBolt11Response, MintMethodSettings, MintQuoteBolt11Request, diff --git a/crates/cashu/src/nuts/nut00/mod.rs b/crates/cashu/src/nuts/nut00/mod.rs index 615928492..b16f6f1ae 100644 --- a/crates/cashu/src/nuts/nut00/mod.rs +++ b/crates/cashu/src/nuts/nut00/mod.rs @@ -379,6 +379,7 @@ pub enum CurrencyUnit { Custom(String), } +#[cfg(feature = "mint")] impl CurrencyUnit { /// Derivation index mint will use for unit pub fn derivation_index(&self) -> Option { diff --git a/crates/cashu/src/nuts/nut04.rs b/crates/cashu/src/nuts/nut04.rs index ebbb62001..0eda1b7a8 100644 --- a/crates/cashu/src/nuts/nut04.rs +++ b/crates/cashu/src/nuts/nut04.rs @@ -8,6 +8,7 @@ use std::str::FromStr; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use thiserror::Error; +#[cfg(feature = "mint")] use uuid::Uuid; use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod}; @@ -115,6 +116,7 @@ impl MintQuoteBolt11Response { } } +#[cfg(feature = "mint")] impl From> for MintQuoteBolt11Response { fn from(value: MintQuoteBolt11Response) -> Self { Self { @@ -127,6 +129,7 @@ impl From> for MintQuoteBolt11Response { } } +#[cfg(feature = "mint")] impl From for MintQuoteBolt11Response { fn from(mint_quote: crate::mint::MintQuote) -> MintQuoteBolt11Response { MintQuoteBolt11Response { @@ -155,6 +158,7 @@ pub struct MintBolt11Request { pub signature: Option, } +#[cfg(feature = "mint")] impl TryFrom> for MintBolt11Request { type Error = uuid::Error; diff --git a/crates/cashu/src/nuts/nut05.rs b/crates/cashu/src/nuts/nut05.rs index 8b4e8514a..ab042c8ee 100644 --- a/crates/cashu/src/nuts/nut05.rs +++ b/crates/cashu/src/nuts/nut05.rs @@ -9,10 +9,12 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; use thiserror::Error; +#[cfg(feature = "mint")] use uuid::Uuid; use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod, Proofs}; use super::nut15::Mpp; +#[cfg(feature = "mint")] use crate::mint::{self, MeltQuote}; use crate::nuts::MeltQuoteState; use crate::{Amount, Bolt11Invoice}; @@ -192,6 +194,7 @@ impl MeltQuoteBolt11Response { } } +#[cfg(feature = "mint")] impl From> for MeltQuoteBolt11Response { fn from(value: MeltQuoteBolt11Response) -> Self { Self { @@ -207,6 +210,7 @@ impl From> for MeltQuoteBolt11Response { } } +#[cfg(feature = "mint")] impl From<&MeltQuote> for MeltQuoteBolt11Response { fn from(melt_quote: &MeltQuote) -> MeltQuoteBolt11Response { MeltQuoteBolt11Response { @@ -306,6 +310,7 @@ impl<'de, Q: DeserializeOwned> Deserialize<'de> for MeltQuoteBolt11Response { } } +#[cfg(feature = "mint")] impl From for MeltQuoteBolt11Response { fn from(melt_quote: mint::MeltQuote) -> MeltQuoteBolt11Response { let paid = melt_quote.state == QuoteState::Paid; @@ -337,6 +342,7 @@ pub struct MeltBolt11Request { pub outputs: Option>, } +#[cfg(feature = "mint")] impl TryFrom> for MeltBolt11Request { type Error = uuid::Error; diff --git a/crates/cashu/src/nuts/nut17/mod.rs b/crates/cashu/src/nuts/nut17/mod.rs index 4a1674d2e..11e686242 100644 --- a/crates/cashu/src/nuts/nut17/mod.rs +++ b/crates/cashu/src/nuts/nut17/mod.rs @@ -1,8 +1,10 @@ //! Specific Subscription for the cdk crate use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; +#[cfg(feature = "mint")] use uuid::Uuid; +#[cfg(feature = "mint")] use super::PublicKey; use crate::nuts::{ CurrencyUnit, MeltQuoteBolt11Response, MintQuoteBolt11Response, PaymentMethod, ProofState, @@ -97,6 +99,7 @@ impl From> for NotificationPayload { } } +#[cfg(feature = "mint")] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] /// A parsed notification pub enum Notification { @@ -129,6 +132,7 @@ impl AsRef for Params { /// Parsing error #[derive(thiserror::Error, Debug)] pub enum Error { + #[cfg(feature = "mint")] #[error("Uuid Error: {0}")] /// Uuid Error Uuid(#[from] uuid::Error), diff --git a/crates/cdk-common/src/wallet.rs b/crates/cashu/src/wallet.rs similarity index 100% rename from crates/cdk-common/src/wallet.rs rename to crates/cashu/src/wallet.rs diff --git a/crates/cdk-common/Cargo.toml b/crates/cdk-common/Cargo.toml index 1a57c3fe5..f3773e318 100644 --- a/crates/cdk-common/Cargo.toml +++ b/crates/cdk-common/Cargo.toml @@ -6,8 +6,11 @@ description = "CDK common types and traits" rust-version = "1.63.0" # MSRV [features] +default = ["mint", "wallet"] swagger = ["dep:utoipa", "cashu/swagger"] bench = [] +wallet = ["cashu/wallet"] +mint = ["cashu/mint"] [dependencies] async-trait = "0.1" @@ -17,7 +20,7 @@ bitcoin = { version = "0.32.2", features = [ "rand", "rand-std", ] } -cashu = { path = "../cashu", version = "0.6.0" } +cashu = { path = "../cashu", default-features = false, version = "0.6.0" } cbor-diag = "0.1.12" ciborium = { version = "0.2.2", default-features = false, features = ["std"] } once_cell = "1.20.2" diff --git a/crates/cdk-common/src/database.rs b/crates/cdk-common/src/database.rs deleted file mode 100644 index 98523a0af..000000000 --- a/crates/cdk-common/src/database.rs +++ /dev/null @@ -1,262 +0,0 @@ -//! CDK Database - -use std::collections::HashMap; -use std::fmt::Debug; - -use async_trait::async_trait; -use thiserror::Error; -use uuid::Uuid; - -use crate::common::{LnKey, ProofInfo}; -use crate::mint::{self, MintKeySetInfo, MintQuote as MintMintQuote}; -use crate::mint_url::MintUrl; -use crate::nuts::{ - BlindSignature, CurrencyUnit, Id, KeySetInfo, Keys, MeltBolt11Request, MeltQuoteState, - MintInfo, MintQuoteState, Proof, Proofs, PublicKey, SpendingConditions, State, -}; -use crate::wallet; -use crate::wallet::MintQuote as WalletMintQuote; - -/// CDK_database error -#[derive(Debug, Error)] -pub enum Error { - /// Database Error - #[error(transparent)] - Database(Box), - /// DHKE error - #[error(transparent)] - DHKE(#[from] crate::dhke::Error), - /// NUT00 Error - #[error(transparent)] - NUT00(#[from] crate::nuts::nut00::Error), - /// NUT02 Error - #[error(transparent)] - NUT02(#[from] crate::nuts::nut02::Error), - /// Serde Error - #[error(transparent)] - Serde(#[from] serde_json::Error), - /// Unknown Quote - #[error("Unknown Quote")] - UnknownQuote, -} - -/// Wallet Database trait -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -pub trait WalletDatabase: Debug { - /// Wallet Database Error - type Err: Into + From; - - /// Add Mint to storage - async fn add_mint( - &self, - mint_url: MintUrl, - mint_info: Option, - ) -> Result<(), Self::Err>; - /// Remove Mint from storage - async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), Self::Err>; - /// Get mint from storage - async fn get_mint(&self, mint_url: MintUrl) -> Result, Self::Err>; - /// Get all mints from storage - async fn get_mints(&self) -> Result>, Self::Err>; - /// Update mint url - async fn update_mint_url( - &self, - old_mint_url: MintUrl, - new_mint_url: MintUrl, - ) -> Result<(), Self::Err>; - - /// Add mint keyset to storage - async fn add_mint_keysets( - &self, - mint_url: MintUrl, - keysets: Vec, - ) -> Result<(), Self::Err>; - /// Get mint keysets for mint url - async fn get_mint_keysets( - &self, - mint_url: MintUrl, - ) -> Result>, Self::Err>; - /// Get mint keyset by id - async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result, Self::Err>; - - /// Add mint quote to storage - async fn add_mint_quote(&self, quote: WalletMintQuote) -> Result<(), Self::Err>; - /// Get mint quote from storage - async fn get_mint_quote(&self, quote_id: &str) -> Result, Self::Err>; - /// Get mint quotes from storage - async fn get_mint_quotes(&self) -> Result, Self::Err>; - /// Remove mint quote from storage - async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err>; - - /// Add melt quote to storage - async fn add_melt_quote(&self, quote: wallet::MeltQuote) -> Result<(), Self::Err>; - /// Get melt quote from storage - async fn get_melt_quote(&self, quote_id: &str) -> Result, Self::Err>; - /// Remove melt quote from storage - async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err>; - - /// Add [`Keys`] to storage - async fn add_keys(&self, keys: Keys) -> Result<(), Self::Err>; - /// Get [`Keys`] from storage - async fn get_keys(&self, id: &Id) -> Result, Self::Err>; - /// Remove [`Keys`] from storage - async fn remove_keys(&self, id: &Id) -> Result<(), Self::Err>; - - /// Update the proofs in storage by adding new proofs or removing proofs by - /// their Y value. - async fn update_proofs( - &self, - added: Vec, - removed_ys: Vec, - ) -> Result<(), Self::Err>; - /// Set proofs as pending in storage. Proofs are identified by their Y - /// value. - async fn set_pending_proofs(&self, ys: Vec) -> Result<(), Self::Err>; - /// Reserve proofs in storage. Proofs are identified by their Y value. - async fn reserve_proofs(&self, ys: Vec) -> Result<(), Self::Err>; - /// Set proofs as unspent in storage. Proofs are identified by their Y - /// value. - async fn set_unspent_proofs(&self, ys: Vec) -> Result<(), Self::Err>; - /// Get proofs from storage - async fn get_proofs( - &self, - mint_url: Option, - unit: Option, - state: Option>, - spending_conditions: Option>, - ) -> Result, Self::Err>; - - /// Increment Keyset counter - async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err>; - /// Get current Keyset counter - async fn get_keyset_counter(&self, keyset_id: &Id) -> Result, Self::Err>; - - /// Get when nostr key was last checked - async fn get_nostr_last_checked( - &self, - verifying_key: &PublicKey, - ) -> Result, Self::Err>; - /// Update last checked time - async fn add_nostr_last_checked( - &self, - verifying_key: PublicKey, - last_checked: u32, - ) -> Result<(), Self::Err>; -} - -/// Mint Database trait -#[async_trait] -pub trait MintDatabase { - /// Mint Database Error - type Err: Into + From; - - /// Add Active Keyset - async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err>; - /// Get Active Keyset - async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result, Self::Err>; - /// Get all Active Keyset - async fn get_active_keysets(&self) -> Result, Self::Err>; - - /// Add [`MintMintQuote`] - async fn add_mint_quote(&self, quote: MintMintQuote) -> Result<(), Self::Err>; - /// Get [`MintMintQuote`] - async fn get_mint_quote(&self, quote_id: &Uuid) -> Result, Self::Err>; - /// Update state of [`MintMintQuote`] - async fn update_mint_quote_state( - &self, - quote_id: &Uuid, - state: MintQuoteState, - ) -> Result; - /// Get all [`MintMintQuote`]s - async fn get_mint_quote_by_request( - &self, - request: &str, - ) -> Result, Self::Err>; - /// Get all [`MintMintQuote`]s - async fn get_mint_quote_by_request_lookup_id( - &self, - request_lookup_id: &str, - ) -> Result, Self::Err>; - /// Get Mint Quotes - async fn get_mint_quotes(&self) -> Result, Self::Err>; - /// Remove [`MintMintQuote`] - async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err>; - - /// Add [`mint::MeltQuote`] - async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err>; - /// Get [`mint::MeltQuote`] - async fn get_melt_quote(&self, quote_id: &Uuid) -> Result, Self::Err>; - /// Update [`mint::MeltQuote`] state - async fn update_melt_quote_state( - &self, - quote_id: &Uuid, - state: MeltQuoteState, - ) -> Result; - /// Get all [`mint::MeltQuote`]s - async fn get_melt_quotes(&self) -> Result, Self::Err>; - /// Remove [`mint::MeltQuote`] - async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err>; - - /// Add melt request - async fn add_melt_request( - &self, - melt_request: MeltBolt11Request, - ln_key: LnKey, - ) -> Result<(), Self::Err>; - /// Get melt request - async fn get_melt_request( - &self, - quote_id: &Uuid, - ) -> Result, LnKey)>, Self::Err>; - - /// Add [`MintKeySetInfo`] - async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err>; - /// Get [`MintKeySetInfo`] - async fn get_keyset_info(&self, id: &Id) -> Result, Self::Err>; - /// Get [`MintKeySetInfo`]s - async fn get_keyset_infos(&self) -> Result, Self::Err>; - - /// Add spent [`Proofs`] - async fn add_proofs(&self, proof: Proofs, quote_id: Option) -> Result<(), Self::Err>; - /// Get [`Proofs`] by ys - async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result>, Self::Err>; - /// Get ys by quote id - async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result, Self::Err>; - /// Get [`Proofs`] state - async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result>, Self::Err>; - /// Get [`Proofs`] state - async fn update_proofs_states( - &self, - ys: &[PublicKey], - proofs_state: State, - ) -> Result>, Self::Err>; - /// Get [`Proofs`] by state - async fn get_proofs_by_keyset_id( - &self, - keyset_id: &Id, - ) -> Result<(Proofs, Vec>), Self::Err>; - - /// Add [`BlindSignature`] - async fn add_blind_signatures( - &self, - blinded_messages: &[PublicKey], - blind_signatures: &[BlindSignature], - quote_id: Option, - ) -> Result<(), Self::Err>; - /// Get [`BlindSignature`]s - async fn get_blind_signatures( - &self, - blinded_messages: &[PublicKey], - ) -> Result>, Self::Err>; - /// Get [`BlindSignature`]s for keyset_id - async fn get_blind_signatures_for_keyset( - &self, - keyset_id: &Id, - ) -> Result, Self::Err>; - /// Get [`BlindSignature`]s for quote - async fn get_blind_signatures_for_quote( - &self, - quote_id: &Uuid, - ) -> Result, Self::Err>; -} diff --git a/crates/cdk-common/src/database/mint.rs b/crates/cdk-common/src/database/mint.rs new file mode 100644 index 000000000..4755b626d --- /dev/null +++ b/crates/cdk-common/src/database/mint.rs @@ -0,0 +1,130 @@ +//! CDK Database + +use std::collections::HashMap; + +use async_trait::async_trait; +use uuid::Uuid; + +use super::Error; +use crate::common::LnKey; +use crate::mint::{self, MintKeySetInfo, MintQuote as MintMintQuote}; +use crate::nuts::{ + BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintQuoteState, Proof, + Proofs, PublicKey, State, +}; + +/// Mint Database trait +#[async_trait] +pub trait Database { + /// Mint Database Error + type Err: Into + From; + + /// Add Active Keyset + async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err>; + /// Get Active Keyset + async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result, Self::Err>; + /// Get all Active Keyset + async fn get_active_keysets(&self) -> Result, Self::Err>; + + /// Add [`MintMintQuote`] + async fn add_mint_quote(&self, quote: MintMintQuote) -> Result<(), Self::Err>; + /// Get [`MintMintQuote`] + async fn get_mint_quote(&self, quote_id: &Uuid) -> Result, Self::Err>; + /// Update state of [`MintMintQuote`] + async fn update_mint_quote_state( + &self, + quote_id: &Uuid, + state: MintQuoteState, + ) -> Result; + /// Get all [`MintMintQuote`]s + async fn get_mint_quote_by_request( + &self, + request: &str, + ) -> Result, Self::Err>; + /// Get all [`MintMintQuote`]s + async fn get_mint_quote_by_request_lookup_id( + &self, + request_lookup_id: &str, + ) -> Result, Self::Err>; + /// Get Mint Quotes + async fn get_mint_quotes(&self) -> Result, Self::Err>; + /// Remove [`MintMintQuote`] + async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err>; + + /// Add [`mint::MeltQuote`] + async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err>; + /// Get [`mint::MeltQuote`] + async fn get_melt_quote(&self, quote_id: &Uuid) -> Result, Self::Err>; + /// Update [`mint::MeltQuote`] state + async fn update_melt_quote_state( + &self, + quote_id: &Uuid, + state: MeltQuoteState, + ) -> Result; + /// Get all [`mint::MeltQuote`]s + async fn get_melt_quotes(&self) -> Result, Self::Err>; + /// Remove [`mint::MeltQuote`] + async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err>; + + /// Add melt request + async fn add_melt_request( + &self, + melt_request: MeltBolt11Request, + ln_key: LnKey, + ) -> Result<(), Self::Err>; + /// Get melt request + async fn get_melt_request( + &self, + quote_id: &Uuid, + ) -> Result, LnKey)>, Self::Err>; + + /// Add [`MintKeySetInfo`] + async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err>; + /// Get [`MintKeySetInfo`] + async fn get_keyset_info(&self, id: &Id) -> Result, Self::Err>; + /// Get [`MintKeySetInfo`]s + async fn get_keyset_infos(&self) -> Result, Self::Err>; + + /// Add spent [`Proofs`] + async fn add_proofs(&self, proof: Proofs, quote_id: Option) -> Result<(), Self::Err>; + /// Get [`Proofs`] by ys + async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result>, Self::Err>; + /// Get ys by quote id + async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result, Self::Err>; + /// Get [`Proofs`] state + async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result>, Self::Err>; + /// Get [`Proofs`] state + async fn update_proofs_states( + &self, + ys: &[PublicKey], + proofs_state: State, + ) -> Result>, Self::Err>; + /// Get [`Proofs`] by state + async fn get_proofs_by_keyset_id( + &self, + keyset_id: &Id, + ) -> Result<(Proofs, Vec>), Self::Err>; + + /// Add [`BlindSignature`] + async fn add_blind_signatures( + &self, + blinded_messages: &[PublicKey], + blind_signatures: &[BlindSignature], + quote_id: Option, + ) -> Result<(), Self::Err>; + /// Get [`BlindSignature`]s + async fn get_blind_signatures( + &self, + blinded_messages: &[PublicKey], + ) -> Result>, Self::Err>; + /// Get [`BlindSignature`]s for keyset_id + async fn get_blind_signatures_for_keyset( + &self, + keyset_id: &Id, + ) -> Result, Self::Err>; + /// Get [`BlindSignature`]s for quote + async fn get_blind_signatures_for_quote( + &self, + quote_id: &Uuid, + ) -> Result, Self::Err>; +} diff --git a/crates/cdk-common/src/database/mod.rs b/crates/cdk-common/src/database/mod.rs new file mode 100644 index 000000000..f9a0e5cac --- /dev/null +++ b/crates/cdk-common/src/database/mod.rs @@ -0,0 +1,34 @@ +//! CDK Database + +#[cfg(feature = "mint")] +mod mint; +#[cfg(feature = "wallet")] +mod wallet; + +#[cfg(feature = "mint")] +pub use mint::Database as MintDatabase; +#[cfg(feature = "wallet")] +pub use wallet::Database as WalletDatabase; + +/// CDK_database error +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Database Error + #[error(transparent)] + Database(Box), + /// DHKE error + #[error(transparent)] + DHKE(#[from] crate::dhke::Error), + /// NUT00 Error + #[error(transparent)] + NUT00(#[from] crate::nuts::nut00::Error), + /// NUT02 Error + #[error(transparent)] + NUT02(#[from] crate::nuts::nut02::Error), + /// Serde Error + #[error(transparent)] + Serde(#[from] serde_json::Error), + /// Unknown Quote + #[error("Unknown Quote")] + UnknownQuote, +} diff --git a/crates/cdk-common/src/database/wallet.rs b/crates/cdk-common/src/database/wallet.rs new file mode 100644 index 000000000..e9213a1e3 --- /dev/null +++ b/crates/cdk-common/src/database/wallet.rs @@ -0,0 +1,120 @@ +//! CDK Database + +use std::collections::HashMap; +use std::fmt::Debug; + +use async_trait::async_trait; + +use super::Error; +use crate::common::ProofInfo; +use crate::mint_url::MintUrl; +use crate::nuts::{ + CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State, +}; +use crate::wallet; +use crate::wallet::MintQuote as WalletMintQuote; + +/// Wallet Database trait +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait Database: Debug { + /// Wallet Database Error + type Err: Into + From; + + /// Add Mint to storage + async fn add_mint( + &self, + mint_url: MintUrl, + mint_info: Option, + ) -> Result<(), Self::Err>; + /// Remove Mint from storage + async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), Self::Err>; + /// Get mint from storage + async fn get_mint(&self, mint_url: MintUrl) -> Result, Self::Err>; + /// Get all mints from storage + async fn get_mints(&self) -> Result>, Self::Err>; + /// Update mint url + async fn update_mint_url( + &self, + old_mint_url: MintUrl, + new_mint_url: MintUrl, + ) -> Result<(), Self::Err>; + + /// Add mint keyset to storage + async fn add_mint_keysets( + &self, + mint_url: MintUrl, + keysets: Vec, + ) -> Result<(), Self::Err>; + /// Get mint keysets for mint url + async fn get_mint_keysets( + &self, + mint_url: MintUrl, + ) -> Result>, Self::Err>; + /// Get mint keyset by id + async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result, Self::Err>; + + /// Add mint quote to storage + async fn add_mint_quote(&self, quote: WalletMintQuote) -> Result<(), Self::Err>; + /// Get mint quote from storage + async fn get_mint_quote(&self, quote_id: &str) -> Result, Self::Err>; + /// Get mint quotes from storage + async fn get_mint_quotes(&self) -> Result, Self::Err>; + /// Remove mint quote from storage + async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err>; + + /// Add melt quote to storage + async fn add_melt_quote(&self, quote: wallet::MeltQuote) -> Result<(), Self::Err>; + /// Get melt quote from storage + async fn get_melt_quote(&self, quote_id: &str) -> Result, Self::Err>; + /// Remove melt quote from storage + async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err>; + + /// Add [`Keys`] to storage + async fn add_keys(&self, keys: Keys) -> Result<(), Self::Err>; + /// Get [`Keys`] from storage + async fn get_keys(&self, id: &Id) -> Result, Self::Err>; + /// Remove [`Keys`] from storage + async fn remove_keys(&self, id: &Id) -> Result<(), Self::Err>; + + /// Update the proofs in storage by adding new proofs or removing proofs by + /// their Y value. + async fn update_proofs( + &self, + added: Vec, + removed_ys: Vec, + ) -> Result<(), Self::Err>; + /// Set proofs as pending in storage. Proofs are identified by their Y + /// value. + async fn set_pending_proofs(&self, ys: Vec) -> Result<(), Self::Err>; + /// Reserve proofs in storage. Proofs are identified by their Y value. + async fn reserve_proofs(&self, ys: Vec) -> Result<(), Self::Err>; + /// Set proofs as unspent in storage. Proofs are identified by their Y + /// value. + async fn set_unspent_proofs(&self, ys: Vec) -> Result<(), Self::Err>; + /// Get proofs from storage + async fn get_proofs( + &self, + mint_url: Option, + unit: Option, + state: Option>, + spending_conditions: Option>, + ) -> Result, Self::Err>; + + /// Increment Keyset counter + async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err>; + /// Get current Keyset counter + async fn get_keyset_counter(&self, keyset_id: &Id) -> Result, Self::Err>; + + /// Get when nostr key was last checked + async fn get_nostr_last_checked( + &self, + verifying_key: &PublicKey, + ) -> Result, Self::Err>; + /// Update last checked time + async fn add_nostr_last_checked( + &self, + verifying_key: PublicKey, + last_checked: u32, + ) -> Result<(), Self::Err>; +} diff --git a/crates/cdk-common/src/error.rs b/crates/cdk-common/src/error.rs index e0054d456..eef8f7b21 100644 --- a/crates/cdk-common/src/error.rs +++ b/crates/cdk-common/src/error.rs @@ -8,6 +8,7 @@ use thiserror::Error; use crate::nuts::Id; use crate::util::hex; +#[cfg(feature = "wallet")] use crate::wallet::WalletKey; use crate::Amount; @@ -128,6 +129,7 @@ pub enum Error { IncorrectWallet(String), /// Unknown Wallet #[error("Unknown wallet: `{0}`")] + #[cfg(feature = "wallet")] UnknownWallet(WalletKey), /// Max Fee Ecxeded #[error("Max fee exceeded")] @@ -250,6 +252,7 @@ pub enum Error { Database(#[from] crate::database::Error), /// Lightning Error #[error(transparent)] + #[cfg(feature = "mint")] Lightning(#[from] crate::lightning::Error), } diff --git a/crates/cdk-common/src/lib.rs b/crates/cdk-common/src/lib.rs index 93d0add85..f7450d7a1 100644 --- a/crates/cdk-common/src/lib.rs +++ b/crates/cdk-common/src/lib.rs @@ -9,15 +9,20 @@ pub mod common; pub mod database; pub mod error; +#[cfg(feature = "mint")] pub mod lightning; pub mod pub_sub; +#[cfg(feature = "mint")] pub mod subscription; -pub mod wallet; pub mod ws; // re-exporting external crates pub use cashu::amount::{self, Amount}; pub use cashu::lightning_invoice::{self, Bolt11Invoice}; +#[cfg(feature = "mint")] +pub use cashu::mint; pub use cashu::nuts::{self, *}; -pub use cashu::{dhke, mint, mint_url, secret, util, SECP256K1}; +#[cfg(feature = "wallet")] +pub use cashu::wallet; +pub use cashu::{dhke, mint_url, secret, util, SECP256K1}; pub use {bitcoin, reqwest}; diff --git a/crates/cdk/Cargo.toml b/crates/cdk/Cargo.toml index 4d023221a..589c98e05 100644 --- a/crates/cdk/Cargo.toml +++ b/crates/cdk/Cargo.toml @@ -12,10 +12,10 @@ license = "MIT" [features] default = ["mint", "wallet"] -mint = ["dep:futures"] +mint = ["dep:futures", "cdk-common/mint"] # We do not commit to a MSRV with swagger enabled swagger = ["mint", "dep:utoipa", "cdk-common/swagger"] -wallet = ["dep:reqwest"] +wallet = ["dep:reqwest", "cdk-common/wallet"] bench = [] http_subscription = []