mintd: add utoipa swagger UI

This commit is contained in:
ok300
2024-10-05 11:53:34 +02:00
parent 6ee79feff5
commit dffc30233c
28 changed files with 392 additions and 17 deletions

View File

@@ -46,6 +46,7 @@ jobs:
-p cdk --no-default-features,
-p cdk --no-default-features --features wallet,
-p cdk --no-default-features --features mint,
-p cdk --no-default-features --features "mint swagger",
-p cdk-redb,
-p cdk-sqlite,
-p cdk-axum,
@@ -143,6 +144,7 @@ jobs:
-p cdk --no-default-features,
-p cdk --no-default-features --features wallet,
-p cdk --no-default-features --features mint,
-p cdk --no-default-features --features "mint swagger",
-p cdk-axum,
-p cdk-strike,
-p cdk-lnbits,

View File

@@ -15,7 +15,11 @@ axum = "0.6.20"
cdk = { path = "../cdk", version = "0.4.0", default-features = false, features = ["mint"] }
tokio = { version = "1", default-features = false }
tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] }
utoipa = { version = "4", features = ["preserve_order", "preserve_path_order"], optional = true }
futures = { version = "0.3.28", default-features = false }
moka = { version = "0.11.1", features = ["future"] }
serde_json = "1"
paste = "1.0.15"
[features]
swagger = ["cdk/swagger", "dep:utoipa"]

View File

@@ -4,6 +4,7 @@
#![warn(rustdoc::bare_urls)]
use std::sync::Arc;
use std::time::Duration;
use anyhow::Result;
use axum::routing::{get, post};
@@ -11,10 +12,42 @@ use axum::Router;
use cdk::mint::Mint;
use moka::future::Cache;
use router_handlers::*;
use std::time::Duration;
mod router_handlers;
#[cfg(feature = "swagger")]
mod swagger_imports {
pub use cdk::amount::Amount;
pub use cdk::error::{ErrorCode, ErrorResponse};
pub use cdk::nuts::nut00::{
BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod, Proof, Witness,
};
pub use cdk::nuts::nut01::{Keys, KeysResponse, PublicKey, SecretKey};
pub use cdk::nuts::nut02::{Id, KeySet, KeySetInfo, KeySetVersion, KeysetResponse};
pub use cdk::nuts::nut03::{SwapRequest, SwapResponse};
pub use cdk::nuts::nut04;
pub use cdk::nuts::nut04::{
MintBolt11Request, MintBolt11Response, MintMethodSettings, MintQuoteBolt11Request,
MintQuoteBolt11Response,
};
pub use cdk::nuts::nut05;
pub use cdk::nuts::nut05::{
MeltBolt11Request, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteBolt11Response,
};
pub use cdk::nuts::nut06::{ContactInfo, MintInfo, MintVersion, Nuts, SupportedSettings};
pub use cdk::nuts::nut07::{CheckStateRequest, CheckStateResponse, ProofState, State};
pub use cdk::nuts::nut09::{RestoreRequest, RestoreResponse};
pub use cdk::nuts::nut11::P2PKWitness;
pub use cdk::nuts::nut12::{BlindSignatureDleq, ProofDleq};
pub use cdk::nuts::nut14::HTLCWitness;
pub use cdk::nuts::nut15;
pub use cdk::nuts::nut15::{Mpp, MppMethodSettings};
pub use cdk::nuts::{MeltQuoteState, MintQuoteState};
}
#[cfg(feature = "swagger")]
use swagger_imports::*;
/// CDK Mint State
#[derive(Clone)]
pub struct MintState {
@@ -22,6 +55,82 @@ pub struct MintState {
cache: Cache<String, String>,
}
#[cfg(feature = "swagger")]
#[derive(utoipa::OpenApi)]
#[openapi(
components(schemas(
Amount,
BlindedMessage,
BlindSignature,
BlindSignatureDleq,
CheckStateRequest,
CheckStateResponse,
ContactInfo,
CurrencyUnit,
ErrorCode,
ErrorResponse,
HTLCWitness,
Id,
Keys,
KeysResponse,
KeysetResponse,
KeySet,
KeySetInfo,
KeySetVersion,
MeltBolt11Request,
MeltQuoteBolt11Request,
MeltQuoteBolt11Response,
MeltQuoteState,
MeltMethodSettings,
MintBolt11Request,
MintBolt11Response,
MintInfo,
MintQuoteBolt11Request,
MintQuoteBolt11Response,
MintQuoteState,
MintMethodSettings,
MintVersion,
Mpp,
MppMethodSettings,
Nuts,
P2PKWitness,
PaymentMethod,
Proof,
ProofDleq,
ProofState,
PublicKey,
RestoreRequest,
RestoreResponse,
SecretKey,
State,
SupportedSettings,
SwapRequest,
SwapResponse,
Witness,
nut04::Settings,
nut05::Settings,
nut15::Settings
)),
info(description = "Cashu CDK mint APIs", title = "cdk-mintd",),
paths(
get_keys,
get_keyset_pubkeys,
get_keysets,
get_mint_info,
get_mint_bolt11_quote,
get_check_mint_bolt11_quote,
post_mint_bolt11,
get_melt_bolt11_quote,
get_check_melt_bolt11_quote,
post_melt_bolt11,
post_swap,
post_check,
post_restore
)
)]
/// OpenAPI spec for the mint's v1 APIs
pub struct ApiDocV1;
/// Create mint [`Router`] with required endpoints for cashu mint
pub async fn create_mint_router(mint: Arc<Mint>, cache_ttl: u64, cache_tti: u64) -> Result<Router> {
let state = MintState {

View File

@@ -49,6 +49,17 @@ post_cache_wrapper!(post_swap, SwapRequest, SwapResponse);
post_cache_wrapper!(post_mint_bolt11, MintBolt11Request, MintBolt11Response);
post_cache_wrapper!(post_melt_bolt11, MeltBolt11Request, MeltQuoteBolt11Response);
#[cfg_attr(feature = "swagger", utoipa::path(
get,
context_path = "/v1",
path = "/keys",
responses(
(status = 200, description = "Successful response", body = KeysResponse, content_type = "application/json")
)
))]
/// Get the public keys of the newest mint keyset
///
/// This endpoint returns a dictionary of all supported token values of the mint and their associated public key.
pub async fn get_keys(State(state): State<MintState>) -> Result<Json<KeysResponse>, Response> {
let pubkeys = state.mint.pubkeys().await.map_err(|err| {
tracing::error!("Could not get keys: {}", err);
@@ -58,6 +69,21 @@ pub async fn get_keys(State(state): State<MintState>) -> Result<Json<KeysRespons
Ok(Json(pubkeys))
}
#[cfg_attr(feature = "swagger", utoipa::path(
get,
context_path = "/v1",
path = "/keys/{keyset_id}",
params(
("keyset_id" = String, description = "The keyset ID"),
),
responses(
(status = 200, description = "Successful response", body = KeysResponse, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Get the public keys of a specific keyset
///
/// Get the public keys of the mint from a specific keyset ID.
pub async fn get_keyset_pubkeys(
State(state): State<MintState>,
Path(keyset_id): Path<Id>,
@@ -70,15 +96,40 @@ pub async fn get_keyset_pubkeys(
Ok(Json(pubkeys))
}
#[cfg_attr(feature = "swagger", utoipa::path(
get,
context_path = "/v1",
path = "/keysets",
responses(
(status = 200, description = "Successful response", body = KeysetResponse, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Get all active keyset IDs of the mint
///
/// This endpoint returns a list of keysets that the mint currently supports and will accept tokens from.
pub async fn get_keysets(State(state): State<MintState>) -> Result<Json<KeysetResponse>, Response> {
let mint = state.mint.keysets().await.map_err(|err| {
tracing::error!("Could not get keyset: {}", err);
let keysets = state.mint.keysets().await.map_err(|err| {
tracing::error!("Could not get keysets: {}", err);
into_response(err)
})?;
Ok(Json(mint))
Ok(Json(keysets))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/mint/quote/bolt11",
request_body(content = MintQuoteBolt11Request, description = "Request params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = MintQuoteBolt11Response, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Request a quote for minting of new tokens
///
/// Request minting of new tokens. The mint responds with a Lightning invoice. This endpoint can be used for a Lightning invoice UX flow.
pub async fn get_mint_bolt11_quote(
State(state): State<MintState>,
Json(payload): Json<MintQuoteBolt11Request>,
@@ -92,6 +143,21 @@ pub async fn get_mint_bolt11_quote(
Ok(Json(quote))
}
#[cfg_attr(feature = "swagger", utoipa::path(
get,
context_path = "/v1",
path = "/mint/quote/bolt11/{quote_id}",
params(
("quote_id" = String, description = "The quote ID"),
),
responses(
(status = 200, description = "Successful response", body = MintQuoteBolt11Response, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Get mint quote by ID
///
/// Get mint quote state.
pub async fn get_check_mint_bolt11_quote(
State(state): State<MintState>,
Path(quote_id): Path<String>,
@@ -108,6 +174,21 @@ pub async fn get_check_mint_bolt11_quote(
Ok(Json(quote))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/mint/bolt11",
request_body(content = MintBolt11Request, description = "Request params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = MintBolt11Response, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Mint tokens by paying a BOLT11 Lightning invoice.
///
/// Requests the minting of tokens belonging to a paid payment request.
///
/// Call this endpoint after `POST /v1/mint/quote`.
pub async fn post_mint_bolt11(
State(state): State<MintState>,
Json(payload): Json<MintBolt11Request>,
@@ -124,6 +205,17 @@ pub async fn post_mint_bolt11(
Ok(Json(res))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/melt/quote/bolt11",
request_body(content = MeltQuoteBolt11Request, description = "Quote params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Request a quote for melting tokens
pub async fn get_melt_bolt11_quote(
State(state): State<MintState>,
Json(payload): Json<MeltQuoteBolt11Request>,
@@ -137,6 +229,21 @@ pub async fn get_melt_bolt11_quote(
Ok(Json(quote))
}
#[cfg_attr(feature = "swagger", utoipa::path(
get,
context_path = "/v1",
path = "/melt/quote/bolt11/{quote_id}",
params(
("quote_id" = String, description = "The quote ID"),
),
responses(
(status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Get melt quote by ID
///
/// Get melt quote state.
pub async fn get_check_melt_bolt11_quote(
State(state): State<MintState>,
Path(quote_id): Path<String>,
@@ -153,6 +260,19 @@ pub async fn get_check_melt_bolt11_quote(
Ok(Json(quote))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/melt/bolt11",
request_body(content = MeltBolt11Request, description = "Melt params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Melt tokens for a Bitcoin payment that the mint will make for the user in exchange
///
/// Requests tokens to be destroyed and sent out via Lightning.
pub async fn post_melt_bolt11(
State(state): State<MintState>,
Json(payload): Json<MeltBolt11Request>,
@@ -166,6 +286,19 @@ pub async fn post_melt_bolt11(
Ok(Json(res))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/checkstate",
request_body(content = CheckStateRequest, description = "State params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = CheckStateResponse, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Check whether a proof is spent already or is pending in a transaction
///
/// Check whether a secret has been spent already or not.
pub async fn post_check(
State(state): State<MintState>,
Json(payload): Json<CheckStateRequest>,
@@ -178,10 +311,34 @@ pub async fn post_check(
Ok(Json(state))
}
#[cfg_attr(feature = "swagger", utoipa::path(
get,
context_path = "/v1",
path = "/info",
responses(
(status = 200, description = "Successful response", body = MintInfo)
)
))]
/// Mint information, operator contact information, and other info
pub async fn get_mint_info(State(state): State<MintState>) -> Result<Json<MintInfo>, Response> {
Ok(Json(state.mint.mint_info().clone().time(unix_time())))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/swap",
request_body(content = SwapRequest, description = "Swap params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = SwapResponse, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Swap inputs for outputs of the same value
///
/// Requests a set of Proofs to be swapped for another set of BlindSignatures.
///
/// This endpoint can be used by Alice to swap a set of proofs before making a payment to Carol. It can then used by Carol to redeem the tokens for new proofs.
pub async fn post_swap(
State(state): State<MintState>,
Json(payload): Json<SwapRequest>,
@@ -197,6 +354,17 @@ pub async fn post_swap(
Ok(Json(swap_response))
}
#[cfg_attr(feature = "swagger", utoipa::path(
post,
context_path = "/v1",
path = "/restore",
request_body(content = RestoreRequest, description = "Restore params", content_type = "application/json"),
responses(
(status = 200, description = "Successful response", body = RestoreResponse, content_type = "application/json"),
(status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json")
)
))]
/// Restores blind signature for a set of outputs.
pub async fn post_restore(
State(state): State<MintState>,
Json(payload): Json<RestoreRequest>,

View File

@@ -34,3 +34,8 @@ tower-http = { version = "0.4.4", features = ["cors"] }
lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
home = "0.5.5"
url = "2.3"
utoipa = { version = "4", optional = true }
utoipa-swagger-ui = { version = "4", features = ["axum"], optional = true }
[features]
swagger = ["cdk-axum/swagger", "dep:utoipa", "dep:utoipa-swagger-ui"]

View File

@@ -4,6 +4,7 @@ listen_host = "127.0.0.1"
listen_port = 8085
mnemonic = ""
# input_fee_ppk = 0
# enable_swagger_ui = false

View File

@@ -15,6 +15,12 @@ pub struct Info {
pub seconds_to_cache_requests_for: Option<u64>,
pub seconds_to_extend_cache_by: Option<u64>,
pub input_fee_ppk: Option<u64>,
/// When this is set to true, the mint exposes a Swagger UI for it's API at
/// `[listen_host]:[listen_port]/swagger-ui`
///
/// This requires `mintd` was built with the `swagger` feature flag.
pub enable_swagger_ui: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
@@ -94,6 +100,7 @@ pub struct Database {
pub engine: DatabaseEngine,
}
/// CDK settings, derived from `config.toml`
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Settings {
pub info: Info,

View File

@@ -36,6 +36,8 @@ use tokio::sync::{Mutex, Notify};
use tower_http::cors::CorsLayer;
use tracing_subscriber::EnvFilter;
use url::Url;
#[cfg(feature = "swagger")]
use utoipa::OpenApi;
mod cli;
mod config;
@@ -451,7 +453,7 @@ async fn main() -> anyhow::Result<()> {
// Checks the status of all pending melt quotes
// Pending melt quotes where the payment has gone through inputs are burnt
// Pending melt quotes where the paynment has **failed** inputs are reset to unspent
// Pending melt quotes where the payment has **failed** inputs are reset to unspent
check_pending_melt_quotes(Arc::clone(&mint), &ln_backends).await?;
let listen_addr = settings.info.listen_host;
@@ -475,6 +477,16 @@ async fn main() -> anyhow::Result<()> {
.merge(v1_service)
.layer(CorsLayer::permissive());
#[cfg(feature = "swagger")]
{
if settings.info.enable_swagger_ui.unwrap_or(false) {
mint_service = mint_service.merge(
utoipa_swagger_ui::SwaggerUi::new("/swagger-ui")
.url("/api-docs/openapi.json", cdk_axum::ApiDocV1::openapi()),
);
}
}
for router in ln_routers {
mint_service = mint_service.merge(router);
}

View File

@@ -649,14 +649,9 @@ impl WalletDatabase for WalletRedbDatabase {
let mut proof = None;
if let Ok(proof_info) = serde_json::from_str::<ProofInfo>(v.value()) {
match proof_info.matches_conditions(
&mint_url,
&unit,
&state,
&spending_conditions,
) {
true => proof = Some(proof_info),
false => (),
if proof_info.matches_conditions(&mint_url, &unit, &state, &spending_conditions)
{
proof = Some(proof_info)
}
}

View File

@@ -13,6 +13,7 @@ license = "MIT"
[features]
default = ["mint", "wallet"]
mint = ["dep:futures"]
swagger = ["mint", "dep:utoipa"]
wallet = ["dep:reqwest"]
bench = []
@@ -39,6 +40,7 @@ tracing = { version = "0.1", default-features = false, features = ["attributes",
thiserror = "1"
futures = { version = "0.3.28", default-features = false, optional = true }
url = "2.3"
utoipa = { version = "4", optional = true }
uuid = { version = "1", features = ["v4"] }
# -Z minimal-versions

View File

@@ -27,6 +27,7 @@ pub enum Error {
/// Amount can be any unit
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
#[serde(transparent)]
pub struct Amount(u64);

View File

@@ -242,8 +242,9 @@ pub enum Error {
/// CDK Error Response
///
/// See NUT defenation in [00](https://github.com/cashubtc/nuts/blob/main/00.md)
/// See NUT definition in [00](https://github.com/cashubtc/nuts/blob/main/00.md)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct ErrorResponse {
/// Error Code
pub code: ErrorCode,
@@ -399,6 +400,7 @@ impl From<ErrorResponse> for Error {
/// Possible Error Codes
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum ErrorCode {
/// Token is already spent
TokenAlreadySpent,

View File

@@ -103,6 +103,7 @@ pub enum Error {
/// Blinded Message (also called `output`)
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct BlindedMessage {
/// Amount
///
@@ -117,6 +118,7 @@ pub struct BlindedMessage {
///
/// The blinded secret message generated by the sender.
#[serde(rename = "B_")]
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub blinded_secret: PublicKey,
/// Witness
///
@@ -146,6 +148,7 @@ impl BlindedMessage {
/// Blind Signature (also called `promise`)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct BlindSignature {
/// Amount
///
@@ -160,6 +163,7 @@ pub struct BlindSignature {
///
/// The blinded signature on the secret message `B_` of [BlindedMessage].
#[serde(rename = "C_")]
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub c: PublicKey,
/// DLEQ Proof
///
@@ -183,6 +187,7 @@ impl PartialOrd for BlindSignature {
/// Witness
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum Witness {
/// P2PK Witness
#[serde(with = "serde_p2pk_witness")]
@@ -226,6 +231,7 @@ impl Witness {
/// Proofs
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct Proof {
/// Amount
pub amount: Amount,
@@ -233,9 +239,11 @@ pub struct Proof {
#[serde(rename = "id")]
pub keyset_id: Id,
/// Secret message
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub secret: Secret,
/// Unblinded signature
#[serde(rename = "C")]
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub c: PublicKey,
/// Witness
#[serde(skip_serializing_if = "Option::is_none")]
@@ -360,6 +368,7 @@ where
/// Currency Unit
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum CurrencyUnit {
/// Sat
#[default]
@@ -436,6 +445,7 @@ impl<'de> Deserialize<'de> for CurrencyUnit {
/// Payment Method
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum PaymentMethod {
/// Bolt11 payment type
#[default]

View File

@@ -43,6 +43,7 @@ pub enum Error {
///
/// See [NUT-01]
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct Keys(BTreeMap<AmountStr, PublicKey>);
impl From<MintKeys> for Keys {
@@ -85,6 +86,7 @@ impl Keys {
/// Mint Public Keys [NUT-01]
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct KeysResponse {
/// Keysets
#[serde_as(as = "VecSkipError<_>")]

View File

@@ -13,7 +13,9 @@ use crate::SECP256K1;
/// PublicKey
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct PublicKey {
#[cfg_attr(feature = "swagger", schema(value_type = String))]
inner: secp256k1::PublicKey,
}

View File

@@ -15,7 +15,9 @@ use crate::SECP256K1;
/// SecretKey
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct SecretKey {
#[cfg_attr(feature = "swagger", schema(value_type = String))]
inner: secp256k1::SecretKey,
}

View File

@@ -53,6 +53,7 @@ pub enum Error {
/// Keyset version
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum KeySetVersion {
/// Current Version 00
Version00,
@@ -88,6 +89,7 @@ impl fmt::Display for KeySetVersion {
/// be stored in a Cashu token such that the token can be used to identify
/// which mint or keyset it was generated from.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct Id {
version: KeySetVersion,
id: [u8; Self::BYTELEN],
@@ -228,6 +230,7 @@ impl From<&Keys> for Id {
/// Ids of mints keyset ids
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct KeysetResponse {
/// set of public key ids that the mint generates
#[serde_as(as = "VecSkipError<_>")]
@@ -236,6 +239,7 @@ pub struct KeysetResponse {
/// Keyset
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct KeySet {
/// Keyset [`Id`]
pub id: Id,
@@ -271,6 +275,7 @@ impl From<MintKeySet> for KeySet {
/// KeySetInfo
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct KeySetInfo {
/// Keyset [`Id`]
pub id: Id,

View File

@@ -34,8 +34,10 @@ pub struct PreSwap {
/// Split Request [NUT-06]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct SwapRequest {
/// Proofs that are to be spent in `Split`
#[cfg_attr(feature = "swagger", schema(value_type = Vec<Proof>))]
pub inputs: Proofs,
/// Blinded Messages for Mint to sign
pub outputs: Vec<BlindedMessage>,
@@ -64,6 +66,7 @@ impl SwapRequest {
/// Split Response [NUT-06]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct SwapResponse {
/// Promises
pub signatures: Vec<BlindSignature>,

View File

@@ -26,6 +26,7 @@ pub enum Error {
/// Mint quote request [NUT-04]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintQuoteBolt11Request {
/// Amount
pub amount: Amount,
@@ -38,6 +39,7 @@ pub struct MintQuoteBolt11Request {
/// Possible states of a quote
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema), schema(as = MintQuoteState))]
pub enum QuoteState {
/// Quote has not been paid
#[default]
@@ -79,6 +81,7 @@ impl FromStr for QuoteState {
/// Mint quote response [NUT-04]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintQuoteBolt11Response {
/// Quote Id
pub quote: String,
@@ -175,10 +178,13 @@ impl From<crate::mint::MintQuote> for MintQuoteBolt11Response {
/// Mint request [NUT-04]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintBolt11Request {
/// Quote id
#[cfg_attr(feature = "swagger", schema(max_length = 1_000))]
pub quote: String,
/// Outputs
#[cfg_attr(feature = "swagger", schema(max_items = 1_000))]
pub outputs: Vec<BlindedMessage>,
}
@@ -196,6 +202,7 @@ impl MintBolt11Request {
/// Mint response [NUT-04]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintBolt11Response {
/// Blinded Signatures
pub signatures: Vec<BlindSignature>,
@@ -203,6 +210,7 @@ pub struct MintBolt11Response {
/// Mint Method Settings
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintMethodSettings {
/// Payment Method e.g. bolt11
pub method: PaymentMethod,
@@ -221,6 +229,7 @@ pub struct MintMethodSettings {
/// Mint Settings
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema), schema(as = nut04::Settings))]
pub struct Settings {
/// Methods to mint
pub methods: Vec<MintMethodSettings>,

View File

@@ -13,6 +13,7 @@ use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod,
use super::nut15::Mpp;
#[cfg(feature = "mint")]
use crate::mint;
use crate::nuts::MeltQuoteState;
use crate::{Amount, Bolt11Invoice};
/// NUT05 Error
@@ -28,8 +29,10 @@ pub enum Error {
/// Melt quote request [NUT-05]
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MeltQuoteBolt11Request {
/// Bolt11 invoice to be paid
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub request: Bolt11Invoice,
/// Unit wallet would like to pay with
pub unit: CurrencyUnit,
@@ -40,6 +43,7 @@ pub struct MeltQuoteBolt11Request {
/// Possible states of a quote
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema), schema(as = MeltQuoteState))]
pub enum QuoteState {
/// Quote has not been paid
#[default]
@@ -83,6 +87,7 @@ impl FromStr for QuoteState {
/// Melt quote response [NUT-05]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MeltQuoteBolt11Response {
/// Quote Id
pub quote: String,
@@ -95,7 +100,7 @@ pub struct MeltQuoteBolt11Response {
/// Deprecated
pub paid: Option<bool>,
/// Quote State
pub state: QuoteState,
pub state: MeltQuoteState,
/// Unix timestamp until the quote is valid
pub expiry: u64,
/// Payment preimage
@@ -209,10 +214,12 @@ impl From<mint::MeltQuote> for MeltQuoteBolt11Response {
/// Melt Bolt11 Request [NUT-05]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MeltBolt11Request {
/// Quote ID
pub quote: String,
/// Proofs
#[cfg_attr(feature = "swagger", schema(value_type = Vec<Proof>))]
pub inputs: Proofs,
/// Blinded Message that can be used to return change [NUT-08]
/// Amount field of BlindedMessages `SHOULD` be set to zero
@@ -229,6 +236,7 @@ impl MeltBolt11Request {
/// Melt Method Settings
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MeltMethodSettings {
/// Payment Method e.g. bolt11
pub method: PaymentMethod,
@@ -266,6 +274,7 @@ impl Settings {
/// Melt Settings
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema), schema(as = nut05::Settings))]
pub struct Settings {
/// Methods to melt
pub methods: Vec<MeltMethodSettings>,

View File

@@ -9,6 +9,7 @@ use super::{nut04, nut05, nut15, MppMethodSettings};
/// Mint Version
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintVersion {
/// Mint Software name
pub name: String,
@@ -52,6 +53,7 @@ impl<'de> Deserialize<'de> for MintVersion {
/// Mint Info [NIP-06]
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MintInfo {
/// name of the mint and should be recognizable
#[serde(skip_serializing_if = "Option::is_none")]
@@ -188,6 +190,7 @@ impl MintInfo {
/// Supported nuts and settings
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct Nuts {
/// NUT04 Settings
#[serde(default)]
@@ -322,12 +325,14 @@ impl Nuts {
/// Check state Settings
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct SupportedSettings {
supported: bool,
}
/// Contact Info
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct ContactInfo {
/// Contact Method i.e. nostr
pub method: String,

View File

@@ -21,6 +21,7 @@ pub enum Error {
/// State of Proof
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum State {
/// Spent
Spent,
@@ -63,19 +64,23 @@ impl FromStr for State {
}
}
/// Check spendabale request [NUT-07]
/// Check spendable request [NUT-07]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct CheckStateRequest {
/// Y's of the proofs to check
#[serde(rename = "Ys")]
#[cfg_attr(feature = "swagger", schema(value_type = Vec<String>, max_items = 1_000))]
pub ys: Vec<PublicKey>,
}
/// Proof state [NUT-07]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct ProofState {
/// Y of proof
#[serde(rename = "Y")]
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub y: PublicKey,
/// State of proof
pub state: State,
@@ -85,6 +90,7 @@ pub struct ProofState {
/// Check Spendable Response [NUT-07]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct CheckStateResponse {
/// Proof states
pub states: Vec<ProofState>,

View File

@@ -8,6 +8,7 @@ use super::nut00::{BlindSignature, BlindedMessage};
/// Restore Request [NUT-09]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct RestoreRequest {
/// Outputs
pub outputs: Vec<BlindedMessage>,
@@ -15,6 +16,7 @@ pub struct RestoreRequest {
/// Restore Response [NUT-09]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct RestoreResponse {
/// Outputs
pub outputs: Vec<BlindedMessage>,

View File

@@ -88,6 +88,7 @@ pub enum Error {
/// P2Pk Witness
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct P2PKWitness {
/// Signatures
pub signatures: Vec<String>,

View File

@@ -41,10 +41,13 @@ pub enum Error {
///
/// Defined in [NUT12](https://github.com/cashubtc/nuts/blob/main/12.md)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct BlindSignatureDleq {
/// e
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub e: SecretKey,
/// s
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub s: SecretKey,
}
@@ -52,12 +55,16 @@ pub struct BlindSignatureDleq {
///
/// Defined in [NUT12](https://github.com/cashubtc/nuts/blob/main/12.md)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct ProofDleq {
/// e
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub e: SecretKey,
/// s
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub s: SecretKey,
/// Blinding factor
#[cfg_attr(feature = "swagger", schema(value_type = String))]
pub r: SecretKey,
}

View File

@@ -52,6 +52,7 @@ pub enum Error {
/// HTLC Witness
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct HTLCWitness {
/// Primage
pub preimage: String,

View File

@@ -10,6 +10,7 @@ use crate::Amount;
/// Multi-part payment
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename = "lowercase")]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct Mpp {
/// Amount
pub amount: Amount,
@@ -17,6 +18,7 @@ pub struct Mpp {
/// Mpp Method Settings
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct MppMethodSettings {
/// Payment Method e.g. bolt11
pub method: PaymentMethod,
@@ -28,6 +30,7 @@ pub struct MppMethodSettings {
/// Mpp Settings
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema), schema(as = nut15::Settings))]
pub struct Settings {
/// Method settings
pub methods: Vec<MppMethodSettings>,

View File

@@ -135,7 +135,7 @@
cargo update -p serde_with --precise 3.1.0
cargo update -p regex --precise 1.9.6
cargo update -p backtrace --precise 0.3.58
# For wasm32-unknown-unknown target
# For wasm32-unknown-unknown target
cargo update -p bumpalo --precise 3.12.0
cargo update -p moka --precise 0.11.1
cargo update -p triomphe --precise 0.1.11