mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-23 15:44:50 +01:00
feat: use Uuid as mint and melt quote ids (#469)
This commit is contained in:
committed by
GitHub
parent
5ad4328a4e
commit
7d87c4806c
@@ -29,6 +29,7 @@ moka = { version = "0.11.1", features = ["future"] }
|
|||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
serde = { version = "1.0.210", features = ["derive"] }
|
serde = { version = "1.0.210", features = ["derive"] }
|
||||||
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
swagger = ["cdk/swagger", "dep:utoipa"]
|
swagger = ["cdk/swagger", "dep:utoipa"]
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ mod swagger_imports {
|
|||||||
|
|
||||||
#[cfg(feature = "swagger")]
|
#[cfg(feature = "swagger")]
|
||||||
use swagger_imports::*;
|
use swagger_imports::*;
|
||||||
|
#[cfg(feature = "swagger")]
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// CDK Mint State
|
/// CDK Mint State
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -75,16 +77,16 @@ pub struct MintState {
|
|||||||
KeySet,
|
KeySet,
|
||||||
KeySetInfo,
|
KeySetInfo,
|
||||||
KeySetVersion,
|
KeySetVersion,
|
||||||
MeltBolt11Request,
|
MeltBolt11Request<Uuid>,
|
||||||
MeltQuoteBolt11Request,
|
MeltQuoteBolt11Request,
|
||||||
MeltQuoteBolt11Response,
|
MeltQuoteBolt11Response<Uuid>,
|
||||||
MeltQuoteState,
|
MeltQuoteState,
|
||||||
MeltMethodSettings,
|
MeltMethodSettings,
|
||||||
MintBolt11Request,
|
MintBolt11Request<Uuid>,
|
||||||
MintBolt11Response,
|
MintBolt11Response,
|
||||||
MintInfo,
|
MintInfo,
|
||||||
MintQuoteBolt11Request,
|
MintQuoteBolt11Request,
|
||||||
MintQuoteBolt11Response,
|
MintQuoteBolt11Response<Uuid>,
|
||||||
MintQuoteState,
|
MintQuoteState,
|
||||||
MintMethodSettings,
|
MintMethodSettings,
|
||||||
MintVersion,
|
MintVersion,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use cdk::nuts::{
|
|||||||
use cdk::util::unix_time;
|
use cdk::util::unix_time;
|
||||||
use cdk::Error;
|
use cdk::Error;
|
||||||
use paste::paste;
|
use paste::paste;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::ws::main_websocket;
|
use crate::ws::main_websocket;
|
||||||
use crate::MintState;
|
use crate::MintState;
|
||||||
@@ -50,8 +51,16 @@ macro_rules! post_cache_wrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
post_cache_wrapper!(post_swap, SwapRequest, SwapResponse);
|
post_cache_wrapper!(post_swap, SwapRequest, SwapResponse);
|
||||||
post_cache_wrapper!(post_mint_bolt11, MintBolt11Request, MintBolt11Response);
|
post_cache_wrapper!(
|
||||||
post_cache_wrapper!(post_melt_bolt11, MeltBolt11Request, MeltQuoteBolt11Response);
|
post_mint_bolt11,
|
||||||
|
MintBolt11Request<Uuid>,
|
||||||
|
MintBolt11Response
|
||||||
|
);
|
||||||
|
post_cache_wrapper!(
|
||||||
|
post_melt_bolt11,
|
||||||
|
MeltBolt11Request<Uuid>,
|
||||||
|
MeltQuoteBolt11Response<Uuid>
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg_attr(feature = "swagger", utoipa::path(
|
#[cfg_attr(feature = "swagger", utoipa::path(
|
||||||
get,
|
get,
|
||||||
@@ -137,7 +146,7 @@ pub async fn get_keysets(State(state): State<MintState>) -> Result<Json<KeysetRe
|
|||||||
pub async fn post_mint_bolt11_quote(
|
pub async fn post_mint_bolt11_quote(
|
||||||
State(state): State<MintState>,
|
State(state): State<MintState>,
|
||||||
Json(payload): Json<MintQuoteBolt11Request>,
|
Json(payload): Json<MintQuoteBolt11Request>,
|
||||||
) -> Result<Json<MintQuoteBolt11Response>, Response> {
|
) -> Result<Json<MintQuoteBolt11Response<Uuid>>, Response> {
|
||||||
let quote = state
|
let quote = state
|
||||||
.mint
|
.mint
|
||||||
.get_mint_bolt11_quote(payload)
|
.get_mint_bolt11_quote(payload)
|
||||||
@@ -164,8 +173,8 @@ pub async fn post_mint_bolt11_quote(
|
|||||||
/// Get mint quote state.
|
/// Get mint quote state.
|
||||||
pub async fn get_check_mint_bolt11_quote(
|
pub async fn get_check_mint_bolt11_quote(
|
||||||
State(state): State<MintState>,
|
State(state): State<MintState>,
|
||||||
Path(quote_id): Path<String>,
|
Path(quote_id): Path<Uuid>,
|
||||||
) -> Result<Json<MintQuoteBolt11Response>, Response> {
|
) -> Result<Json<MintQuoteBolt11Response<Uuid>>, Response> {
|
||||||
let quote = state
|
let quote = state
|
||||||
.mint
|
.mint
|
||||||
.check_mint_quote("e_id)
|
.check_mint_quote("e_id)
|
||||||
@@ -199,7 +208,7 @@ pub async fn ws_handler(State(state): State<MintState>, ws: WebSocketUpgrade) ->
|
|||||||
))]
|
))]
|
||||||
pub async fn post_mint_bolt11(
|
pub async fn post_mint_bolt11(
|
||||||
State(state): State<MintState>,
|
State(state): State<MintState>,
|
||||||
Json(payload): Json<MintBolt11Request>,
|
Json(payload): Json<MintBolt11Request<Uuid>>,
|
||||||
) -> Result<Json<MintBolt11Response>, Response> {
|
) -> Result<Json<MintBolt11Response>, Response> {
|
||||||
let res = state
|
let res = state
|
||||||
.mint
|
.mint
|
||||||
@@ -227,7 +236,7 @@ pub async fn post_mint_bolt11(
|
|||||||
pub async fn post_melt_bolt11_quote(
|
pub async fn post_melt_bolt11_quote(
|
||||||
State(state): State<MintState>,
|
State(state): State<MintState>,
|
||||||
Json(payload): Json<MeltQuoteBolt11Request>,
|
Json(payload): Json<MeltQuoteBolt11Request>,
|
||||||
) -> Result<Json<MeltQuoteBolt11Response>, Response> {
|
) -> Result<Json<MeltQuoteBolt11Response<Uuid>>, Response> {
|
||||||
let quote = state
|
let quote = state
|
||||||
.mint
|
.mint
|
||||||
.get_melt_bolt11_quote(&payload)
|
.get_melt_bolt11_quote(&payload)
|
||||||
@@ -254,8 +263,8 @@ pub async fn post_melt_bolt11_quote(
|
|||||||
/// Get melt quote state.
|
/// Get melt quote state.
|
||||||
pub async fn get_check_melt_bolt11_quote(
|
pub async fn get_check_melt_bolt11_quote(
|
||||||
State(state): State<MintState>,
|
State(state): State<MintState>,
|
||||||
Path(quote_id): Path<String>,
|
Path(quote_id): Path<Uuid>,
|
||||||
) -> Result<Json<MeltQuoteBolt11Response>, Response> {
|
) -> Result<Json<MeltQuoteBolt11Response<Uuid>>, Response> {
|
||||||
let quote = state
|
let quote = state
|
||||||
.mint
|
.mint
|
||||||
.check_melt_quote("e_id)
|
.check_melt_quote("e_id)
|
||||||
@@ -283,8 +292,8 @@ pub async fn get_check_melt_bolt11_quote(
|
|||||||
/// Requests tokens to be destroyed and sent out via Lightning.
|
/// Requests tokens to be destroyed and sent out via Lightning.
|
||||||
pub async fn post_melt_bolt11(
|
pub async fn post_melt_bolt11(
|
||||||
State(state): State<MintState>,
|
State(state): State<MintState>,
|
||||||
Json(payload): Json<MeltBolt11Request>,
|
Json(payload): Json<MeltBolt11Request<Uuid>>,
|
||||||
) -> Result<Json<MeltQuoteBolt11Response>, Response> {
|
) -> Result<Json<MeltQuoteBolt11Response<Uuid>>, Response> {
|
||||||
let res = state
|
let res = state
|
||||||
.mint
|
.mint
|
||||||
.melt_bolt11(&payload)
|
.melt_bolt11(&payload)
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ tracing = { version = "0.1", default-features = false, features = ["attributes",
|
|||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
uuid = { version = "1", features = ["v4"] }
|
|
||||||
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
|
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
|
||||||
tokio-stream = "0.1.15"
|
tokio-stream = "0.1.15"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ async fn test_regtest_mint_melt_round_trip() -> Result<()> {
|
|||||||
_ => panic!("Wrong payload"),
|
_ => panic!("Wrong payload"),
|
||||||
};
|
};
|
||||||
assert_eq!(payload.amount + payload.fee_reserve, 100.into());
|
assert_eq!(payload.amount + payload.fee_reserve, 100.into());
|
||||||
assert_eq!(payload.quote, melt.id);
|
assert_eq!(payload.quote.to_string(), melt.id);
|
||||||
assert_eq!(payload.state, MeltQuoteState::Unpaid);
|
assert_eq!(payload.state, MeltQuoteState::Unpaid);
|
||||||
|
|
||||||
// get current state
|
// get current state
|
||||||
@@ -131,7 +131,7 @@ async fn test_regtest_mint_melt_round_trip() -> Result<()> {
|
|||||||
_ => panic!("Wrong payload"),
|
_ => panic!("Wrong payload"),
|
||||||
};
|
};
|
||||||
assert_eq!(payload.amount + payload.fee_reserve, 100.into());
|
assert_eq!(payload.amount + payload.fee_reserve, 100.into());
|
||||||
assert_eq!(payload.quote, melt.id);
|
assert_eq!(payload.quote.to_string(), melt.id);
|
||||||
assert_eq!(payload.state, MeltQuoteState::Paid);
|
assert_eq!(payload.state, MeltQuoteState::Paid);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -24,3 +24,4 @@ tracing = { version = "0.1", default-features = false, features = ["attributes",
|
|||||||
serde = { version = "1", default-features = false, features = ["derive"] }
|
serde = { version = "1", default-features = false, features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
|
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
|
||||||
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ use cdk::mint_url::MintUrl;
|
|||||||
use cdk::nuts::{CurrencyUnit, MintQuoteState, Proof, State};
|
use cdk::nuts::{CurrencyUnit, MintQuoteState, Proof, State};
|
||||||
use cdk::Amount;
|
use cdk::Amount;
|
||||||
use lightning_invoice::Bolt11Invoice;
|
use lightning_invoice::Bolt11Invoice;
|
||||||
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
|
use redb::{
|
||||||
|
Database, MultimapTableDefinition, ReadableMultimapTable, ReadableTable, TableDefinition,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{Error, PROOFS_STATE_TABLE, PROOFS_TABLE, QUOTE_SIGNATURES_TABLE};
|
use super::{Error, PROOFS_STATE_TABLE, PROOFS_TABLE, QUOTE_SIGNATURES_TABLE};
|
||||||
|
|
||||||
const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
|
const ID_STR_MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
|
||||||
const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
|
const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
|
||||||
TableDefinition::new("pending_proofs");
|
TableDefinition::new("pending_proofs");
|
||||||
const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
|
const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
|
||||||
@@ -36,10 +39,158 @@ pub fn migrate_03_to_04(db: Arc<Database>) -> Result<u32, Error> {
|
|||||||
Ok(4)
|
Ok(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn migrate_04_to_05(db: Arc<Database>) -> Result<u32, Error> {
|
||||||
|
let write_txn = db.begin_write()?;
|
||||||
|
|
||||||
|
// Mint quotes
|
||||||
|
{
|
||||||
|
const MINT_QUOTE_TABLE_NAME: &str = "mint_quotes";
|
||||||
|
const OLD_TABLE: TableDefinition<&str, &str> = TableDefinition::new(MINT_QUOTE_TABLE_NAME);
|
||||||
|
const NEW_TABLE: TableDefinition<[u8; 16], &str> =
|
||||||
|
TableDefinition::new(MINT_QUOTE_TABLE_NAME);
|
||||||
|
|
||||||
|
let old_table = write_txn.open_table(OLD_TABLE)?;
|
||||||
|
|
||||||
|
let mut tmp_hashmap = HashMap::new();
|
||||||
|
|
||||||
|
for (k, v) in old_table.iter().map_err(Error::from)?.flatten() {
|
||||||
|
let quote_id = Uuid::try_parse(k.value()).unwrap();
|
||||||
|
tmp_hashmap.insert(quote_id, v.value().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
write_txn.delete_table(old_table).map_err(Error::from)?;
|
||||||
|
let mut new_table = write_txn.open_table(NEW_TABLE)?;
|
||||||
|
|
||||||
|
for (k, v) in tmp_hashmap.into_iter() {
|
||||||
|
new_table
|
||||||
|
.insert(k.as_bytes(), v.as_str())
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Melt quotes
|
||||||
|
{
|
||||||
|
const MELT_QUOTE_TABLE_NAME: &str = "melt_quotes";
|
||||||
|
const OLD_TABLE: TableDefinition<&str, &str> = TableDefinition::new(MELT_QUOTE_TABLE_NAME);
|
||||||
|
const NEW_TABLE: TableDefinition<[u8; 16], &str> =
|
||||||
|
TableDefinition::new(MELT_QUOTE_TABLE_NAME);
|
||||||
|
|
||||||
|
let old_table = write_txn.open_table(OLD_TABLE)?;
|
||||||
|
|
||||||
|
let mut tmp_hashmap = HashMap::new();
|
||||||
|
|
||||||
|
for (k, v) in old_table.iter().map_err(Error::from)?.flatten() {
|
||||||
|
let quote_id = Uuid::try_parse(k.value()).unwrap();
|
||||||
|
tmp_hashmap.insert(quote_id, v.value().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
write_txn.delete_table(old_table).map_err(Error::from)?;
|
||||||
|
let mut new_table = write_txn.open_table(NEW_TABLE)?;
|
||||||
|
|
||||||
|
for (k, v) in tmp_hashmap.into_iter() {
|
||||||
|
new_table
|
||||||
|
.insert(k.as_bytes(), v.as_str())
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Quote proofs
|
||||||
|
{
|
||||||
|
const QUOTE_PROOFS_TABLE_NAME: &str = "quote_proofs";
|
||||||
|
const OLD_TABLE: MultimapTableDefinition<&str, [u8; 33]> =
|
||||||
|
MultimapTableDefinition::new(QUOTE_PROOFS_TABLE_NAME);
|
||||||
|
const NEW_TABLE: MultimapTableDefinition<[u8; 16], [u8; 33]> =
|
||||||
|
MultimapTableDefinition::new(QUOTE_PROOFS_TABLE_NAME);
|
||||||
|
|
||||||
|
let old_table = write_txn.open_multimap_table(OLD_TABLE)?;
|
||||||
|
|
||||||
|
let mut tmp_hashmap = HashMap::new();
|
||||||
|
|
||||||
|
for (k, v) in old_table.iter().map_err(Error::from)?.flatten() {
|
||||||
|
let quote_id = Uuid::try_parse(k.value()).unwrap();
|
||||||
|
let ys: Vec<[u8; 33]> = v.into_iter().flatten().map(|v| v.value()).collect();
|
||||||
|
tmp_hashmap.insert(quote_id, ys);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_txn
|
||||||
|
.delete_multimap_table(old_table)
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
let mut new_table = write_txn.open_multimap_table(NEW_TABLE)?;
|
||||||
|
|
||||||
|
for (quote_id, blind_messages) in tmp_hashmap.into_iter() {
|
||||||
|
for blind_message in blind_messages {
|
||||||
|
new_table
|
||||||
|
.insert(quote_id.as_bytes(), blind_message)
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Quote signatures
|
||||||
|
{
|
||||||
|
const QUOTE_SIGNATURES_TABLE_NAME: &str = "quote_signatures";
|
||||||
|
const OLD_TABLE: MultimapTableDefinition<&str, [u8; 33]> =
|
||||||
|
MultimapTableDefinition::new(QUOTE_SIGNATURES_TABLE_NAME);
|
||||||
|
const NEW_TABLE: MultimapTableDefinition<[u8; 16], [u8; 33]> =
|
||||||
|
MultimapTableDefinition::new(QUOTE_SIGNATURES_TABLE_NAME);
|
||||||
|
|
||||||
|
let old_table = write_txn.open_multimap_table(OLD_TABLE)?;
|
||||||
|
|
||||||
|
let mut tmp_hashmap = HashMap::new();
|
||||||
|
|
||||||
|
for (k, v) in old_table.iter().map_err(Error::from)?.flatten() {
|
||||||
|
let quote_id = Uuid::try_parse(k.value()).unwrap();
|
||||||
|
let ys: Vec<[u8; 33]> = v.into_iter().flatten().map(|v| v.value()).collect();
|
||||||
|
tmp_hashmap.insert(quote_id, ys);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_txn
|
||||||
|
.delete_multimap_table(old_table)
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
let mut new_table = write_txn.open_multimap_table(NEW_TABLE)?;
|
||||||
|
|
||||||
|
for (quote_id, signatures) in tmp_hashmap.into_iter() {
|
||||||
|
for signature in signatures {
|
||||||
|
new_table
|
||||||
|
.insert(quote_id.as_bytes(), signature)
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Melt requests
|
||||||
|
{
|
||||||
|
const MELT_REQUESTS_TABLE_NAME: &str = "melt_requests";
|
||||||
|
const OLD_TABLE: TableDefinition<&str, (&str, &str)> =
|
||||||
|
TableDefinition::new(MELT_REQUESTS_TABLE_NAME);
|
||||||
|
const NEW_TABLE: TableDefinition<[u8; 16], (&str, &str)> =
|
||||||
|
TableDefinition::new(MELT_REQUESTS_TABLE_NAME);
|
||||||
|
|
||||||
|
let old_table = write_txn.open_table(OLD_TABLE)?;
|
||||||
|
|
||||||
|
let mut tmp_hashmap = HashMap::new();
|
||||||
|
|
||||||
|
for (k, v) in old_table.iter().map_err(Error::from)?.flatten() {
|
||||||
|
let quote_id = Uuid::try_parse(k.value()).unwrap();
|
||||||
|
let value = v.value();
|
||||||
|
tmp_hashmap.insert(quote_id, (value.0.to_string(), value.1.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
write_txn.delete_table(old_table).map_err(Error::from)?;
|
||||||
|
let mut new_table = write_txn.open_table(NEW_TABLE)?;
|
||||||
|
|
||||||
|
for (k, v) in tmp_hashmap.into_iter() {
|
||||||
|
new_table
|
||||||
|
.insert(k.as_bytes(), (v.0.as_str(), v.1.as_str()))
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_txn.commit().map_err(Error::from)?;
|
||||||
|
|
||||||
|
Ok(5)
|
||||||
|
}
|
||||||
|
|
||||||
/// Mint Quote Info
|
/// Mint Quote Info
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
struct V1MintQuote {
|
struct V1MintQuote {
|
||||||
pub id: String,
|
pub id: Uuid,
|
||||||
pub mint_url: MintUrl,
|
pub mint_url: MintUrl,
|
||||||
pub amount: Amount,
|
pub amount: Amount,
|
||||||
pub unit: CurrencyUnit,
|
pub unit: CurrencyUnit,
|
||||||
@@ -66,7 +217,7 @@ impl From<V1MintQuote> for MintQuote {
|
|||||||
fn migrate_mint_quotes_01_to_02(db: Arc<Database>) -> Result<(), Error> {
|
fn migrate_mint_quotes_01_to_02(db: Arc<Database>) -> Result<(), Error> {
|
||||||
let read_txn = db.begin_read().map_err(Error::from)?;
|
let read_txn = db.begin_read().map_err(Error::from)?;
|
||||||
let table = read_txn
|
let table = read_txn
|
||||||
.open_table(MINT_QUOTES_TABLE)
|
.open_table(ID_STR_MINT_QUOTES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
let mint_quotes: HashMap<String, Option<V1MintQuote>>;
|
let mint_quotes: HashMap<String, Option<V1MintQuote>>;
|
||||||
@@ -94,7 +245,7 @@ fn migrate_mint_quotes_01_to_02(db: Arc<Database>) -> Result<(), Error> {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut table = write_txn
|
let mut table = write_txn
|
||||||
.open_table(MINT_QUOTES_TABLE)
|
.open_table(ID_STR_MINT_QUOTES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
for (quote_id, quote) in migrated_mint_quotes {
|
for (quote_id, quote) in migrated_mint_quotes {
|
||||||
match quote {
|
match quote {
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ use cdk::nuts::{
|
|||||||
};
|
};
|
||||||
use cdk::types::LnKey;
|
use cdk::types::LnKey;
|
||||||
use cdk::{cdk_database, mint};
|
use cdk::{cdk_database, mint};
|
||||||
use migrations::migrate_01_to_02;
|
use migrations::{migrate_01_to_02, migrate_04_to_05};
|
||||||
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
|
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
use crate::migrations::migrate_00_to_01;
|
use crate::migrations::migrate_00_to_01;
|
||||||
@@ -28,22 +29,23 @@ mod migrations;
|
|||||||
|
|
||||||
const ACTIVE_KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("active_keysets");
|
const ACTIVE_KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("active_keysets");
|
||||||
const KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("keysets");
|
const KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("keysets");
|
||||||
const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
|
const MINT_QUOTES_TABLE: TableDefinition<[u8; 16], &str> = TableDefinition::new("mint_quotes");
|
||||||
const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
|
const MELT_QUOTES_TABLE: TableDefinition<[u8; 16], &str> = TableDefinition::new("melt_quotes");
|
||||||
const PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("proofs");
|
const PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("proofs");
|
||||||
const PROOFS_STATE_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("proofs_state");
|
const PROOFS_STATE_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("proofs_state");
|
||||||
const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
|
const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
|
||||||
// Key is hex blinded_message B_ value is blinded_signature
|
// Key is hex blinded_message B_ value is blinded_signature
|
||||||
const BLINDED_SIGNATURES: TableDefinition<[u8; 33], &str> =
|
const BLINDED_SIGNATURES: TableDefinition<[u8; 33], &str> =
|
||||||
TableDefinition::new("blinded_signatures");
|
TableDefinition::new("blinded_signatures");
|
||||||
const QUOTE_PROOFS_TABLE: MultimapTableDefinition<&str, [u8; 33]> =
|
const QUOTE_PROOFS_TABLE: MultimapTableDefinition<[u8; 16], [u8; 33]> =
|
||||||
MultimapTableDefinition::new("quote_proofs");
|
MultimapTableDefinition::new("quote_proofs");
|
||||||
const QUOTE_SIGNATURES_TABLE: MultimapTableDefinition<&str, [u8; 33]> =
|
const QUOTE_SIGNATURES_TABLE: MultimapTableDefinition<[u8; 16], [u8; 33]> =
|
||||||
MultimapTableDefinition::new("quote_signatures");
|
MultimapTableDefinition::new("quote_signatures");
|
||||||
|
|
||||||
const MELT_REQUESTS: TableDefinition<&str, (&str, &str)> = TableDefinition::new("melt_requests");
|
const MELT_REQUESTS: TableDefinition<[u8; 16], (&str, &str)> =
|
||||||
|
TableDefinition::new("melt_requests");
|
||||||
|
|
||||||
const DATABASE_VERSION: u32 = 4;
|
const DATABASE_VERSION: u32 = 5;
|
||||||
|
|
||||||
/// Mint Redbdatabase
|
/// Mint Redbdatabase
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -93,6 +95,10 @@ impl MintRedbDatabase {
|
|||||||
current_file_version = migrate_03_to_04(Arc::clone(&db))?;
|
current_file_version = migrate_03_to_04(Arc::clone(&db))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if current_file_version == 4 {
|
||||||
|
current_file_version = migrate_04_to_05(Arc::clone(&db))?;
|
||||||
|
}
|
||||||
|
|
||||||
if current_file_version != DATABASE_VERSION {
|
if current_file_version != DATABASE_VERSION {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"Database upgrade did not complete at {} current is {}",
|
"Database upgrade did not complete at {} current is {}",
|
||||||
@@ -261,7 +267,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
table
|
table
|
||||||
.insert(
|
.insert(
|
||||||
quote.id.as_str(),
|
quote.id.as_bytes(),
|
||||||
serde_json::to_string("e).map_err(Error::from)?.as_str(),
|
serde_json::to_string("e).map_err(Error::from)?.as_str(),
|
||||||
)
|
)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
@@ -271,13 +277,13 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
|
async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintQuote>, Self::Err> {
|
||||||
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
|
let table = read_txn
|
||||||
.open_table(MINT_QUOTES_TABLE)
|
.open_table(MINT_QUOTES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
match table.get(quote_id).map_err(Error::from)? {
|
match table.get(quote_id.as_bytes()).map_err(Error::from)? {
|
||||||
Some(quote) => Ok(serde_json::from_str(quote.value()).map_err(Error::from)?),
|
Some(quote) => Ok(serde_json::from_str(quote.value()).map_err(Error::from)?),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
@@ -285,7 +291,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
|
|
||||||
async fn update_mint_quote_state(
|
async fn update_mint_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MintQuoteState,
|
state: MintQuoteState,
|
||||||
) -> Result<MintQuoteState, Self::Err> {
|
) -> Result<MintQuoteState, Self::Err> {
|
||||||
let write_txn = self.db.begin_write().map_err(Error::from)?;
|
let write_txn = self.db.begin_write().map_err(Error::from)?;
|
||||||
@@ -297,7 +303,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
let quote_guard = table
|
let quote_guard = table
|
||||||
.get(quote_id)
|
.get(quote_id.as_bytes())
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.ok_or(Error::UnknownMintInfo)?;
|
.ok_or(Error::UnknownMintInfo)?;
|
||||||
|
|
||||||
@@ -316,7 +322,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
|
|
||||||
table
|
table
|
||||||
.insert(
|
.insert(
|
||||||
quote_id,
|
quote_id.as_bytes(),
|
||||||
serde_json::to_string(&mint_quote)
|
serde_json::to_string(&mint_quote)
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.as_str(),
|
.as_str(),
|
||||||
@@ -376,14 +382,14 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
Ok(quotes)
|
Ok(quotes)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
async fn remove_mint_quote(&self, quote_id: &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)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut table = write_txn
|
let mut table = write_txn
|
||||||
.open_table(MINT_QUOTES_TABLE)
|
.open_table(MINT_QUOTES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
table.remove(quote_id).map_err(Error::from)?;
|
table.remove(quote_id.as_bytes()).map_err(Error::from)?;
|
||||||
}
|
}
|
||||||
write_txn.commit().map_err(Error::from)?;
|
write_txn.commit().map_err(Error::from)?;
|
||||||
|
|
||||||
@@ -399,7 +405,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
table
|
table
|
||||||
.insert(
|
.insert(
|
||||||
quote.id.as_str(),
|
quote.id.as_bytes(),
|
||||||
serde_json::to_string("e).map_err(Error::from)?.as_str(),
|
serde_json::to_string("e).map_err(Error::from)?.as_str(),
|
||||||
)
|
)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
@@ -409,20 +415,20 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<mint::MeltQuote>, Self::Err> {
|
async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, Self::Err> {
|
||||||
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
|
let table = read_txn
|
||||||
.open_table(MELT_QUOTES_TABLE)
|
.open_table(MELT_QUOTES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
let quote = table.get(quote_id).map_err(Error::from)?;
|
let quote = table.get(quote_id.as_bytes()).map_err(Error::from)?;
|
||||||
|
|
||||||
Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
|
Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_melt_quote_state(
|
async fn update_melt_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MeltQuoteState,
|
state: MeltQuoteState,
|
||||||
) -> Result<MeltQuoteState, Self::Err> {
|
) -> Result<MeltQuoteState, Self::Err> {
|
||||||
let write_txn = self.db.begin_write().map_err(Error::from)?;
|
let write_txn = self.db.begin_write().map_err(Error::from)?;
|
||||||
@@ -435,7 +441,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
let quote_guard = table
|
let quote_guard = table
|
||||||
.get(quote_id)
|
.get(quote_id.as_bytes())
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.ok_or(Error::UnknownMintInfo)?;
|
.ok_or(Error::UnknownMintInfo)?;
|
||||||
|
|
||||||
@@ -454,7 +460,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
|
|
||||||
table
|
table
|
||||||
.insert(
|
.insert(
|
||||||
quote_id,
|
quote_id.as_bytes(),
|
||||||
serde_json::to_string(&melt_quote)
|
serde_json::to_string(&melt_quote)
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.as_str(),
|
.as_str(),
|
||||||
@@ -483,21 +489,21 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
Ok(quotes)
|
Ok(quotes)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
async fn remove_melt_quote(&self, quote_id: &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)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut table = write_txn
|
let mut table = write_txn
|
||||||
.open_table(MELT_QUOTES_TABLE)
|
.open_table(MELT_QUOTES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
table.remove(quote_id).map_err(Error::from)?;
|
table.remove(quote_id.as_bytes()).map_err(Error::from)?;
|
||||||
}
|
}
|
||||||
write_txn.commit().map_err(Error::from)?;
|
write_txn.commit().map_err(Error::from)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<String>) -> 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)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -519,7 +525,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
|
|
||||||
if let Some(quote_id) = "e_id {
|
if let Some(quote_id) = "e_id {
|
||||||
quote_proofs_table
|
quote_proofs_table
|
||||||
.insert(quote_id.as_str(), y)
|
.insert(quote_id.as_bytes(), y)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -547,13 +553,13 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
Ok(proofs)
|
Ok(proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_proof_ys_by_quote_id(&self, quote_id: &str) -> Result<Vec<PublicKey>, Self::Err> {
|
async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, Self::Err> {
|
||||||
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
|
let table = read_txn
|
||||||
.open_multimap_table(QUOTE_PROOFS_TABLE)
|
.open_multimap_table(QUOTE_PROOFS_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
let ys = table.get(quote_id).map_err(Error::from)?;
|
let ys = table.get(quote_id.as_bytes()).map_err(Error::from)?;
|
||||||
|
|
||||||
let proof_ys = ys.fold(Vec::new(), |mut acc, y| {
|
let proof_ys = ys.fold(Vec::new(), |mut acc, y| {
|
||||||
if let Ok(y) = y {
|
if let Ok(y) = y {
|
||||||
@@ -660,7 +666,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
&self,
|
&self,
|
||||||
blinded_messages: &[PublicKey],
|
blinded_messages: &[PublicKey],
|
||||||
blind_signatures: &[BlindSignature],
|
blind_signatures: &[BlindSignature],
|
||||||
quote_id: Option<String>,
|
quote_id: Option<Uuid>,
|
||||||
) -> Result<(), Self::Err> {
|
) -> 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)?;
|
||||||
|
|
||||||
@@ -681,7 +687,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
|
|
||||||
if let Some(quote_id) = "e_id {
|
if let Some(quote_id) = "e_id {
|
||||||
quote_sigs_table
|
quote_sigs_table
|
||||||
.insert(quote_id.as_str(), blinded_message.to_bytes())
|
.insert(quote_id.as_bytes(), blinded_message.to_bytes())
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -740,7 +746,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
/// Add melt request
|
/// Add melt request
|
||||||
async fn add_melt_request(
|
async fn add_melt_request(
|
||||||
&self,
|
&self,
|
||||||
melt_request: MeltBolt11Request,
|
melt_request: MeltBolt11Request<Uuid>,
|
||||||
ln_key: LnKey,
|
ln_key: LnKey,
|
||||||
) -> Result<(), Self::Err> {
|
) -> 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)?;
|
||||||
@@ -748,7 +754,7 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
|
|
||||||
table
|
table
|
||||||
.insert(
|
.insert(
|
||||||
melt_request.quote.as_str(),
|
melt_request.quote.as_bytes(),
|
||||||
(
|
(
|
||||||
serde_json::to_string(&melt_request)?.as_str(),
|
serde_json::to_string(&melt_request)?.as_str(),
|
||||||
serde_json::to_string(&ln_key)?.as_str(),
|
serde_json::to_string(&ln_key)?.as_str(),
|
||||||
@@ -761,12 +767,12 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
/// Get melt request
|
/// Get melt request
|
||||||
async fn get_melt_request(
|
async fn get_melt_request(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Option<(MeltBolt11Request, LnKey)>, Self::Err> {
|
) -> Result<Option<(MeltBolt11Request<Uuid>, LnKey)>, Self::Err> {
|
||||||
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(MELT_REQUESTS).map_err(Error::from)?;
|
let table = read_txn.open_table(MELT_REQUESTS).map_err(Error::from)?;
|
||||||
|
|
||||||
match table.get(quote_id).map_err(Error::from)? {
|
match table.get(quote_id.as_bytes()).map_err(Error::from)? {
|
||||||
Some(melt_request) => {
|
Some(melt_request) => {
|
||||||
let (melt_request_str, ln_key_str) = melt_request.value();
|
let (melt_request_str, ln_key_str) = melt_request.value();
|
||||||
let melt_request = serde_json::from_str(melt_request_str)?;
|
let melt_request = serde_json::from_str(melt_request_str)?;
|
||||||
@@ -781,14 +787,14 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
/// 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,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Vec<BlindSignature>, Self::Err> {
|
) -> Result<Vec<BlindSignature>, Self::Err> {
|
||||||
let read_txn = self.db.begin_read().map_err(Error::from)?;
|
let read_txn = self.db.begin_read().map_err(Error::from)?;
|
||||||
let quote_proofs_table = read_txn
|
let quote_proofs_table = read_txn
|
||||||
.open_multimap_table(QUOTE_SIGNATURES_TABLE)
|
.open_multimap_table(QUOTE_SIGNATURES_TABLE)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
|
|
||||||
let ys = quote_proofs_table.get(quote_id).unwrap();
|
let ys = quote_proofs_table.get(quote_id.as_bytes()).unwrap();
|
||||||
|
|
||||||
let ys: Vec<[u8; 33]> = ys.into_iter().flatten().map(|v| v.value()).collect();
|
let ys: Vec<[u8; 33]> = ys.into_iter().flatten().map(|v| v.value()).collect();
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ wallet = ["cdk/wallet"]
|
|||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
cdk = { path = "../cdk", version = "0.5.0", default-features = false }
|
cdk = { path = "../cdk", version = "0.5.0", default-features = false }
|
||||||
bitcoin = { version = "0.32.2", default-features = false }
|
bitcoin = { version = "0.32.2", default-features = false }
|
||||||
sqlx = { version = "0.6.3", default-features = false, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
sqlx = { version = "0.6.3", default-features = false, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "uuid"] }
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
tokio = { version = "1", features = [
|
tokio = { version = "1", features = [
|
||||||
"time",
|
"time",
|
||||||
@@ -29,3 +29,4 @@ tokio = { version = "1", features = [
|
|||||||
tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] }
|
tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
|
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
|
||||||
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ use error::Error;
|
|||||||
use lightning_invoice::Bolt11Invoice;
|
use lightning_invoice::Bolt11Invoice;
|
||||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions, SqliteRow};
|
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions, SqliteRow};
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
|
use uuid::fmt::Hyphenated;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
@@ -236,7 +238,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
|
async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintQuote>, 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#"
|
||||||
@@ -245,7 +247,7 @@ FROM mint_quote
|
|||||||
WHERE id=?;
|
WHERE id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_one(&mut transaction)
|
.fetch_one(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -345,7 +347,7 @@ WHERE request_lookup_id=?;
|
|||||||
|
|
||||||
async fn update_mint_quote_state(
|
async fn update_mint_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MintQuoteState,
|
state: MintQuoteState,
|
||||||
) -> Result<MintQuoteState, Self::Err> {
|
) -> Result<MintQuoteState, Self::Err> {
|
||||||
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
||||||
@@ -357,7 +359,7 @@ FROM mint_quote
|
|||||||
WHERE id=?;
|
WHERE id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_one(&mut transaction)
|
.fetch_one(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
let quote = match rec {
|
let quote = match rec {
|
||||||
@@ -378,7 +380,7 @@ WHERE id=?;
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(state.to_string())
|
.bind(state.to_string())
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -430,7 +432,7 @@ FROM mint_quote
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
async fn remove_mint_quote(&self, quote_id: &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)?;
|
||||||
|
|
||||||
let res = sqlx::query(
|
let res = sqlx::query(
|
||||||
@@ -439,7 +441,7 @@ DELETE FROM mint_quote
|
|||||||
WHERE id=?
|
WHERE id=?
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -497,7 +499,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<mint::MeltQuote>, Self::Err> {
|
async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, 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#"
|
||||||
@@ -506,7 +508,7 @@ FROM melt_quote
|
|||||||
WHERE id=?;
|
WHERE id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_one(&mut transaction)
|
.fetch_one(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -564,7 +566,7 @@ FROM melt_quote
|
|||||||
|
|
||||||
async fn update_melt_quote_state(
|
async fn update_melt_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MeltQuoteState,
|
state: MeltQuoteState,
|
||||||
) -> Result<MeltQuoteState, Self::Err> {
|
) -> Result<MeltQuoteState, Self::Err> {
|
||||||
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
||||||
@@ -576,7 +578,7 @@ FROM melt_quote
|
|||||||
WHERE id=?;
|
WHERE id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_one(&mut transaction)
|
.fetch_one(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -598,7 +600,7 @@ WHERE id=?;
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(state.to_string())
|
.bind(state.to_string())
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -619,7 +621,7 @@ WHERE id=?;
|
|||||||
Ok(quote.state)
|
Ok(quote.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
async fn remove_melt_quote(&self, quote_id: &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)?;
|
||||||
let res = sqlx::query(
|
let res = sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
@@ -627,7 +629,7 @@ DELETE FROM melt_quote
|
|||||||
WHERE id=?
|
WHERE id=?
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -748,7 +750,7 @@ FROM keyset;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<String>) -> 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)?;
|
||||||
for proof in proofs {
|
for proof in proofs {
|
||||||
if let Err(err) = sqlx::query(
|
if let Err(err) = sqlx::query(
|
||||||
@@ -765,7 +767,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
|||||||
.bind(proof.c.to_bytes().to_vec())
|
.bind(proof.c.to_bytes().to_vec())
|
||||||
.bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
|
.bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
|
||||||
.bind("UNSPENT")
|
.bind("UNSPENT")
|
||||||
.bind(quote_id.clone())
|
.bind(quote_id.map(|q| q.hyphenated()))
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
.await
|
.await
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
@@ -812,7 +814,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
|||||||
Ok(ys.iter().map(|y| proofs.remove(y)).collect())
|
Ok(ys.iter().map(|y| proofs.remove(y)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_proof_ys_by_quote_id(&self, quote_id: &str) -> Result<Vec<PublicKey>, Self::Err> {
|
async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, 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(
|
||||||
@@ -822,7 +824,7 @@ FROM proof
|
|||||||
WHERE quote_id=?;
|
WHERE quote_id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_all(&mut transaction)
|
.fetch_all(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -996,7 +998,7 @@ WHERE keyset_id=?;
|
|||||||
&self,
|
&self,
|
||||||
blinded_messages: &[PublicKey],
|
blinded_messages: &[PublicKey],
|
||||||
blinded_signatures: &[BlindSignature],
|
blinded_signatures: &[BlindSignature],
|
||||||
quote_id: Option<String>,
|
quote_id: Option<Uuid>,
|
||||||
) -> Result<(), Self::Err> {
|
) -> 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)?;
|
||||||
for (message, signature) in blinded_messages.iter().zip(blinded_signatures) {
|
for (message, signature) in blinded_messages.iter().zip(blinded_signatures) {
|
||||||
@@ -1011,7 +1013,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?);
|
|||||||
.bind(u64::from(signature.amount) as i64)
|
.bind(u64::from(signature.amount) as i64)
|
||||||
.bind(signature.keyset_id.to_string())
|
.bind(signature.keyset_id.to_string())
|
||||||
.bind(signature.c.to_bytes().to_vec())
|
.bind(signature.c.to_bytes().to_vec())
|
||||||
.bind(quote_id.clone())
|
.bind(quote_id.map(|q| q.hyphenated()))
|
||||||
.bind(signature.dleq.as_ref().map(|dleq| dleq.e.to_secret_hex()))
|
.bind(signature.dleq.as_ref().map(|dleq| dleq.e.to_secret_hex()))
|
||||||
.bind(signature.dleq.as_ref().map(|dleq| dleq.s.to_secret_hex()))
|
.bind(signature.dleq.as_ref().map(|dleq| dleq.s.to_secret_hex()))
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
@@ -1111,7 +1113,7 @@ WHERE keyset_id=?;
|
|||||||
|
|
||||||
async fn add_melt_request(
|
async fn add_melt_request(
|
||||||
&self,
|
&self,
|
||||||
melt_request: MeltBolt11Request,
|
melt_request: MeltBolt11Request<Uuid>,
|
||||||
ln_key: LnKey,
|
ln_key: LnKey,
|
||||||
) -> Result<(), Self::Err> {
|
) -> 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)?;
|
||||||
@@ -1149,8 +1151,8 @@ VALUES (?, ?, ?, ?, ?);
|
|||||||
|
|
||||||
async fn get_melt_request(
|
async fn get_melt_request(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Option<(MeltBolt11Request, LnKey)>, Self::Err> {
|
) -> Result<Option<(MeltBolt11Request<Uuid>, LnKey)>, 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(
|
||||||
@@ -1160,7 +1162,7 @@ FROM melt_request
|
|||||||
WHERE id=?;
|
WHERE id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_one(&mut transaction)
|
.fetch_one(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -1192,7 +1194,7 @@ WHERE id=?;
|
|||||||
/// 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,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Vec<BlindSignature>, Self::Err> {
|
) -> Result<Vec<BlindSignature>, Self::Err> {
|
||||||
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
||||||
|
|
||||||
@@ -1203,7 +1205,7 @@ FROM blind_signature
|
|||||||
WHERE quote_id=?;
|
WHERE quote_id=?;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(quote_id)
|
.bind(quote_id.as_hyphenated())
|
||||||
.fetch_all(&mut transaction)
|
.fetch_all(&mut transaction)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -1254,7 +1256,7 @@ fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
|
fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
|
||||||
let row_id: String = row.try_get("id").map_err(Error::from)?;
|
let row_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
|
||||||
let row_mint_url: String = row.try_get("mint_url").map_err(Error::from)?;
|
let row_mint_url: String = row.try_get("mint_url").map_err(Error::from)?;
|
||||||
let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
|
let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
|
||||||
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
|
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
|
||||||
@@ -1273,7 +1275,7 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(MintQuote {
|
Ok(MintQuote {
|
||||||
id: row_id,
|
id: row_id.into_uuid(),
|
||||||
mint_url: MintUrl::from_str(&row_mint_url)?,
|
mint_url: MintUrl::from_str(&row_mint_url)?,
|
||||||
amount: Amount::from(row_amount as u64),
|
amount: Amount::from(row_amount as u64),
|
||||||
unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
|
unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
|
||||||
@@ -1285,7 +1287,7 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sqlite_row_to_melt_quote(row: SqliteRow) -> Result<mint::MeltQuote, Error> {
|
fn sqlite_row_to_melt_quote(row: SqliteRow) -> Result<mint::MeltQuote, Error> {
|
||||||
let row_id: String = row.try_get("id").map_err(Error::from)?;
|
let row_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
|
||||||
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
|
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
|
||||||
let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
|
let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
|
||||||
let row_request: String = row.try_get("request").map_err(Error::from)?;
|
let row_request: String = row.try_get("request").map_err(Error::from)?;
|
||||||
@@ -1299,7 +1301,7 @@ fn sqlite_row_to_melt_quote(row: SqliteRow) -> Result<mint::MeltQuote, Error> {
|
|||||||
let request_lookup_id = row_request_lookup.unwrap_or(row_request.clone());
|
let request_lookup_id = row_request_lookup.unwrap_or(row_request.clone());
|
||||||
|
|
||||||
Ok(mint::MeltQuote {
|
Ok(mint::MeltQuote {
|
||||||
id: row_id,
|
id: row_id.into_uuid(),
|
||||||
amount: Amount::from(row_amount as u64),
|
amount: Amount::from(row_amount as u64),
|
||||||
unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
|
unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
|
||||||
request: row_request,
|
request: row_request,
|
||||||
@@ -1375,15 +1377,15 @@ fn sqlite_row_to_blind_signature(row: SqliteRow) -> Result<BlindSignature, Error
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sqlite_row_to_melt_request(row: SqliteRow) -> Result<(MeltBolt11Request, LnKey), Error> {
|
fn sqlite_row_to_melt_request(row: SqliteRow) -> Result<(MeltBolt11Request<Uuid>, LnKey), Error> {
|
||||||
let quote_id: String = row.try_get("id").map_err(Error::from)?;
|
let quote_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
|
||||||
let row_inputs: String = row.try_get("inputs").map_err(Error::from)?;
|
let row_inputs: String = row.try_get("inputs").map_err(Error::from)?;
|
||||||
let row_outputs: Option<String> = row.try_get("outputs").map_err(Error::from)?;
|
let row_outputs: Option<String> = row.try_get("outputs").map_err(Error::from)?;
|
||||||
let row_method: String = row.try_get("method").map_err(Error::from)?;
|
let row_method: String = row.try_get("method").map_err(Error::from)?;
|
||||||
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
|
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
|
||||||
|
|
||||||
let melt_request = MeltBolt11Request {
|
let melt_request = MeltBolt11Request {
|
||||||
quote: quote_id,
|
quote: quote_id.into_uuid(),
|
||||||
inputs: serde_json::from_str(&row_inputs)?,
|
inputs: serde_json::from_str(&row_inputs)?,
|
||||||
outputs: row_outputs.and_then(|o| serde_json::from_str(&o).ok()),
|
outputs: row_outputs.and_then(|o| serde_json::from_str(&o).ok()),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ thiserror = "1"
|
|||||||
futures = { version = "0.3.28", default-features = false, optional = true, features = ["alloc"] }
|
futures = { version = "0.3.28", default-features = false, optional = true, features = ["alloc"] }
|
||||||
url = "2.3"
|
url = "2.3"
|
||||||
utoipa = { version = "4", optional = true }
|
utoipa = { version = "4", optional = true }
|
||||||
uuid = { version = "1", features = ["v4"] }
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
|
|
||||||
# -Z minimal-versions
|
# -Z minimal-versions
|
||||||
sync_wrapper = "0.1.2"
|
sync_wrapper = "0.1.2"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::{Mutex, RwLock};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{Error, MintDatabase};
|
use super::{Error, MintDatabase};
|
||||||
use crate::dhke::hash_to_curve;
|
use crate::dhke::hash_to_curve;
|
||||||
@@ -19,17 +20,18 @@ use crate::types::LnKey;
|
|||||||
|
|
||||||
/// Mint Memory Database
|
/// Mint Memory Database
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub struct MintMemoryDatabase {
|
pub struct MintMemoryDatabase {
|
||||||
active_keysets: Arc<RwLock<HashMap<CurrencyUnit, Id>>>,
|
active_keysets: Arc<RwLock<HashMap<CurrencyUnit, Id>>>,
|
||||||
keysets: Arc<RwLock<HashMap<Id, MintKeySetInfo>>>,
|
keysets: Arc<RwLock<HashMap<Id, MintKeySetInfo>>>,
|
||||||
mint_quotes: Arc<RwLock<HashMap<String, MintQuote>>>,
|
mint_quotes: Arc<RwLock<HashMap<Uuid, MintQuote>>>,
|
||||||
melt_quotes: Arc<RwLock<HashMap<String, mint::MeltQuote>>>,
|
melt_quotes: Arc<RwLock<HashMap<Uuid, mint::MeltQuote>>>,
|
||||||
proofs: Arc<RwLock<HashMap<[u8; 33], Proof>>>,
|
proofs: Arc<RwLock<HashMap<[u8; 33], Proof>>>,
|
||||||
proof_state: Arc<Mutex<HashMap<[u8; 33], nut07::State>>>,
|
proof_state: Arc<Mutex<HashMap<[u8; 33], nut07::State>>>,
|
||||||
quote_proofs: Arc<Mutex<HashMap<String, Vec<PublicKey>>>>,
|
quote_proofs: Arc<Mutex<HashMap<Uuid, Vec<PublicKey>>>>,
|
||||||
blinded_signatures: Arc<RwLock<HashMap<[u8; 33], BlindSignature>>>,
|
blinded_signatures: Arc<RwLock<HashMap<[u8; 33], BlindSignature>>>,
|
||||||
quote_signatures: Arc<RwLock<HashMap<String, Vec<BlindSignature>>>>,
|
quote_signatures: Arc<RwLock<HashMap<Uuid, Vec<BlindSignature>>>>,
|
||||||
melt_requests: Arc<RwLock<HashMap<String, (MeltBolt11Request, LnKey)>>>,
|
melt_requests: Arc<RwLock<HashMap<Uuid, (MeltBolt11Request<Uuid>, LnKey)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MintMemoryDatabase {
|
impl MintMemoryDatabase {
|
||||||
@@ -42,10 +44,10 @@ impl MintMemoryDatabase {
|
|||||||
melt_quotes: Vec<mint::MeltQuote>,
|
melt_quotes: Vec<mint::MeltQuote>,
|
||||||
pending_proofs: Proofs,
|
pending_proofs: Proofs,
|
||||||
spent_proofs: Proofs,
|
spent_proofs: Proofs,
|
||||||
quote_proofs: HashMap<String, Vec<PublicKey>>,
|
quote_proofs: HashMap<Uuid, Vec<PublicKey>>,
|
||||||
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
||||||
quote_signatures: HashMap<String, Vec<BlindSignature>>,
|
quote_signatures: HashMap<Uuid, Vec<BlindSignature>>,
|
||||||
melt_request: Vec<(MeltBolt11Request, LnKey)>,
|
melt_request: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut proofs = HashMap::new();
|
let mut proofs = HashMap::new();
|
||||||
let mut proof_states = HashMap::new();
|
let mut proof_states = HashMap::new();
|
||||||
@@ -64,7 +66,7 @@ impl MintMemoryDatabase {
|
|||||||
|
|
||||||
let melt_requests = melt_request
|
let melt_requests = melt_request
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(request, ln_key)| (request.quote.clone(), (request, ln_key)))
|
.map(|(request, ln_key)| (request.quote, (request, ln_key)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -73,10 +75,10 @@ impl MintMemoryDatabase {
|
|||||||
keysets.into_iter().map(|k| (k.id, k)).collect(),
|
keysets.into_iter().map(|k| (k.id, k)).collect(),
|
||||||
)),
|
)),
|
||||||
mint_quotes: Arc::new(RwLock::new(
|
mint_quotes: Arc::new(RwLock::new(
|
||||||
mint_quotes.into_iter().map(|q| (q.id.clone(), q)).collect(),
|
mint_quotes.into_iter().map(|q| (q.id, q)).collect(),
|
||||||
)),
|
)),
|
||||||
melt_quotes: Arc::new(RwLock::new(
|
melt_quotes: Arc::new(RwLock::new(
|
||||||
melt_quotes.into_iter().map(|q| (q.id.clone(), q)).collect(),
|
melt_quotes.into_iter().map(|q| (q.id, q)).collect(),
|
||||||
)),
|
)),
|
||||||
proofs: Arc::new(RwLock::new(proofs)),
|
proofs: Arc::new(RwLock::new(proofs)),
|
||||||
proof_state: Arc::new(Mutex::new(proof_states)),
|
proof_state: Arc::new(Mutex::new(proof_states)),
|
||||||
@@ -119,20 +121,17 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
|
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
|
||||||
self.mint_quotes
|
self.mint_quotes.write().await.insert(quote.id, quote);
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.insert(quote.id.clone(), quote);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
|
async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintQuote>, Self::Err> {
|
||||||
Ok(self.mint_quotes.read().await.get(quote_id).cloned())
|
Ok(self.mint_quotes.read().await.get(quote_id).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_mint_quote_state(
|
async fn update_mint_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MintQuoteState,
|
state: MintQuoteState,
|
||||||
) -> Result<MintQuoteState, Self::Err> {
|
) -> Result<MintQuoteState, Self::Err> {
|
||||||
let mut mint_quotes = self.mint_quotes.write().await;
|
let mut mint_quotes = self.mint_quotes.write().await;
|
||||||
@@ -146,7 +145,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
|
|
||||||
quote.state = state;
|
quote.state = state;
|
||||||
|
|
||||||
mint_quotes.insert(quote_id.to_string(), quote.clone());
|
mint_quotes.insert(*quote_id, quote.clone());
|
||||||
|
|
||||||
Ok(current_state)
|
Ok(current_state)
|
||||||
}
|
}
|
||||||
@@ -186,27 +185,24 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
Ok(self.mint_quotes.read().await.values().cloned().collect())
|
Ok(self.mint_quotes.read().await.values().cloned().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err> {
|
||||||
self.mint_quotes.write().await.remove(quote_id);
|
self.mint_quotes.write().await.remove(quote_id);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err> {
|
async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err> {
|
||||||
self.melt_quotes
|
self.melt_quotes.write().await.insert(quote.id, quote);
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.insert(quote.id.clone(), quote);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<mint::MeltQuote>, Self::Err> {
|
async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, Self::Err> {
|
||||||
Ok(self.melt_quotes.read().await.get(quote_id).cloned())
|
Ok(self.melt_quotes.read().await.get(quote_id).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_melt_quote_state(
|
async fn update_melt_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MeltQuoteState,
|
state: MeltQuoteState,
|
||||||
) -> Result<MeltQuoteState, Self::Err> {
|
) -> Result<MeltQuoteState, Self::Err> {
|
||||||
let mut melt_quotes = self.melt_quotes.write().await;
|
let mut melt_quotes = self.melt_quotes.write().await;
|
||||||
@@ -220,7 +216,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
|
|
||||||
quote.state = state;
|
quote.state = state;
|
||||||
|
|
||||||
melt_quotes.insert(quote_id.to_string(), quote.clone());
|
melt_quotes.insert(*quote_id, quote.clone());
|
||||||
|
|
||||||
Ok(current_state)
|
Ok(current_state)
|
||||||
}
|
}
|
||||||
@@ -229,7 +225,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
Ok(self.melt_quotes.read().await.values().cloned().collect())
|
Ok(self.melt_quotes.read().await.values().cloned().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err> {
|
||||||
self.melt_quotes.write().await.remove(quote_id);
|
self.melt_quotes.write().await.remove(quote_id);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -237,18 +233,18 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
|
|
||||||
async fn add_melt_request(
|
async fn add_melt_request(
|
||||||
&self,
|
&self,
|
||||||
melt_request: MeltBolt11Request,
|
melt_request: MeltBolt11Request<Uuid>,
|
||||||
ln_key: LnKey,
|
ln_key: LnKey,
|
||||||
) -> Result<(), Self::Err> {
|
) -> Result<(), Self::Err> {
|
||||||
let mut melt_requests = self.melt_requests.write().await;
|
let mut melt_requests = self.melt_requests.write().await;
|
||||||
melt_requests.insert(melt_request.quote.clone(), (melt_request, ln_key));
|
melt_requests.insert(melt_request.quote, (melt_request, ln_key));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_melt_request(
|
async fn get_melt_request(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Option<(MeltBolt11Request, LnKey)>, Self::Err> {
|
) -> Result<Option<(MeltBolt11Request<Uuid>, LnKey)>, Self::Err> {
|
||||||
let melt_requests = self.melt_requests.read().await;
|
let melt_requests = self.melt_requests.read().await;
|
||||||
|
|
||||||
let melt_request = melt_requests.get(quote_id);
|
let melt_request = melt_requests.get(quote_id);
|
||||||
@@ -256,7 +252,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
Ok(melt_request.cloned())
|
Ok(melt_request.cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<String>) -> Result<(), Self::Err> {
|
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err> {
|
||||||
let mut db_proofs = self.proofs.write().await;
|
let mut db_proofs = self.proofs.write().await;
|
||||||
|
|
||||||
let mut ys = Vec::with_capacity(proofs.capacity());
|
let mut ys = Vec::with_capacity(proofs.capacity());
|
||||||
@@ -293,7 +289,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
Ok(proofs)
|
Ok(proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_proof_ys_by_quote_id(&self, quote_id: &str) -> Result<Vec<PublicKey>, Self::Err> {
|
async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, Self::Err> {
|
||||||
let quote_proofs = &__self.quote_proofs.lock().await;
|
let quote_proofs = &__self.quote_proofs.lock().await;
|
||||||
|
|
||||||
match quote_proofs.get(quote_id) {
|
match quote_proofs.get(quote_id) {
|
||||||
@@ -360,7 +356,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
&self,
|
&self,
|
||||||
blinded_message: &[PublicKey],
|
blinded_message: &[PublicKey],
|
||||||
blind_signatures: &[BlindSignature],
|
blind_signatures: &[BlindSignature],
|
||||||
quote_id: Option<String>,
|
quote_id: Option<Uuid>,
|
||||||
) -> Result<(), Self::Err> {
|
) -> Result<(), Self::Err> {
|
||||||
let mut current_blinded_signatures = self.blinded_signatures.write().await;
|
let mut current_blinded_signatures = self.blinded_signatures.write().await;
|
||||||
|
|
||||||
@@ -370,7 +366,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
|
|
||||||
if let Some(quote_id) = quote_id {
|
if let Some(quote_id) = quote_id {
|
||||||
let mut current_quote_signatures = self.quote_signatures.write().await;
|
let mut current_quote_signatures = self.quote_signatures.write().await;
|
||||||
current_quote_signatures.insert(quote_id.clone(), blind_signatures.to_vec());
|
current_quote_signatures.insert(quote_id, blind_signatures.to_vec());
|
||||||
let t = current_quote_signatures.get("e_id);
|
let t = current_quote_signatures.get("e_id);
|
||||||
println!("after insert: {:?}", t);
|
println!("after insert: {:?}", t);
|
||||||
}
|
}
|
||||||
@@ -411,7 +407,7 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
/// 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,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Vec<BlindSignature>, Self::Err> {
|
) -> Result<Vec<BlindSignature>, Self::Err> {
|
||||||
let ys = self.quote_signatures.read().await;
|
let ys = self.quote_signatures.read().await;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ use std::fmt::Debug;
|
|||||||
#[cfg(any(feature = "wallet", feature = "mint"))]
|
#[cfg(any(feature = "wallet", feature = "mint"))]
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
#[cfg(feature = "mint")]
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
use crate::mint;
|
use crate::mint;
|
||||||
@@ -187,11 +189,11 @@ pub trait MintDatabase {
|
|||||||
/// 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>;
|
||||||
/// Get [`MintMintQuote`]
|
/// Get [`MintMintQuote`]
|
||||||
async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintMintQuote>, Self::Err>;
|
async fn get_mint_quote(&self, quote_id: &Uuid) -> Result<Option<MintMintQuote>, Self::Err>;
|
||||||
/// Update state of [`MintMintQuote`]
|
/// Update state of [`MintMintQuote`]
|
||||||
async fn update_mint_quote_state(
|
async fn update_mint_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MintQuoteState,
|
state: MintQuoteState,
|
||||||
) -> Result<MintQuoteState, Self::Err>;
|
) -> Result<MintQuoteState, Self::Err>;
|
||||||
/// Get all [`MintMintQuote`]s
|
/// Get all [`MintMintQuote`]s
|
||||||
@@ -207,34 +209,34 @@ pub trait MintDatabase {
|
|||||||
/// Get Mint Quotes
|
/// Get Mint Quotes
|
||||||
async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
|
async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
|
||||||
/// Remove [`MintMintQuote`]
|
/// Remove [`MintMintQuote`]
|
||||||
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err>;
|
async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err>;
|
||||||
|
|
||||||
/// Add [`mint::MeltQuote`]
|
/// Add [`mint::MeltQuote`]
|
||||||
async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
|
async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err>;
|
||||||
/// Get [`mint::MeltQuote`]
|
/// Get [`mint::MeltQuote`]
|
||||||
async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<mint::MeltQuote>, Self::Err>;
|
async fn get_melt_quote(&self, quote_id: &Uuid) -> Result<Option<mint::MeltQuote>, Self::Err>;
|
||||||
/// Update [`mint::MeltQuote`] state
|
/// Update [`mint::MeltQuote`] state
|
||||||
async fn update_melt_quote_state(
|
async fn update_melt_quote_state(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
state: MeltQuoteState,
|
state: MeltQuoteState,
|
||||||
) -> Result<MeltQuoteState, Self::Err>;
|
) -> Result<MeltQuoteState, Self::Err>;
|
||||||
/// Get all [`mint::MeltQuote`]s
|
/// Get all [`mint::MeltQuote`]s
|
||||||
async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
|
async fn get_melt_quotes(&self) -> Result<Vec<mint::MeltQuote>, Self::Err>;
|
||||||
/// Remove [`mint::MeltQuote`]
|
/// Remove [`mint::MeltQuote`]
|
||||||
async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err>;
|
async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err>;
|
||||||
|
|
||||||
/// Add melt request
|
/// Add melt request
|
||||||
async fn add_melt_request(
|
async fn add_melt_request(
|
||||||
&self,
|
&self,
|
||||||
melt_request: MeltBolt11Request,
|
melt_request: MeltBolt11Request<Uuid>,
|
||||||
ln_key: LnKey,
|
ln_key: LnKey,
|
||||||
) -> Result<(), Self::Err>;
|
) -> Result<(), Self::Err>;
|
||||||
/// Get melt request
|
/// Get melt request
|
||||||
async fn get_melt_request(
|
async fn get_melt_request(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Option<(MeltBolt11Request, LnKey)>, Self::Err>;
|
) -> Result<Option<(MeltBolt11Request<Uuid>, LnKey)>, Self::Err>;
|
||||||
|
|
||||||
/// Add [`MintKeySetInfo`]
|
/// Add [`MintKeySetInfo`]
|
||||||
async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err>;
|
async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err>;
|
||||||
@@ -244,11 +246,11 @@ pub trait MintDatabase {
|
|||||||
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
|
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
|
||||||
|
|
||||||
/// Add spent [`Proofs`]
|
/// Add spent [`Proofs`]
|
||||||
async fn add_proofs(&self, proof: Proofs, quote_id: Option<String>) -> Result<(), Self::Err>;
|
async fn add_proofs(&self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>;
|
||||||
/// Get [`Proofs`] by ys
|
/// Get [`Proofs`] by ys
|
||||||
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
|
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
|
||||||
/// Get ys by quote id
|
/// Get ys by quote id
|
||||||
async fn get_proof_ys_by_quote_id(&self, quote_id: &str) -> Result<Vec<PublicKey>, Self::Err>;
|
async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result<Vec<PublicKey>, Self::Err>;
|
||||||
/// Get [`Proofs`] state
|
/// Get [`Proofs`] state
|
||||||
async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
|
async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
|
||||||
/// Get [`Proofs`] state
|
/// Get [`Proofs`] state
|
||||||
@@ -268,7 +270,7 @@ pub trait MintDatabase {
|
|||||||
&self,
|
&self,
|
||||||
blinded_messages: &[PublicKey],
|
blinded_messages: &[PublicKey],
|
||||||
blind_signatures: &[BlindSignature],
|
blind_signatures: &[BlindSignature],
|
||||||
quote_id: Option<String>,
|
quote_id: Option<Uuid>,
|
||||||
) -> Result<(), Self::Err>;
|
) -> Result<(), Self::Err>;
|
||||||
/// Get [`BlindSignature`]s
|
/// Get [`BlindSignature`]s
|
||||||
async fn get_blind_signatures(
|
async fn get_blind_signatures(
|
||||||
@@ -283,6 +285,6 @@ pub trait MintDatabase {
|
|||||||
/// 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,
|
||||||
quote_id: &str,
|
quote_id: &Uuid,
|
||||||
) -> Result<Vec<BlindSignature>, Self::Err>;
|
) -> Result<Vec<BlindSignature>, Self::Err>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::str::FromStr;
|
|||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use lightning_invoice::Bolt11Invoice;
|
use lightning_invoice::Bolt11Invoice;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
CurrencyUnit, MeltBolt11Request, MeltQuote, MeltQuoteBolt11Request, MeltQuoteBolt11Response,
|
CurrencyUnit, MeltBolt11Request, MeltQuote, MeltQuoteBolt11Request, MeltQuoteBolt11Response,
|
||||||
@@ -53,7 +54,7 @@ impl Mint {
|
|||||||
pub async fn get_melt_bolt11_quote(
|
pub async fn get_melt_bolt11_quote(
|
||||||
&self,
|
&self,
|
||||||
melt_request: &MeltQuoteBolt11Request,
|
melt_request: &MeltQuoteBolt11Request,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<Uuid>, Error> {
|
||||||
let MeltQuoteBolt11Request {
|
let MeltQuoteBolt11Request {
|
||||||
request,
|
request,
|
||||||
unit,
|
unit,
|
||||||
@@ -117,7 +118,10 @@ impl Mint {
|
|||||||
|
|
||||||
/// Check melt quote status
|
/// Check melt quote status
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn check_melt_quote(&self, quote_id: &str) -> Result<MeltQuoteBolt11Response, Error> {
|
pub async fn check_melt_quote(
|
||||||
|
&self,
|
||||||
|
quote_id: &Uuid,
|
||||||
|
) -> Result<MeltQuoteBolt11Response<Uuid>, Error> {
|
||||||
let quote = self
|
let quote = self
|
||||||
.localstore
|
.localstore
|
||||||
.get_melt_quote(quote_id)
|
.get_melt_quote(quote_id)
|
||||||
@@ -159,7 +163,7 @@ impl Mint {
|
|||||||
|
|
||||||
/// Remove melt quote
|
/// Remove melt quote
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Error> {
|
pub async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Error> {
|
||||||
self.localstore.remove_melt_quote(quote_id).await?;
|
self.localstore.remove_melt_quote(quote_id).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -170,7 +174,7 @@ impl Mint {
|
|||||||
pub async fn check_melt_expected_ln_fees(
|
pub async fn check_melt_expected_ln_fees(
|
||||||
&self,
|
&self,
|
||||||
melt_quote: &MeltQuote,
|
melt_quote: &MeltQuote,
|
||||||
melt_request: &MeltBolt11Request,
|
melt_request: &MeltBolt11Request<Uuid>,
|
||||||
) -> Result<Option<Amount>, Error> {
|
) -> Result<Option<Amount>, Error> {
|
||||||
let invoice = Bolt11Invoice::from_str(&melt_quote.request)?;
|
let invoice = Bolt11Invoice::from_str(&melt_quote.request)?;
|
||||||
|
|
||||||
@@ -226,7 +230,7 @@ impl Mint {
|
|||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn verify_melt_request(
|
pub async fn verify_melt_request(
|
||||||
&self,
|
&self,
|
||||||
melt_request: &MeltBolt11Request,
|
melt_request: &MeltBolt11Request<Uuid>,
|
||||||
) -> Result<MeltQuote, Error> {
|
) -> Result<MeltQuote, Error> {
|
||||||
let state = self
|
let state = self
|
||||||
.localstore
|
.localstore
|
||||||
@@ -248,10 +252,7 @@ impl Mint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.localstore
|
self.localstore
|
||||||
.add_proofs(
|
.add_proofs(melt_request.inputs.clone(), Some(melt_request.quote))
|
||||||
melt_request.inputs.clone(),
|
|
||||||
Some(melt_request.quote.clone()),
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
self.check_ys_spendable(&ys, State::Pending).await?;
|
self.check_ys_spendable(&ys, State::Pending).await?;
|
||||||
|
|
||||||
@@ -345,7 +346,10 @@ impl Mint {
|
|||||||
/// made The [`Proofs`] should be returned to an unspent state and the
|
/// made The [`Proofs`] should be returned to an unspent state and the
|
||||||
/// quote should be unpaid
|
/// quote should be unpaid
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn process_unpaid_melt(&self, melt_request: &MeltBolt11Request) -> Result<(), Error> {
|
pub async fn process_unpaid_melt(
|
||||||
|
&self,
|
||||||
|
melt_request: &MeltBolt11Request<Uuid>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let input_ys = melt_request.inputs.ys()?;
|
let input_ys = melt_request.inputs.ys()?;
|
||||||
|
|
||||||
self.localstore
|
self.localstore
|
||||||
@@ -373,8 +377,8 @@ impl Mint {
|
|||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn melt_bolt11(
|
pub async fn melt_bolt11(
|
||||||
&self,
|
&self,
|
||||||
melt_request: &MeltBolt11Request,
|
melt_request: &MeltBolt11Request<Uuid>,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<Uuid>, Error> {
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
async fn check_payment_state(
|
async fn check_payment_state(
|
||||||
ln: Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
|
ln: Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
|
||||||
@@ -584,10 +588,10 @@ impl Mint {
|
|||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn process_melt_request(
|
pub async fn process_melt_request(
|
||||||
&self,
|
&self,
|
||||||
melt_request: &MeltBolt11Request,
|
melt_request: &MeltBolt11Request<Uuid>,
|
||||||
payment_preimage: Option<String>,
|
payment_preimage: Option<String>,
|
||||||
total_spent: Amount,
|
total_spent: Amount,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<Uuid>, Error> {
|
||||||
tracing::debug!("Processing melt quote: {}", melt_request.quote);
|
tracing::debug!("Processing melt quote: {}", melt_request.quote);
|
||||||
|
|
||||||
let quote = self
|
let quote = self
|
||||||
@@ -673,7 +677,7 @@ impl Mint {
|
|||||||
.map(|o| o.blinded_secret)
|
.map(|o| o.blinded_secret)
|
||||||
.collect::<Vec<PublicKey>>(),
|
.collect::<Vec<PublicKey>>(),
|
||||||
&change_sigs,
|
&change_sigs,
|
||||||
Some(quote.id.clone()),
|
Some(quote.id),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
nut04, CurrencyUnit, Mint, MintQuote, MintQuoteBolt11Request, MintQuoteBolt11Response,
|
nut04, CurrencyUnit, Mint, MintQuote, MintQuoteBolt11Request, MintQuoteBolt11Response,
|
||||||
@@ -59,7 +60,7 @@ impl Mint {
|
|||||||
pub async fn get_mint_bolt11_quote(
|
pub async fn get_mint_bolt11_quote(
|
||||||
&self,
|
&self,
|
||||||
mint_quote_request: MintQuoteBolt11Request,
|
mint_quote_request: MintQuoteBolt11Request,
|
||||||
) -> Result<MintQuoteBolt11Response, Error> {
|
) -> Result<MintQuoteBolt11Response<Uuid>, Error> {
|
||||||
let MintQuoteBolt11Request {
|
let MintQuoteBolt11Request {
|
||||||
amount,
|
amount,
|
||||||
unit,
|
unit,
|
||||||
@@ -116,7 +117,7 @@ impl Mint {
|
|||||||
|
|
||||||
self.localstore.add_mint_quote(quote.clone()).await?;
|
self.localstore.add_mint_quote(quote.clone()).await?;
|
||||||
|
|
||||||
let quote: MintQuoteBolt11Response = quote.into();
|
let quote: MintQuoteBolt11Response<Uuid> = quote.into();
|
||||||
|
|
||||||
self.pubsub_manager
|
self.pubsub_manager
|
||||||
.broadcast(NotificationPayload::MintQuoteBolt11Response(quote.clone()));
|
.broadcast(NotificationPayload::MintQuoteBolt11Response(quote.clone()));
|
||||||
@@ -126,7 +127,10 @@ impl Mint {
|
|||||||
|
|
||||||
/// Check mint quote
|
/// Check mint quote
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn check_mint_quote(&self, quote_id: &str) -> Result<MintQuoteBolt11Response, Error> {
|
pub async fn check_mint_quote(
|
||||||
|
&self,
|
||||||
|
quote_id: &Uuid,
|
||||||
|
) -> Result<MintQuoteBolt11Response<Uuid>, Error> {
|
||||||
let quote = self
|
let quote = self
|
||||||
.localstore
|
.localstore
|
||||||
.get_mint_quote(quote_id)
|
.get_mint_quote(quote_id)
|
||||||
@@ -187,7 +191,7 @@ impl Mint {
|
|||||||
|
|
||||||
/// Remove mint quote
|
/// Remove mint quote
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Error> {
|
pub async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Error> {
|
||||||
self.localstore.remove_mint_quote(quote_id).await?;
|
self.localstore.remove_mint_quote(quote_id).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -250,7 +254,7 @@ impl Mint {
|
|||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn process_mint_request(
|
pub async fn process_mint_request(
|
||||||
&self,
|
&self,
|
||||||
mint_request: nut04::MintBolt11Request,
|
mint_request: nut04::MintBolt11Request<Uuid>,
|
||||||
) -> Result<nut04::MintBolt11Response, Error> {
|
) -> Result<nut04::MintBolt11Response, Error> {
|
||||||
let mint_quote =
|
let mint_quote =
|
||||||
if let Some(mint_quote) = self.localstore.get_mint_quote(&mint_request.quote).await? {
|
if let Some(mint_quote) = self.localstore.get_mint_quote(&mint_request.quote).await? {
|
||||||
@@ -321,7 +325,7 @@ impl Mint {
|
|||||||
.map(|p| p.blinded_secret)
|
.map(|p| p.blinded_secret)
|
||||||
.collect::<Vec<PublicKey>>(),
|
.collect::<Vec<PublicKey>>(),
|
||||||
&blind_signatures,
|
&blind_signatures,
|
||||||
Some(mint_request.quote.clone()),
|
Some(mint_request.quote),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tokio::sync::{Notify, RwLock};
|
use tokio::sync::{Notify, RwLock};
|
||||||
use tokio::task::JoinSet;
|
use tokio::task::JoinSet;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::cdk_database::{self, MintDatabase};
|
use crate::cdk_database::{self, MintDatabase};
|
||||||
use crate::cdk_lightning::{self, MintLightning};
|
use crate::cdk_lightning::{self, MintLightning};
|
||||||
@@ -380,7 +381,7 @@ impl Mint {
|
|||||||
pub async fn handle_internal_melt_mint(
|
pub async fn handle_internal_melt_mint(
|
||||||
&self,
|
&self,
|
||||||
melt_quote: &MeltQuote,
|
melt_quote: &MeltQuote,
|
||||||
melt_request: &MeltBolt11Request,
|
melt_request: &MeltBolt11Request<Uuid>,
|
||||||
) -> Result<Option<Amount>, Error> {
|
) -> Result<Option<Amount>, Error> {
|
||||||
let mint_quote = match self
|
let mint_quote = match self
|
||||||
.localstore
|
.localstore
|
||||||
@@ -608,6 +609,7 @@ mod tests {
|
|||||||
|
|
||||||
use bitcoin::Network;
|
use bitcoin::Network;
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::Secp256k1;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::types::LnKey;
|
use crate::types::LnKey;
|
||||||
@@ -709,13 +711,13 @@ mod tests {
|
|||||||
pending_proofs: Proofs,
|
pending_proofs: Proofs,
|
||||||
spent_proofs: Proofs,
|
spent_proofs: Proofs,
|
||||||
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
||||||
quote_proofs: HashMap<String, Vec<PublicKey>>,
|
quote_proofs: HashMap<Uuid, Vec<PublicKey>>,
|
||||||
quote_signatures: HashMap<String, Vec<BlindSignature>>,
|
quote_signatures: HashMap<Uuid, Vec<BlindSignature>>,
|
||||||
mint_url: &'a str,
|
mint_url: &'a str,
|
||||||
seed: &'a [u8],
|
seed: &'a [u8],
|
||||||
mint_info: MintInfo,
|
mint_info: MintInfo,
|
||||||
supported_units: HashMap<CurrencyUnit, (u64, u8)>,
|
supported_units: HashMap<CurrencyUnit, (u64, u8)>,
|
||||||
melt_requests: Vec<(MeltBolt11Request, LnKey)>,
|
melt_requests: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
|
||||||
quote_ttl: QuoteTTL,
|
quote_ttl: QuoteTTL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::Amount;
|
|||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MintQuote {
|
pub struct MintQuote {
|
||||||
/// Quote id
|
/// Quote id
|
||||||
pub id: String,
|
pub id: Uuid,
|
||||||
/// Mint Url
|
/// Mint Url
|
||||||
pub mint_url: MintUrl,
|
pub mint_url: MintUrl,
|
||||||
/// Amount of quote
|
/// Amount of quote
|
||||||
@@ -43,7 +43,7 @@ impl MintQuote {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
mint_url,
|
mint_url,
|
||||||
id: id.to_string(),
|
id,
|
||||||
amount,
|
amount,
|
||||||
unit,
|
unit,
|
||||||
request,
|
request,
|
||||||
@@ -58,7 +58,7 @@ impl MintQuote {
|
|||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MeltQuote {
|
pub struct MeltQuote {
|
||||||
/// Quote id
|
/// Quote id
|
||||||
pub id: String,
|
pub id: Uuid,
|
||||||
/// Quote unit
|
/// Quote unit
|
||||||
pub unit: CurrencyUnit,
|
pub unit: CurrencyUnit,
|
||||||
/// Quote amount
|
/// Quote amount
|
||||||
@@ -90,7 +90,7 @@ impl MeltQuote {
|
|||||||
let id = Uuid::new_v4();
|
let id = Uuid::new_v4();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: id.to_string(),
|
id,
|
||||||
amount,
|
amount,
|
||||||
unit,
|
unit,
|
||||||
request,
|
request,
|
||||||
|
|||||||
@@ -5,8 +5,11 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
#[cfg(feature = "mint")]
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod};
|
use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod};
|
||||||
use super::MintQuoteState;
|
use super::MintQuoteState;
|
||||||
@@ -81,9 +84,10 @@ impl FromStr for QuoteState {
|
|||||||
/// Mint quote response [NUT-04]
|
/// Mint quote response [NUT-04]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
||||||
pub struct MintQuoteBolt11Response {
|
#[serde(bound = "Q: Serialize + DeserializeOwned")]
|
||||||
|
pub struct MintQuoteBolt11Response<Q> {
|
||||||
/// Quote Id
|
/// Quote Id
|
||||||
pub quote: String,
|
pub quote: Q,
|
||||||
/// Payment request to fulfil
|
/// Payment request to fulfil
|
||||||
pub request: String,
|
pub request: String,
|
||||||
/// Quote State
|
/// Quote State
|
||||||
@@ -93,8 +97,8 @@ pub struct MintQuoteBolt11Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
impl From<crate::mint::MintQuote> for MintQuoteBolt11Response {
|
impl From<crate::mint::MintQuote> for MintQuoteBolt11Response<Uuid> {
|
||||||
fn from(mint_quote: crate::mint::MintQuote) -> MintQuoteBolt11Response {
|
fn from(mint_quote: crate::mint::MintQuote) -> MintQuoteBolt11Response<Uuid> {
|
||||||
MintQuoteBolt11Response {
|
MintQuoteBolt11Response {
|
||||||
quote: mint_quote.id,
|
quote: mint_quote.id,
|
||||||
request: mint_quote.request,
|
request: mint_quote.request,
|
||||||
@@ -107,16 +111,17 @@ impl From<crate::mint::MintQuote> for MintQuoteBolt11Response {
|
|||||||
/// Mint request [NUT-04]
|
/// Mint request [NUT-04]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
||||||
pub struct MintBolt11Request {
|
#[serde(bound = "Q: Serialize + DeserializeOwned")]
|
||||||
|
pub struct MintBolt11Request<Q> {
|
||||||
/// Quote id
|
/// Quote id
|
||||||
#[cfg_attr(feature = "swagger", schema(max_length = 1_000))]
|
#[cfg_attr(feature = "swagger", schema(max_length = 1_000))]
|
||||||
pub quote: String,
|
pub quote: Q,
|
||||||
/// Outputs
|
/// Outputs
|
||||||
#[cfg_attr(feature = "swagger", schema(max_items = 1_000))]
|
#[cfg_attr(feature = "swagger", schema(max_items = 1_000))]
|
||||||
pub outputs: Vec<BlindedMessage>,
|
pub outputs: Vec<BlindedMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MintBolt11Request {
|
impl<Q> MintBolt11Request<Q> {
|
||||||
/// Total [`Amount`] of outputs
|
/// Total [`Amount`] of outputs
|
||||||
pub fn total_amount(&self) -> Result<Amount, Error> {
|
pub fn total_amount(&self) -> Result<Amount, Error> {
|
||||||
Amount::try_sum(
|
Amount::try_sum(
|
||||||
|
|||||||
@@ -5,9 +5,12 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
#[cfg(feature = "mint")]
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod, Proofs};
|
use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod, Proofs};
|
||||||
use super::nut15::Mpp;
|
use super::nut15::Mpp;
|
||||||
@@ -88,9 +91,10 @@ impl FromStr for QuoteState {
|
|||||||
/// Melt quote response [NUT-05]
|
/// Melt quote response [NUT-05]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||||
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
||||||
pub struct MeltQuoteBolt11Response {
|
#[serde(bound = "Q: Serialize")]
|
||||||
|
pub struct MeltQuoteBolt11Response<Q> {
|
||||||
/// Quote Id
|
/// Quote Id
|
||||||
pub quote: String,
|
pub quote: Q,
|
||||||
/// The amount that needs to be provided
|
/// The amount that needs to be provided
|
||||||
pub amount: Amount,
|
pub amount: Amount,
|
||||||
/// The fee reserve that is required
|
/// The fee reserve that is required
|
||||||
@@ -112,10 +116,10 @@ pub struct MeltQuoteBolt11Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
impl From<&MeltQuote> for MeltQuoteBolt11Response {
|
impl From<&MeltQuote> for MeltQuoteBolt11Response<Uuid> {
|
||||||
fn from(melt_quote: &MeltQuote) -> MeltQuoteBolt11Response {
|
fn from(melt_quote: &MeltQuote) -> MeltQuoteBolt11Response<Uuid> {
|
||||||
MeltQuoteBolt11Response {
|
MeltQuoteBolt11Response {
|
||||||
quote: melt_quote.id.clone(),
|
quote: melt_quote.id,
|
||||||
payment_preimage: None,
|
payment_preimage: None,
|
||||||
change: None,
|
change: None,
|
||||||
state: melt_quote.state,
|
state: melt_quote.state,
|
||||||
@@ -129,14 +133,14 @@ impl From<&MeltQuote> for MeltQuoteBolt11Response {
|
|||||||
|
|
||||||
// A custom deserializer is needed until all mints
|
// A custom deserializer is needed until all mints
|
||||||
// update some will return without the required state.
|
// update some will return without the required state.
|
||||||
impl<'de> Deserialize<'de> for MeltQuoteBolt11Response {
|
impl<'de, Q: DeserializeOwned> Deserialize<'de> for MeltQuoteBolt11Response<Q> {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let value = Value::deserialize(deserializer)?;
|
let value = Value::deserialize(deserializer)?;
|
||||||
|
|
||||||
let quote: String = serde_json::from_value(
|
let quote: Q = serde_json::from_value(
|
||||||
value
|
value
|
||||||
.get("quote")
|
.get("quote")
|
||||||
.ok_or(serde::de::Error::missing_field("quote"))?
|
.ok_or(serde::de::Error::missing_field("quote"))?
|
||||||
@@ -212,8 +216,8 @@ impl<'de> Deserialize<'de> for MeltQuoteBolt11Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
impl From<mint::MeltQuote> for MeltQuoteBolt11Response {
|
impl From<mint::MeltQuote> for MeltQuoteBolt11Response<Uuid> {
|
||||||
fn from(melt_quote: mint::MeltQuote) -> MeltQuoteBolt11Response {
|
fn from(melt_quote: mint::MeltQuote) -> MeltQuoteBolt11Response<Uuid> {
|
||||||
let paid = melt_quote.state == QuoteState::Paid;
|
let paid = melt_quote.state == QuoteState::Paid;
|
||||||
MeltQuoteBolt11Response {
|
MeltQuoteBolt11Response {
|
||||||
quote: melt_quote.id,
|
quote: melt_quote.id,
|
||||||
@@ -231,9 +235,10 @@ impl From<mint::MeltQuote> for MeltQuoteBolt11Response {
|
|||||||
/// Melt Bolt11 Request [NUT-05]
|
/// Melt Bolt11 Request [NUT-05]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
|
||||||
pub struct MeltBolt11Request {
|
#[serde(bound = "Q: Serialize + DeserializeOwned")]
|
||||||
|
pub struct MeltBolt11Request<Q> {
|
||||||
/// Quote ID
|
/// Quote ID
|
||||||
pub quote: String,
|
pub quote: Q,
|
||||||
/// Proofs
|
/// Proofs
|
||||||
#[cfg_attr(feature = "swagger", schema(value_type = Vec<Proof>))]
|
#[cfg_attr(feature = "swagger", schema(value_type = Vec<Proof>))]
|
||||||
pub inputs: Proofs,
|
pub inputs: Proofs,
|
||||||
@@ -242,7 +247,7 @@ pub struct MeltBolt11Request {
|
|||||||
pub outputs: Option<Vec<BlindedMessage>>,
|
pub outputs: Option<Vec<BlindedMessage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltBolt11Request {
|
impl<Q: Serialize + DeserializeOwned> MeltBolt11Request<Q> {
|
||||||
/// Total [`Amount`] of [`Proofs`]
|
/// Total [`Amount`] of [`Proofs`]
|
||||||
pub fn proofs_amount(&self) -> Result<Amount, Error> {
|
pub fn proofs_amount(&self) -> Result<Amount, Error> {
|
||||||
Amount::try_sum(self.inputs.iter().map(|proof| proof.amount))
|
Amount::try_sum(self.inputs.iter().map(|proof| proof.amount))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
use super::nut05::{MeltBolt11Request, MeltQuoteBolt11Response};
|
use super::nut05::{MeltBolt11Request, MeltQuoteBolt11Response};
|
||||||
use crate::Amount;
|
use crate::Amount;
|
||||||
|
|
||||||
impl MeltBolt11Request {
|
impl<Q> MeltBolt11Request<Q> {
|
||||||
/// Total output [`Amount`]
|
/// Total output [`Amount`]
|
||||||
pub fn output_amount(&self) -> Option<Amount> {
|
pub fn output_amount(&self) -> Option<Amount> {
|
||||||
self.outputs
|
self.outputs
|
||||||
@@ -14,7 +14,7 @@ impl MeltBolt11Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltQuoteBolt11Response {
|
impl<Q> MeltQuoteBolt11Response<Q> {
|
||||||
/// Total change [`Amount`]
|
/// Total change [`Amount`]
|
||||||
pub fn change_amount(&self) -> Option<Amount> {
|
pub fn change_amount(&self) -> Option<Amount> {
|
||||||
self.change
|
self.change
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! Specific Subscription for the cdk crate
|
//! Specific Subscription for the cdk crate
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -8,7 +9,9 @@ use serde::{Deserialize, Serialize};
|
|||||||
mod on_subscription;
|
mod on_subscription;
|
||||||
|
|
||||||
pub use on_subscription::OnSubscription;
|
pub use on_subscription::OnSubscription;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::PublicKey;
|
||||||
use crate::cdk_database::{self, MintDatabase};
|
use crate::cdk_database::{self, MintDatabase};
|
||||||
use crate::nuts::{
|
use crate::nuts::{
|
||||||
BlindSignature, CurrencyUnit, MeltQuoteBolt11Response, MeltQuoteState, MintQuoteBolt11Response,
|
BlindSignature, CurrencyUnit, MeltQuoteBolt11Response, MeltQuoteState, MintQuoteBolt11Response,
|
||||||
@@ -91,9 +94,9 @@ pub enum NotificationPayload {
|
|||||||
/// Proof State
|
/// Proof State
|
||||||
ProofState(ProofState),
|
ProofState(ProofState),
|
||||||
/// Melt Quote Bolt11 Response
|
/// Melt Quote Bolt11 Response
|
||||||
MeltQuoteBolt11Response(MeltQuoteBolt11Response),
|
MeltQuoteBolt11Response(MeltQuoteBolt11Response<Uuid>),
|
||||||
/// Mint Quote Bolt11 Response
|
/// Mint Quote Bolt11 Response
|
||||||
MintQuoteBolt11Response(MintQuoteBolt11Response),
|
MintQuoteBolt11Response(MintQuoteBolt11Response<Uuid>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ProofState> for NotificationPayload {
|
impl From<ProofState> for NotificationPayload {
|
||||||
@@ -102,37 +105,42 @@ impl From<ProofState> for NotificationPayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MeltQuoteBolt11Response> for NotificationPayload {
|
impl From<MeltQuoteBolt11Response<Uuid>> for NotificationPayload {
|
||||||
fn from(melt_quote: MeltQuoteBolt11Response) -> NotificationPayload {
|
fn from(melt_quote: MeltQuoteBolt11Response<Uuid>) -> NotificationPayload {
|
||||||
NotificationPayload::MeltQuoteBolt11Response(melt_quote)
|
NotificationPayload::MeltQuoteBolt11Response(melt_quote)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MintQuoteBolt11Response> for NotificationPayload {
|
impl From<MintQuoteBolt11Response<Uuid>> for NotificationPayload {
|
||||||
fn from(mint_quote: MintQuoteBolt11Response) -> NotificationPayload {
|
fn from(mint_quote: MintQuoteBolt11Response<Uuid>) -> NotificationPayload {
|
||||||
NotificationPayload::MintQuoteBolt11Response(mint_quote)
|
NotificationPayload::MintQuoteBolt11Response(mint_quote)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
/// A parsed notification
|
||||||
|
pub enum Notification {
|
||||||
|
/// ProofState id is a Pubkey
|
||||||
|
ProofState(PublicKey),
|
||||||
|
/// MeltQuote id is an Uuid
|
||||||
|
MeltQuoteBolt11(Uuid),
|
||||||
|
/// MintQuote id is an Uuid
|
||||||
|
MintQuoteBolt11(Uuid),
|
||||||
|
}
|
||||||
|
|
||||||
impl Indexable for NotificationPayload {
|
impl Indexable for NotificationPayload {
|
||||||
type Type = (String, Kind);
|
type Type = Notification;
|
||||||
|
|
||||||
fn to_indexes(&self) -> Vec<Index<Self::Type>> {
|
fn to_indexes(&self) -> Vec<Index<Self::Type>> {
|
||||||
match self {
|
match self {
|
||||||
NotificationPayload::ProofState(proof_state) => {
|
NotificationPayload::ProofState(proof_state) => {
|
||||||
vec![Index::from((proof_state.y.to_hex(), Kind::ProofState))]
|
vec![Index::from(Notification::ProofState(proof_state.y))]
|
||||||
}
|
}
|
||||||
NotificationPayload::MeltQuoteBolt11Response(melt_quote) => {
|
NotificationPayload::MeltQuoteBolt11Response(melt_quote) => {
|
||||||
vec![Index::from((
|
vec![Index::from(Notification::MeltQuoteBolt11(melt_quote.quote))]
|
||||||
melt_quote.quote.clone(),
|
|
||||||
Kind::Bolt11MeltQuote,
|
|
||||||
))]
|
|
||||||
}
|
}
|
||||||
NotificationPayload::MintQuoteBolt11Response(mint_quote) => {
|
NotificationPayload::MintQuoteBolt11Response(mint_quote) => {
|
||||||
vec![Index::from((
|
vec![Index::from(Notification::MintQuoteBolt11(mint_quote.quote))]
|
||||||
mint_quote.quote.clone(),
|
|
||||||
Kind::Bolt11MintQuote,
|
|
||||||
))]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,13 +165,27 @@ impl AsRef<SubId> for Params {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Params> for Vec<Index<(String, Kind)>> {
|
impl From<Params> for Vec<Index<Notification>> {
|
||||||
fn from(val: Params) -> Self {
|
fn from(val: Params) -> Self {
|
||||||
let sub_id: SubscriptionGlobalId = Default::default();
|
let sub_id: SubscriptionGlobalId = Default::default();
|
||||||
val.filters
|
val.filters
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|filter| Index::from(((filter.clone(), val.kind), val.id.clone(), sub_id)))
|
.map(|filter| {
|
||||||
.collect()
|
let idx = match val.kind {
|
||||||
|
Kind::Bolt11MeltQuote => {
|
||||||
|
Notification::MeltQuoteBolt11(Uuid::from_str(&filter)?)
|
||||||
|
}
|
||||||
|
Kind::Bolt11MintQuote => {
|
||||||
|
Notification::MintQuoteBolt11(Uuid::from_str(&filter)?)
|
||||||
|
}
|
||||||
|
Kind::ProofState => Notification::ProofState(PublicKey::from_str(&filter)?),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Index::from((idx, val.id.clone(), sub_id)))
|
||||||
|
})
|
||||||
|
.collect::<Result<_, anyhow::Error>>()
|
||||||
|
.unwrap()
|
||||||
|
// TODO don't unwrap, move to try from
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +194,7 @@ impl From<Params> for Vec<Index<(String, Kind)>> {
|
|||||||
///
|
///
|
||||||
/// Nut-17 implementation is system-wide and not only through the WebSocket, so
|
/// Nut-17 implementation is system-wide and not only through the WebSocket, so
|
||||||
/// it is possible for another part of the system to subscribe to events.
|
/// it is possible for another part of the system to subscribe to events.
|
||||||
pub struct PubSubManager(pub_sub::Manager<NotificationPayload, (String, Kind), OnSubscription>);
|
pub struct PubSubManager(pub_sub::Manager<NotificationPayload, Notification, OnSubscription>);
|
||||||
|
|
||||||
#[allow(clippy::default_constructed_unit_structs)]
|
#[allow(clippy::default_constructed_unit_structs)]
|
||||||
impl Default for PubSubManager {
|
impl Default for PubSubManager {
|
||||||
@@ -188,7 +210,7 @@ impl From<Arc<dyn MintDatabase<Err = cdk_database::Error> + Send + Sync>> for Pu
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for PubSubManager {
|
impl Deref for PubSubManager {
|
||||||
type Target = pub_sub::Manager<NotificationPayload, (String, Kind), OnSubscription>;
|
type Target = pub_sub::Manager<NotificationPayload, Notification, OnSubscription>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
@@ -202,7 +224,7 @@ impl PubSubManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function to emit a MintQuoteBolt11Response status
|
/// Helper function to emit a MintQuoteBolt11Response status
|
||||||
pub fn mint_quote_bolt11_status<E: Into<MintQuoteBolt11Response>>(
|
pub fn mint_quote_bolt11_status<E: Into<MintQuoteBolt11Response<Uuid>>>(
|
||||||
&self,
|
&self,
|
||||||
quote: E,
|
quote: E,
|
||||||
new_state: MintQuoteState,
|
new_state: MintQuoteState,
|
||||||
@@ -214,7 +236,7 @@ impl PubSubManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function to emit a MeltQuoteBolt11Response status
|
/// Helper function to emit a MeltQuoteBolt11Response status
|
||||||
pub fn melt_quote_status<E: Into<MeltQuoteBolt11Response>>(
|
pub fn melt_quote_status<E: Into<MeltQuoteBolt11Response<Uuid>>>(
|
||||||
&self,
|
&self,
|
||||||
quote: E,
|
quote: E,
|
||||||
payment_preimage: Option<String>,
|
payment_preimage: Option<String>,
|
||||||
@@ -244,7 +266,11 @@ mod test {
|
|||||||
let manager = PubSubManager::default();
|
let manager = PubSubManager::default();
|
||||||
let params = Params {
|
let params = Params {
|
||||||
kind: Kind::ProofState,
|
kind: Kind::ProofState,
|
||||||
filters: vec!["x".to_string()],
|
filters: vec![PublicKey::from_hex(
|
||||||
|
"02194603ffa36356f4a56b7df9371fc3192472351453ec7398b8da8117e7c3e104",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.to_string()],
|
||||||
id: "uno".into(),
|
id: "uno".into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
//! On Subscription
|
//! On Subscription
|
||||||
//!
|
//!
|
||||||
//! This module contains the code that is triggered when a new subscription is created.
|
//! This module contains the code that is triggered when a new subscription is created.
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Kind, NotificationPayload};
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::{Notification, NotificationPayload};
|
||||||
use crate::cdk_database::{self, MintDatabase};
|
use crate::cdk_database::{self, MintDatabase};
|
||||||
use crate::nuts::{MeltQuoteBolt11Response, MintQuoteBolt11Response, ProofState, PublicKey};
|
use crate::nuts::{MeltQuoteBolt11Response, MintQuoteBolt11Response, ProofState, PublicKey};
|
||||||
use crate::pub_sub::OnNewSubscription;
|
use crate::pub_sub::OnNewSubscription;
|
||||||
@@ -22,7 +23,7 @@ pub struct OnSubscription(
|
|||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl OnNewSubscription for OnSubscription {
|
impl OnNewSubscription for OnSubscription {
|
||||||
type Event = NotificationPayload;
|
type Event = NotificationPayload;
|
||||||
type Index = (String, Kind);
|
type Index = Notification;
|
||||||
|
|
||||||
async fn on_new_subscription(
|
async fn on_new_subscription(
|
||||||
&self,
|
&self,
|
||||||
@@ -35,76 +36,58 @@ impl OnNewSubscription for OnSubscription {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut to_return = vec![];
|
let mut to_return = vec![];
|
||||||
|
let mut public_keys: Vec<PublicKey> = Vec::new();
|
||||||
|
let mut melt_queries = Vec::new();
|
||||||
|
let mut mint_queries = Vec::new();
|
||||||
|
|
||||||
for (kind, values) in request.iter().fold(
|
for idx in request.iter() {
|
||||||
HashMap::new(),
|
match idx {
|
||||||
|mut acc: HashMap<&Kind, Vec<&String>>, (data, kind)| {
|
Notification::ProofState(pk) => public_keys.push(*pk),
|
||||||
acc.entry(kind).or_default().push(data);
|
Notification::MeltQuoteBolt11(uuid) => {
|
||||||
acc
|
melt_queries.push(datastore.get_melt_quote(uuid))
|
||||||
},
|
|
||||||
) {
|
|
||||||
match kind {
|
|
||||||
Kind::Bolt11MeltQuote => {
|
|
||||||
let queries = values
|
|
||||||
.iter()
|
|
||||||
.map(|id| datastore.get_melt_quote(id))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
to_return.extend(
|
|
||||||
futures::future::try_join_all(queries)
|
|
||||||
.await
|
|
||||||
.map(|quotes| {
|
|
||||||
quotes
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|quote| quote.map(|x| x.into()))
|
|
||||||
.map(|x: MeltQuoteBolt11Response| x.into())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.map_err(|e| e.to_string())?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Kind::Bolt11MintQuote => {
|
Notification::MintQuoteBolt11(uuid) => {
|
||||||
let queries = values
|
mint_queries.push(datastore.get_mint_quote(uuid))
|
||||||
.iter()
|
|
||||||
.map(|id| datastore.get_mint_quote(id))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
to_return.extend(
|
|
||||||
futures::future::try_join_all(queries)
|
|
||||||
.await
|
|
||||||
.map(|quotes| {
|
|
||||||
quotes
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|quote| quote.map(|x| x.into()))
|
|
||||||
.map(|x: MintQuoteBolt11Response| x.into())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.map_err(|e| e.to_string())?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Kind::ProofState => {
|
|
||||||
let public_keys = values
|
|
||||||
.iter()
|
|
||||||
.map(PublicKey::from_hex)
|
|
||||||
.collect::<Result<Vec<PublicKey>, _>>()
|
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
|
|
||||||
to_return.extend(
|
|
||||||
datastore
|
|
||||||
.get_proofs_states(&public_keys)
|
|
||||||
.await
|
|
||||||
.map_err(|e| e.to_string())?
|
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(idx, state)| {
|
|
||||||
state.map(|state| (public_keys[idx], state).into())
|
|
||||||
})
|
|
||||||
.map(|state: ProofState| state.into()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_return.extend(
|
||||||
|
futures::future::try_join_all(melt_queries)
|
||||||
|
.await
|
||||||
|
.map(|quotes| {
|
||||||
|
quotes
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|quote| quote.map(|x| x.into()))
|
||||||
|
.map(|x: MeltQuoteBolt11Response<Uuid>| x.into())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.map_err(|e| e.to_string())?,
|
||||||
|
);
|
||||||
|
to_return.extend(
|
||||||
|
futures::future::try_join_all(mint_queries)
|
||||||
|
.await
|
||||||
|
.map(|quotes| {
|
||||||
|
quotes
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|quote| quote.map(|x| x.into()))
|
||||||
|
.map(|x: MintQuoteBolt11Response<Uuid>| x.into())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.map_err(|e| e.to_string())?,
|
||||||
|
);
|
||||||
|
|
||||||
|
to_return.extend(
|
||||||
|
datastore
|
||||||
|
.get_proofs_states(public_keys.as_slice())
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(idx, state)| state.map(|state| (public_keys[idx], state).into()))
|
||||||
|
.map(|state: ProofState| state.into()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(to_return)
|
Ok(to_return)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ impl HttpClientMethods for HttpClient {
|
|||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MintQuoteBolt11Request,
|
request: MintQuoteBolt11Request,
|
||||||
) -> Result<MintQuoteBolt11Response, Error> {
|
) -> Result<MintQuoteBolt11Response<String>, Error> {
|
||||||
let url = mint_url.join_paths(&["v1", "mint", "quote", "bolt11"])?;
|
let url = mint_url.join_paths(&["v1", "mint", "quote", "bolt11"])?;
|
||||||
|
|
||||||
let res = self
|
let res = self
|
||||||
@@ -132,7 +132,7 @@ impl HttpClientMethods for HttpClient {
|
|||||||
.text()
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
convert_http_response!(MintQuoteBolt11Response, res)
|
convert_http_response!(MintQuoteBolt11Response<String>, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mint Quote status
|
/// Mint Quote status
|
||||||
@@ -141,12 +141,12 @@ impl HttpClientMethods for HttpClient {
|
|||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
quote_id: &str,
|
quote_id: &str,
|
||||||
) -> Result<MintQuoteBolt11Response, Error> {
|
) -> Result<MintQuoteBolt11Response<String>, Error> {
|
||||||
let url = mint_url.join_paths(&["v1", "mint", "quote", "bolt11", quote_id])?;
|
let url = mint_url.join_paths(&["v1", "mint", "quote", "bolt11", quote_id])?;
|
||||||
|
|
||||||
let res = self.inner.get(url).send().await?.text().await?;
|
let res = self.inner.get(url).send().await?.text().await?;
|
||||||
|
|
||||||
convert_http_response!(MintQuoteBolt11Response, res)
|
convert_http_response!(MintQuoteBolt11Response<String>, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mint Tokens [NUT-04]
|
/// Mint Tokens [NUT-04]
|
||||||
@@ -154,7 +154,7 @@ impl HttpClientMethods for HttpClient {
|
|||||||
async fn post_mint(
|
async fn post_mint(
|
||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MintBolt11Request,
|
request: MintBolt11Request<String>,
|
||||||
) -> Result<MintBolt11Response, Error> {
|
) -> Result<MintBolt11Response, Error> {
|
||||||
let url = mint_url.join_paths(&["v1", "mint", "bolt11"])?;
|
let url = mint_url.join_paths(&["v1", "mint", "bolt11"])?;
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ impl HttpClientMethods for HttpClient {
|
|||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MeltQuoteBolt11Request,
|
request: MeltQuoteBolt11Request,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<String>, Error> {
|
||||||
let url = mint_url.join_paths(&["v1", "melt", "quote", "bolt11"])?;
|
let url = mint_url.join_paths(&["v1", "melt", "quote", "bolt11"])?;
|
||||||
|
|
||||||
let res = self
|
let res = self
|
||||||
@@ -188,7 +188,7 @@ impl HttpClientMethods for HttpClient {
|
|||||||
.text()
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
convert_http_response!(MeltQuoteBolt11Response, res)
|
convert_http_response!(MeltQuoteBolt11Response<String>, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Melt Quote Status
|
/// Melt Quote Status
|
||||||
@@ -197,12 +197,12 @@ impl HttpClientMethods for HttpClient {
|
|||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
quote_id: &str,
|
quote_id: &str,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<String>, Error> {
|
||||||
let url = mint_url.join_paths(&["v1", "melt", "quote", "bolt11", quote_id])?;
|
let url = mint_url.join_paths(&["v1", "melt", "quote", "bolt11", quote_id])?;
|
||||||
|
|
||||||
let res = self.inner.get(url).send().await?.text().await?;
|
let res = self.inner.get(url).send().await?.text().await?;
|
||||||
|
|
||||||
convert_http_response!(MeltQuoteBolt11Response, res)
|
convert_http_response!(MeltQuoteBolt11Response<String>, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Melt [NUT-05]
|
/// Melt [NUT-05]
|
||||||
@@ -211,8 +211,8 @@ impl HttpClientMethods for HttpClient {
|
|||||||
async fn post_melt(
|
async fn post_melt(
|
||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MeltBolt11Request,
|
request: MeltBolt11Request<String>,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<String>, Error> {
|
||||||
let url = mint_url.join_paths(&["v1", "melt", "bolt11"])?;
|
let url = mint_url.join_paths(&["v1", "melt", "bolt11"])?;
|
||||||
|
|
||||||
let res = self
|
let res = self
|
||||||
@@ -224,7 +224,7 @@ impl HttpClientMethods for HttpClient {
|
|||||||
.text()
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
convert_http_response!(MeltQuoteBolt11Response, res)
|
convert_http_response!(MeltQuoteBolt11Response<String>, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Swap Token [NUT-03]
|
/// Swap Token [NUT-03]
|
||||||
@@ -319,20 +319,20 @@ pub trait HttpClientMethods: Debug {
|
|||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MintQuoteBolt11Request,
|
request: MintQuoteBolt11Request,
|
||||||
) -> Result<MintQuoteBolt11Response, Error>;
|
) -> Result<MintQuoteBolt11Response<String>, Error>;
|
||||||
|
|
||||||
/// Mint Quote status
|
/// Mint Quote status
|
||||||
async fn get_mint_quote_status(
|
async fn get_mint_quote_status(
|
||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
quote_id: &str,
|
quote_id: &str,
|
||||||
) -> Result<MintQuoteBolt11Response, Error>;
|
) -> Result<MintQuoteBolt11Response<String>, Error>;
|
||||||
|
|
||||||
/// Mint Tokens [NUT-04]
|
/// Mint Tokens [NUT-04]
|
||||||
async fn post_mint(
|
async fn post_mint(
|
||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MintBolt11Request,
|
request: MintBolt11Request<String>,
|
||||||
) -> Result<MintBolt11Response, Error>;
|
) -> Result<MintBolt11Response, Error>;
|
||||||
|
|
||||||
/// Melt Quote [NUT-05]
|
/// Melt Quote [NUT-05]
|
||||||
@@ -340,22 +340,22 @@ pub trait HttpClientMethods: Debug {
|
|||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MeltQuoteBolt11Request,
|
request: MeltQuoteBolt11Request,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error>;
|
) -> Result<MeltQuoteBolt11Response<String>, Error>;
|
||||||
|
|
||||||
/// Melt Quote Status
|
/// Melt Quote Status
|
||||||
async fn get_melt_quote_status(
|
async fn get_melt_quote_status(
|
||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
quote_id: &str,
|
quote_id: &str,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error>;
|
) -> Result<MeltQuoteBolt11Response<String>, Error>;
|
||||||
|
|
||||||
/// Melt [NUT-05]
|
/// Melt [NUT-05]
|
||||||
/// [Nut-08] Lightning fee return if outputs defined
|
/// [Nut-08] Lightning fee return if outputs defined
|
||||||
async fn post_melt(
|
async fn post_melt(
|
||||||
&self,
|
&self,
|
||||||
mint_url: MintUrl,
|
mint_url: MintUrl,
|
||||||
request: MeltBolt11Request,
|
request: MeltBolt11Request<String>,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error>;
|
) -> Result<MeltQuoteBolt11Response<String>, Error>;
|
||||||
|
|
||||||
/// Split Token [NUT-06]
|
/// Split Token [NUT-06]
|
||||||
async fn post_swap(
|
async fn post_swap(
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl Wallet {
|
|||||||
pub async fn melt_quote_status(
|
pub async fn melt_quote_status(
|
||||||
&self,
|
&self,
|
||||||
quote_id: &str,
|
quote_id: &str,
|
||||||
) -> Result<MeltQuoteBolt11Response, Error> {
|
) -> Result<MeltQuoteBolt11Response<String>, Error> {
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.get_melt_quote_status(self.mint_url.clone(), quote_id)
|
.get_melt_quote_status(self.mint_url.clone(), quote_id)
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ impl Wallet {
|
|||||||
|
|
||||||
let quote = MintQuote {
|
let quote = MintQuote {
|
||||||
mint_url,
|
mint_url,
|
||||||
id: quote_res.quote.clone(),
|
id: quote_res.quote,
|
||||||
amount,
|
amount,
|
||||||
unit: unit.clone(),
|
unit: unit.clone(),
|
||||||
request: quote_res.request,
|
request: quote_res.request,
|
||||||
@@ -93,7 +93,10 @@ impl Wallet {
|
|||||||
|
|
||||||
/// Check mint quote status
|
/// Check mint quote status
|
||||||
#[instrument(skip(self, quote_id))]
|
#[instrument(skip(self, quote_id))]
|
||||||
pub async fn mint_quote_state(&self, quote_id: &str) -> Result<MintQuoteBolt11Response, Error> {
|
pub async fn mint_quote_state(
|
||||||
|
&self,
|
||||||
|
quote_id: &str,
|
||||||
|
) -> Result<MintQuoteBolt11Response<String>, Error> {
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.get_mint_quote_status(self.mint_url.clone(), quote_id)
|
.get_mint_quote_status(self.mint_url.clone(), quote_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user