split MintDatabase into separate narrower scoped traits

- MintKeysDatabase
- MintQuotesDatabase
- MintProofsDatabase
- MintSignaturesDatabase

This commit splits the MintDatabase trait with 30+ methods into a series
of smaller traits, each dedicate to a specific subsystem of the mint
service.
This commit is contained in:
codingpeanut157
2025-03-26 16:48:41 +01:00
parent 7b4951041e
commit 47903c3bfd
12 changed files with 301 additions and 227 deletions

View File

@@ -20,10 +20,10 @@ mod auth;
#[cfg(feature = "auth")] #[cfg(feature = "auth")]
pub use auth::MintAuthDatabase; pub use auth::MintAuthDatabase;
/// Mint Database trait /// Mint Keys Database trait
#[async_trait] #[async_trait]
pub trait Database { pub trait KeysDatabase {
/// Mint Database Error /// Mint Keys Database Error
type Err: Into<Error> + From<Error>; type Err: Into<Error> + From<Error>;
/// Add Active Keyset /// Add Active Keyset
@@ -32,6 +32,18 @@ pub trait Database {
async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err>; async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err>;
/// Get all Active Keyset /// Get all Active Keyset
async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err>; async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, 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<Option<MintKeySetInfo>, Self::Err>;
/// Get [`MintKeySetInfo`]s
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
}
/// Mint Quote Database trait
#[async_trait]
pub trait QuotesDatabase {
/// Mint Quotes Database Error
type Err: Into<Error> + From<Error>;
/// Add [`MintMintQuote`] /// Add [`MintMintQuote`]
async fn add_mint_quote(&self, quote: MintMintQuote) -> Result<(), Self::Err>; async fn add_mint_quote(&self, quote: MintMintQuote) -> Result<(), Self::Err>;
@@ -89,13 +101,13 @@ pub trait Database {
&self, &self,
quote_id: &Uuid, quote_id: &Uuid,
) -> Result<Option<(MeltBolt11Request<Uuid>, PaymentProcessorKey)>, Self::Err>; ) -> Result<Option<(MeltBolt11Request<Uuid>, PaymentProcessorKey)>, Self::Err>;
}
/// Add [`MintKeySetInfo`] /// Mint Proof Database trait
async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err>; #[async_trait]
/// Get [`MintKeySetInfo`] pub trait ProofsDatabase {
async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err>; /// Mint Proof Database Error
/// Get [`MintKeySetInfo`]s type Err: Into<Error> + From<Error>;
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
/// Add [`Proofs`] /// Add [`Proofs`]
async fn add_proofs(&self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>; async fn add_proofs(&self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>;
@@ -122,6 +134,13 @@ pub trait Database {
&self, &self,
keyset_id: &Id, keyset_id: &Id,
) -> Result<(Proofs, Vec<Option<State>>), Self::Err>; ) -> Result<(Proofs, Vec<Option<State>>), Self::Err>;
}
#[async_trait]
/// Mint Signatures Database trait
pub trait SignaturesDatabase {
/// Mint Signature Database Error
type Err: Into<Error> + From<Error>;
/// Add [`BlindSignature`] /// Add [`BlindSignature`]
async fn add_blind_signatures( async fn add_blind_signatures(
@@ -145,14 +164,23 @@ pub trait Database {
&self, &self,
quote_id: &Uuid, quote_id: &Uuid,
) -> Result<Vec<BlindSignature>, Self::Err>; ) -> Result<Vec<BlindSignature>, Self::Err>;
}
/// Mint Database trait
#[async_trait]
pub trait Database<Error>:
KeysDatabase<Err = Error>
+ QuotesDatabase<Err = Error>
+ ProofsDatabase<Err = Error>
+ SignaturesDatabase<Err = Error>
{
/// Set [`MintInfo`] /// Set [`MintInfo`]
async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err>; async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Error>;
/// Get [`MintInfo`] /// Get [`MintInfo`]
async fn get_mint_info(&self) -> Result<MintInfo, Self::Err>; async fn get_mint_info(&self) -> Result<MintInfo, Error>;
/// Set [`QuoteTTL`] /// Set [`QuoteTTL`]
async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err>; async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Error>;
/// Get [`QuoteTTL`] /// Get [`QuoteTTL`]
async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err>; async fn get_quote_ttl(&self) -> Result<QuoteTTL, Error>;
} }

View File

@@ -5,10 +5,14 @@ mod mint;
#[cfg(feature = "wallet")] #[cfg(feature = "wallet")]
mod wallet; mod wallet;
#[cfg(feature = "mint")]
pub use mint::Database as MintDatabase;
#[cfg(all(feature = "mint", feature = "auth"))] #[cfg(all(feature = "mint", feature = "auth"))]
pub use mint::MintAuthDatabase; pub use mint::MintAuthDatabase;
#[cfg(feature = "mint")]
pub use mint::{
Database as MintDatabase, KeysDatabase as MintKeysDatabase,
ProofsDatabase as MintProofsDatabase, QuotesDatabase as MintQuotesDatabase,
SignaturesDatabase as MintSignaturesDatabase,
};
#[cfg(feature = "wallet")] #[cfg(feature = "wallet")]
pub use wallet::Database as WalletDatabase; pub use wallet::Database as WalletDatabase;

View File

@@ -19,7 +19,7 @@ pub async fn start_fake_mint_with_auth<D, A>(
auth_database: A, auth_database: A,
) -> Result<()> ) -> Result<()>
where where
D: MintDatabase<Err = cdk_database::Error> + Send + Sync + 'static, D: MintDatabase<cdk_database::Error> + Send + Sync + 'static,
A: MintAuthDatabase<Err = cdk_database::Error> + Send + Sync + 'static, A: MintAuthDatabase<Err = cdk_database::Error> + Send + Sync + 'static,
{ {
let fee_reserve = FeeReserve { let fee_reserve = FeeReserve {

View File

@@ -121,7 +121,7 @@ async fn main() -> anyhow::Result<()> {
// ENV VARS will take **priority** over those in the config // ENV VARS will take **priority** over those in the config
let settings = settings.from_env()?; let settings = settings.from_env()?;
let localstore: Arc<dyn MintDatabase<Err = cdk_database::Error> + Send + Sync> = let localstore: Arc<dyn MintDatabase<cdk_database::Error> + Send + Sync> =
match settings.database.engine { match settings.database.engine {
DatabaseEngine::Sqlite => { DatabaseEngine::Sqlite => {
let sql_db_path = work_dir.join("cdk-mintd.sqlite"); let sql_db_path = work_dir.join("cdk-mintd.sqlite");

View File

@@ -8,7 +8,10 @@ use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use cdk_common::common::{PaymentProcessorKey, QuoteTTL}; use cdk_common::common::{PaymentProcessorKey, QuoteTTL};
use cdk_common::database::{self, MintDatabase}; use cdk_common::database::{
self, MintDatabase, MintKeysDatabase, MintProofsDatabase, MintQuotesDatabase,
MintSignaturesDatabase,
};
use cdk_common::dhke::hash_to_curve; use cdk_common::dhke::hash_to_curve;
use cdk_common::mint::{self, MintKeySetInfo, MintQuote}; use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
use cdk_common::nut00::ProofsMethods; use cdk_common::nut00::ProofsMethods;
@@ -165,7 +168,7 @@ impl MintRedbDatabase {
} }
#[async_trait] #[async_trait]
impl MintDatabase for MintRedbDatabase { impl MintKeysDatabase for MintRedbDatabase {
type Err = database::Error; type Err = database::Error;
async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> { async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> {
@@ -261,6 +264,11 @@ impl MintDatabase for MintRedbDatabase {
Ok(keysets) Ok(keysets)
} }
}
#[async_trait]
impl MintQuotesDatabase for MintRedbDatabase {
type Err = database::Error;
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> { async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
let write_txn = self.db.begin_write().map_err(Error::from)?; let write_txn = self.db.begin_write().map_err(Error::from)?;
@@ -524,6 +532,52 @@ impl MintDatabase for MintRedbDatabase {
Ok(()) Ok(())
} }
/// Add melt request
async fn add_melt_request(
&self,
melt_request: MeltBolt11Request<Uuid>,
ln_key: PaymentProcessorKey,
) -> Result<(), Self::Err> {
let write_txn = self.db.begin_write().map_err(Error::from)?;
let mut table = write_txn.open_table(MELT_REQUESTS).map_err(Error::from)?;
table
.insert(
melt_request.quote.as_bytes(),
(
serde_json::to_string(&melt_request)?.as_str(),
serde_json::to_string(&ln_key)?.as_str(),
),
)
.map_err(Error::from)?;
Ok(())
}
/// Get melt request
async fn get_melt_request(
&self,
quote_id: &Uuid,
) -> Result<Option<(MeltBolt11Request<Uuid>, PaymentProcessorKey)>, Self::Err> {
let read_txn = self.db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(MELT_REQUESTS).map_err(Error::from)?;
match table.get(quote_id.as_bytes()).map_err(Error::from)? {
Some(melt_request) => {
let (melt_request_str, ln_key_str) = melt_request.value();
let melt_request = serde_json::from_str(melt_request_str)?;
let ln_key = serde_json::from_str(ln_key_str)?;
Ok(Some((melt_request, ln_key)))
}
None => Ok(None),
}
}
}
#[async_trait]
impl MintProofsDatabase for MintRedbDatabase {
type Err = database::Error;
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err> { async fn add_proofs(&self, proofs: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err> {
let write_txn = self.db.begin_write().map_err(Error::from)?; let write_txn = self.db.begin_write().map_err(Error::from)?;
@@ -745,6 +799,11 @@ impl MintDatabase for MintRedbDatabase {
Ok(states) Ok(states)
} }
}
#[async_trait]
impl MintSignaturesDatabase for MintRedbDatabase {
type Err = database::Error;
async fn add_blind_signatures( async fn add_blind_signatures(
&self, &self,
@@ -827,47 +886,6 @@ impl MintDatabase for MintRedbDatabase {
.collect()) .collect())
} }
/// Add melt request
async fn add_melt_request(
&self,
melt_request: MeltBolt11Request<Uuid>,
ln_key: PaymentProcessorKey,
) -> Result<(), Self::Err> {
let write_txn = self.db.begin_write().map_err(Error::from)?;
let mut table = write_txn.open_table(MELT_REQUESTS).map_err(Error::from)?;
table
.insert(
melt_request.quote.as_bytes(),
(
serde_json::to_string(&melt_request)?.as_str(),
serde_json::to_string(&ln_key)?.as_str(),
),
)
.map_err(Error::from)?;
Ok(())
}
/// Get melt request
async fn get_melt_request(
&self,
quote_id: &Uuid,
) -> Result<Option<(MeltBolt11Request<Uuid>, PaymentProcessorKey)>, Self::Err> {
let read_txn = self.db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(MELT_REQUESTS).map_err(Error::from)?;
match table.get(quote_id.as_bytes()).map_err(Error::from)? {
Some(melt_request) => {
let (melt_request_str, ln_key_str) = melt_request.value();
let melt_request = serde_json::from_str(melt_request_str)?;
let ln_key = serde_json::from_str(ln_key_str)?;
Ok(Some((melt_request, ln_key)))
}
None => Ok(None),
}
}
/// Get [`BlindSignature`]s for quote /// Get [`BlindSignature`]s for quote
async fn get_blind_signatures_for_quote( async fn get_blind_signatures_for_quote(
&self, &self,
@@ -897,8 +915,11 @@ impl MintDatabase for MintRedbDatabase {
Ok(signatures) Ok(signatures)
} }
}
async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err> { #[async_trait]
impl MintDatabase<database::Error> for MintRedbDatabase {
async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), database::Error> {
let write_txn = self.db.begin_write().map_err(Error::from)?; let write_txn = self.db.begin_write().map_err(Error::from)?;
{ {
@@ -911,7 +932,7 @@ impl MintDatabase for MintRedbDatabase {
Ok(()) Ok(())
} }
async fn get_mint_info(&self) -> Result<MintInfo, Self::Err> { async fn get_mint_info(&self) -> Result<MintInfo, database::Error> {
let read_txn = self.db.begin_read().map_err(Error::from)?; let read_txn = self.db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(CONFIG_TABLE).map_err(Error::from)?; let table = read_txn.open_table(CONFIG_TABLE).map_err(Error::from)?;
@@ -924,7 +945,7 @@ impl MintDatabase for MintRedbDatabase {
Err(Error::UnknownMintInfo.into()) Err(Error::UnknownMintInfo.into())
} }
async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> { async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), database::Error> {
let write_txn = self.db.begin_write().map_err(Error::from)?; let write_txn = self.db.begin_write().map_err(Error::from)?;
{ {
@@ -937,7 +958,7 @@ impl MintDatabase for MintRedbDatabase {
Ok(()) Ok(())
} }
async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err> { async fn get_quote_ttl(&self) -> Result<QuoteTTL, database::Error> {
let read_txn = self.db.begin_read().map_err(Error::from)?; let read_txn = self.db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(CONFIG_TABLE).map_err(Error::from)?; let table = read_txn.open_table(CONFIG_TABLE).map_err(Error::from)?;

View File

@@ -2,7 +2,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use cdk_common::common::PaymentProcessorKey; use cdk_common::common::PaymentProcessorKey;
use cdk_common::database::{self, MintDatabase}; use cdk_common::database::{
self, MintDatabase, MintKeysDatabase, MintProofsDatabase, MintQuotesDatabase,
};
use cdk_common::mint::{self, MintKeySetInfo, MintQuote}; use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
use cdk_common::nuts::{CurrencyUnit, Id, MeltBolt11Request, Proofs}; use cdk_common::nuts::{CurrencyUnit, Id, MeltBolt11Request, Proofs};
use cdk_common::MintInfo; use cdk_common::MintInfo;

View File

@@ -7,7 +7,10 @@ use std::str::FromStr;
use async_trait::async_trait; use async_trait::async_trait;
use bitcoin::bip32::DerivationPath; use bitcoin::bip32::DerivationPath;
use cdk_common::common::{PaymentProcessorKey, QuoteTTL}; use cdk_common::common::{PaymentProcessorKey, QuoteTTL};
use cdk_common::database::{self, MintDatabase}; use cdk_common::database::{
self, MintDatabase, MintKeysDatabase, MintProofsDatabase, MintQuotesDatabase,
MintSignaturesDatabase,
};
use cdk_common::mint::{self, MintKeySetInfo, MintQuote}; use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
use cdk_common::nut00::ProofsMethods; use cdk_common::nut00::ProofsMethods;
use cdk_common::nut05::QuoteState; use cdk_common::nut05::QuoteState;
@@ -105,7 +108,7 @@ impl MintSqliteDatabase {
} }
#[async_trait] #[async_trait]
impl MintDatabase for MintSqliteDatabase { impl MintKeysDatabase for MintSqliteDatabase {
type Err = database::Error; type Err = database::Error;
async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> { async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> {
@@ -244,6 +247,121 @@ WHERE active = 1
} }
} }
async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let res = sqlx::query(
r#"
INSERT INTO keyset
(id, unit, active, valid_from, valid_to, derivation_path, max_order, input_fee_ppk, derivation_path_index)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
unit = excluded.unit,
active = excluded.active,
valid_from = excluded.valid_from,
valid_to = excluded.valid_to,
derivation_path = excluded.derivation_path,
max_order = excluded.max_order,
input_fee_ppk = excluded.input_fee_ppk,
derivation_path_index = excluded.derivation_path_index
"#,
)
.bind(keyset.id.to_string())
.bind(keyset.unit.to_string())
.bind(keyset.active)
.bind(keyset.valid_from as i64)
.bind(keyset.valid_to.map(|v| v as i64))
.bind(keyset.derivation_path.to_string())
.bind(keyset.max_order)
.bind(keyset.input_fee_ppk as i64)
.bind(keyset.derivation_path_index)
.execute(&mut *transaction)
.await;
match res {
Ok(_) => {
transaction.commit().await.map_err(Error::from)?;
Ok(())
}
Err(err) => {
tracing::error!("SQLite could not add keyset info");
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
Err(Error::from(err).into())
}
}
}
async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let rec = sqlx::query(
r#"
SELECT *
FROM keyset
WHERE id=?;
"#,
)
.bind(id.to_string())
.fetch_one(&mut *transaction)
.await;
match rec {
Ok(rec) => {
transaction.commit().await.map_err(Error::from)?;
Ok(Some(sqlite_row_to_keyset_info(rec)?))
}
Err(err) => match err {
sqlx::Error::RowNotFound => {
transaction.commit().await.map_err(Error::from)?;
return Ok(None);
}
_ => {
tracing::error!("SQLite could not get keyset info");
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
return Err(Error::SQLX(err).into());
}
},
}
}
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let recs = sqlx::query(
r#"
SELECT *
FROM keyset;
"#,
)
.fetch_all(&mut *transaction)
.await
.map_err(Error::from);
match recs {
Ok(recs) => {
transaction.commit().await.map_err(Error::from)?;
Ok(recs
.into_iter()
.map(sqlite_row_to_keyset_info)
.collect::<Result<_, _>>()?)
}
Err(err) => {
tracing::error!("SQLite could not get keyset info");
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
Err(err.into())
}
}
}
}
#[async_trait]
impl MintQuotesDatabase for MintSqliteDatabase {
type Err = database::Error;
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> { async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
@@ -763,33 +881,30 @@ WHERE id=?
} }
} }
async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> { async fn add_melt_request(
&self,
melt_request: MeltBolt11Request<Uuid>,
ln_key: PaymentProcessorKey,
) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let res = sqlx::query( let res = sqlx::query(
r#" r#"
INSERT INTO keyset INSERT INTO melt_request
(id, unit, active, valid_from, valid_to, derivation_path, max_order, input_fee_ppk, derivation_path_index) (id, inputs, outputs, method, unit)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET ON CONFLICT(id) DO UPDATE SET
unit = excluded.unit, inputs = excluded.inputs,
active = excluded.active, outputs = excluded.outputs,
valid_from = excluded.valid_from, method = excluded.method,
valid_to = excluded.valid_to, unit = excluded.unit
derivation_path = excluded.derivation_path,
max_order = excluded.max_order,
input_fee_ppk = excluded.input_fee_ppk,
derivation_path_index = excluded.derivation_path_index
"#, "#,
) )
.bind(keyset.id.to_string()) .bind(melt_request.quote)
.bind(keyset.unit.to_string()) .bind(serde_json::to_string(&melt_request.inputs)?)
.bind(keyset.active) .bind(serde_json::to_string(&melt_request.outputs)?)
.bind(keyset.valid_from as i64) .bind(ln_key.method.to_string())
.bind(keyset.valid_to.map(|v| v as i64)) .bind(ln_key.unit.to_string())
.bind(keyset.derivation_path.to_string())
.bind(keyset.max_order)
.bind(keyset.input_fee_ppk as i64)
.bind(keyset.derivation_path_index)
.execute(&mut *transaction) .execute(&mut *transaction)
.await; .await;
@@ -799,7 +914,7 @@ ON CONFLICT(id) DO UPDATE SET
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
tracing::error!("SQLite could not add keyset info"); tracing::error!("SQLite Could not update keyset");
if let Err(err) = transaction.rollback().await { if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err); tracing::error!("Could not rollback sql transaction: {}", err);
} }
@@ -809,23 +924,30 @@ ON CONFLICT(id) DO UPDATE SET
} }
} }
async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err> { async fn get_melt_request(
&self,
quote_id: &Uuid,
) -> Result<Option<(MeltBolt11Request<Uuid>, PaymentProcessorKey)>, Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let rec = sqlx::query( let rec = sqlx::query(
r#" r#"
SELECT * SELECT *
FROM keyset FROM melt_request
WHERE id=?; WHERE id=?;
"#, "#,
) )
.bind(id.to_string()) .bind(quote_id.as_hyphenated())
.fetch_one(&mut *transaction) .fetch_one(&mut *transaction)
.await; .await;
match rec { match rec {
Ok(rec) => { Ok(rec) => {
transaction.commit().await.map_err(Error::from)?; transaction.commit().await.map_err(Error::from)?;
Ok(Some(sqlite_row_to_keyset_info(rec)?))
let (request, key) = sqlite_row_to_melt_request(rec)?;
Ok(Some((request, key)))
} }
Err(err) => match err { Err(err) => match err {
sqlx::Error::RowNotFound => { sqlx::Error::RowNotFound => {
@@ -833,45 +955,21 @@ WHERE id=?;
return Ok(None); return Ok(None);
} }
_ => { _ => {
tracing::error!("SQLite could not get keyset info"); return {
if let Err(err) = transaction.rollback().await { if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err); tracing::error!("Could not rollback sql transaction: {}", err);
} }
return Err(Error::SQLX(err).into()); Err(Error::SQLX(err).into())
}
} }
}, },
} }
} }
}
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err> { #[async_trait]
let mut transaction = self.pool.begin().await.map_err(Error::from)?; impl MintProofsDatabase for MintSqliteDatabase {
let recs = sqlx::query( type Err = database::Error;
r#"
SELECT *
FROM keyset;
"#,
)
.fetch_all(&mut *transaction)
.await
.map_err(Error::from);
match recs {
Ok(recs) => {
transaction.commit().await.map_err(Error::from)?;
Ok(recs
.into_iter()
.map(sqlite_row_to_keyset_info)
.collect::<Result<_, _>>()?)
}
Err(err) => {
tracing::error!("SQLite could not get keyset info");
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
Err(err.into())
}
}
}
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err> { async fn add_proofs(&self, proofs: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
@@ -1176,6 +1274,11 @@ WHERE keyset_id=?;
Ok(ys.iter().map(|y| current_states.remove(y)).collect()) Ok(ys.iter().map(|y| current_states.remove(y)).collect())
} }
}
#[async_trait]
impl MintSignaturesDatabase for MintSqliteDatabase {
type Err = database::Error;
async fn add_blind_signatures( async fn add_blind_signatures(
&self, &self,
@@ -1290,91 +1393,6 @@ WHERE keyset_id=?;
} }
} }
async fn add_melt_request(
&self,
melt_request: MeltBolt11Request<Uuid>,
ln_key: PaymentProcessorKey,
) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let res = sqlx::query(
r#"
INSERT INTO melt_request
(id, inputs, outputs, method, unit)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
inputs = excluded.inputs,
outputs = excluded.outputs,
method = excluded.method,
unit = excluded.unit
"#,
)
.bind(melt_request.quote)
.bind(serde_json::to_string(&melt_request.inputs)?)
.bind(serde_json::to_string(&melt_request.outputs)?)
.bind(ln_key.method.to_string())
.bind(ln_key.unit.to_string())
.execute(&mut *transaction)
.await;
match res {
Ok(_) => {
transaction.commit().await.map_err(Error::from)?;
Ok(())
}
Err(err) => {
tracing::error!("SQLite Could not update keyset");
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
Err(Error::from(err).into())
}
}
}
async fn get_melt_request(
&self,
quote_id: &Uuid,
) -> Result<Option<(MeltBolt11Request<Uuid>, PaymentProcessorKey)>, Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let rec = sqlx::query(
r#"
SELECT *
FROM melt_request
WHERE id=?;
"#,
)
.bind(quote_id.as_hyphenated())
.fetch_one(&mut *transaction)
.await;
match rec {
Ok(rec) => {
transaction.commit().await.map_err(Error::from)?;
let (request, key) = sqlite_row_to_melt_request(rec)?;
Ok(Some((request, key)))
}
Err(err) => match err {
sqlx::Error::RowNotFound => {
transaction.commit().await.map_err(Error::from)?;
return Ok(None);
}
_ => {
return {
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
Err(Error::SQLX(err).into())
}
}
},
}
}
/// Get [`BlindSignature`]s for quote /// Get [`BlindSignature`]s for quote
async fn get_blind_signatures_for_quote( async fn get_blind_signatures_for_quote(
&self, &self,
@@ -1412,8 +1430,11 @@ WHERE quote_id=?;
} }
} }
} }
}
async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err> { #[async_trait]
impl MintDatabase<database::Error> for MintSqliteDatabase {
async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), database::Error> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let res = sqlx::query( let res = sqlx::query(
@@ -1446,7 +1467,7 @@ ON CONFLICT(id) DO UPDATE SET
} }
} }
} }
async fn get_mint_info(&self) -> Result<MintInfo, Self::Err> { async fn get_mint_info(&self) -> Result<MintInfo, database::Error> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let rec = sqlx::query( let rec = sqlx::query(
@@ -1487,7 +1508,7 @@ WHERE id=?;
} }
} }
async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> { async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), database::Error> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let res = sqlx::query( let res = sqlx::query(
@@ -1520,7 +1541,7 @@ ON CONFLICT(id) DO UPDATE SET
} }
} }
} }
async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err> { async fn get_quote_ttl(&self) -> Result<QuoteTTL, database::Error> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?; let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let rec = sqlx::query( let rec = sqlx::query(

View File

@@ -32,7 +32,7 @@ pub struct MintBuilder {
/// Mint Info /// Mint Info
pub mint_info: MintInfo, pub mint_info: MintInfo,
/// Mint Storage backend /// Mint Storage backend
localstore: Option<Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>>, localstore: Option<Arc<dyn MintDatabase<database::Error> + Send + Sync>>,
/// Mint Storage backend /// Mint Storage backend
#[cfg(feature = "auth")] #[cfg(feature = "auth")]
auth_localstore: Option<Arc<dyn MintAuthDatabase<Err = cdk_database::Error> + Send + Sync>>, auth_localstore: Option<Arc<dyn MintAuthDatabase<Err = cdk_database::Error> + Send + Sync>>,
@@ -70,7 +70,7 @@ impl MintBuilder {
/// Set localstore /// Set localstore
pub fn with_localstore( pub fn with_localstore(
mut self, mut self,
localstore: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>, localstore: Arc<dyn MintDatabase<database::Error> + Send + Sync>,
) -> MintBuilder { ) -> MintBuilder {
self.localstore = Some(localstore); self.localstore = Some(localstore);
self self

View File

@@ -23,7 +23,7 @@ impl Mint {
pub async fn init_keysets( pub async fn init_keysets(
xpriv: Xpriv, xpriv: Xpriv,
secp_ctx: &Secp256k1<All>, secp_ctx: &Secp256k1<All>,
localstore: &Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>, localstore: &Arc<dyn MintDatabase<database::Error> + Send + Sync>,
supported_units: &HashMap<CurrencyUnit, (u64, u8)>, supported_units: &HashMap<CurrencyUnit, (u64, u8)>,
custom_paths: &HashMap<CurrencyUnit, DerivationPath>, custom_paths: &HashMap<CurrencyUnit, DerivationPath>,
) -> Result<(HashMap<Id, MintKeySet>, Vec<CurrencyUnit>), Error> { ) -> Result<(HashMap<Id, MintKeySet>, Vec<CurrencyUnit>), Error> {

View File

@@ -49,7 +49,7 @@ pub use verification::Verification;
#[derive(Clone)] #[derive(Clone)]
pub struct Mint { pub struct Mint {
/// Mint Storage backend /// Mint Storage backend
pub localstore: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>, pub localstore: Arc<dyn MintDatabase<database::Error> + Send + Sync>,
/// Auth Storage backend (only available with auth feature) /// Auth Storage backend (only available with auth feature)
#[cfg(feature = "auth")] #[cfg(feature = "auth")]
pub auth_localstore: Option<Arc<dyn MintAuthDatabase<Err = database::Error> + Send + Sync>>, pub auth_localstore: Option<Arc<dyn MintAuthDatabase<Err = database::Error> + Send + Sync>>,
@@ -70,7 +70,7 @@ impl Mint {
/// Create new [`Mint`] without authentication /// Create new [`Mint`] without authentication
pub async fn new( pub async fn new(
seed: &[u8], seed: &[u8],
localstore: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>, localstore: Arc<dyn MintDatabase<database::Error> + Send + Sync>,
ln: HashMap< ln: HashMap<
PaymentProcessorKey, PaymentProcessorKey,
Arc<dyn MintPayment<Err = cdk_payment::Error> + Send + Sync>, Arc<dyn MintPayment<Err = cdk_payment::Error> + Send + Sync>,
@@ -96,7 +96,7 @@ impl Mint {
#[cfg(feature = "auth")] #[cfg(feature = "auth")]
pub async fn new_with_auth( pub async fn new_with_auth(
seed: &[u8], seed: &[u8],
localstore: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>, localstore: Arc<dyn MintDatabase<database::Error> + Send + Sync>,
auth_localstore: Arc<dyn MintAuthDatabase<Err = database::Error> + Send + Sync>, auth_localstore: Arc<dyn MintAuthDatabase<Err = database::Error> + Send + Sync>,
ln: HashMap< ln: HashMap<
PaymentProcessorKey, PaymentProcessorKey,
@@ -121,7 +121,7 @@ impl Mint {
/// Internal function to create a new [`Mint`] with shared logic /// Internal function to create a new [`Mint`] with shared logic
async fn new_internal( async fn new_internal(
seed: &[u8], seed: &[u8],
localstore: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>, localstore: Arc<dyn MintDatabase<database::Error> + Send + Sync>,
#[cfg(feature = "auth")] auth_localstore: Option< #[cfg(feature = "auth")] auth_localstore: Option<
Arc<dyn database::MintAuthDatabase<Err = database::Error> + Send + Sync>, Arc<dyn database::MintAuthDatabase<Err = database::Error> + Send + Sync>,
>, >,

View File

@@ -28,8 +28,8 @@ impl Default for PubSubManager {
} }
} }
impl From<Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>> for PubSubManager { impl From<Arc<dyn MintDatabase<database::Error> + Send + Sync>> for PubSubManager {
fn from(val: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>) -> Self { fn from(val: Arc<dyn MintDatabase<database::Error> + Send + Sync>) -> Self {
PubSubManager(OnSubscription(Some(val)).into()) PubSubManager(OnSubscription(Some(val)).into())
} }
} }

View File

@@ -17,9 +17,7 @@ use crate::nuts::{MeltQuoteBolt11Response, MintQuoteBolt11Response, ProofState,
/// This struct triggers code when a new subscription is created. /// This struct triggers code when a new subscription is created.
/// ///
/// It is used to send the initial state of the subscription to the client. /// It is used to send the initial state of the subscription to the client.
pub struct OnSubscription( pub struct OnSubscription(pub(crate) Option<Arc<dyn MintDatabase<database::Error> + Send + Sync>>);
pub(crate) Option<Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>>,
);
#[async_trait::async_trait] #[async_trait::async_trait]
impl OnNewSubscription for OnSubscription { impl OnNewSubscription for OnSubscription {