diff --git a/Cargo.lock b/Cargo.lock index 21308ae6..2242f117 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -756,6 +756,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-queue" version = "0.3.8" @@ -1409,6 +1418,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "float-cmp" version = "0.9.0" @@ -2646,6 +2665,7 @@ dependencies = [ "serde_with", "thiserror", "url", + "utoipa", "uuid", ] @@ -2728,6 +2748,8 @@ dependencies = [ "tracing", "tracing-subscriber", "url", + "utoipa", + "utoipa-swagger-ui", "uuid", ] @@ -3422,6 +3444,41 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust-embed" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810294a8a4a0853d4118e3b94bb079905f2107c7fe979d8f0faae98765eb6378" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfc144a1273124a67b8c1d7cd19f5695d1878b31569c0512f6086f0f4676604e" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "shellexpand", + "syn 2.0.39", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ccd4875431253d6bb54b804bcff4369cbde9bae33defde25fdf6c2ef91d40" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -3512,6 +3569,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3751,6 +3817,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shellexpand" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +dependencies = [ + "dirs", +] + [[package]] name = "shlex" version = "1.2.0" @@ -4644,6 +4719,47 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utoipa" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ff05e3bac2c9428f57ade702667753ca3f5cf085e2011fe697de5bfd49aa72d" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0b6f4667edd64be0e820d6631a60433a269710b6ee89ac39525b872b76d61d" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 2.0.39", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f839caa8e09dddc3ff1c3112a91ef7da0601075ba5025d9f33ae99c4cb9b6e51" +dependencies = [ + "axum 0.7.2", + "mime_guess", + "regex", + "rust-embed", + "serde", + "serde_json", + "utoipa", + "zip", +] + [[package]] name = "uuid" version = "1.6.1" @@ -4714,6 +4830,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -4864,6 +4990,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -5056,6 +5191,18 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", +] + [[package]] name = "zstd-sys" version = "2.0.9+zstd.1.5.5" diff --git a/moksha-core/Cargo.toml b/moksha-core/Cargo.toml index 6934682b..85bc5263 100644 --- a/moksha-core/Cargo.toml +++ b/moksha-core/Cargo.toml @@ -24,6 +24,7 @@ serde_with = "3.4.0" thiserror = "1.0.50" itertools = "0.12.0" uuid = { version = "1.6.1", features = ["serde", "v4"] } +utoipa = { version = "4.1.0" } [target.'cfg(target_family = "wasm")'.dependencies] # getrandom is transitive dependency of rand diff --git a/moksha-core/src/primitives.rs b/moksha-core/src/primitives.rs index d0bcd933..9f6759ee 100644 --- a/moksha-core/src/primitives.rs +++ b/moksha-core/src/primitives.rs @@ -7,6 +7,7 @@ use secp256k1::PublicKey; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use std::convert::TryFrom; +use utoipa::ToSchema; use uuid::Uuid; use crate::{ @@ -120,7 +121,7 @@ pub struct KeyResponse { pub keys: HashMap, } -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone, ToSchema)] #[serde(rename_all = "lowercase")] pub enum CurrencyUnit { Sat, @@ -136,7 +137,7 @@ impl Display for CurrencyUnit { } } -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone, ToSchema)] #[serde(rename_all = "lowercase")] pub enum PaymentMethod { Bolt11, @@ -260,19 +261,20 @@ pub struct PostMeltBolt11Response { } #[skip_serializing_none] -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ToSchema)] pub struct MintInfoResponse { pub name: Option, + #[schema(value_type = String)] pub pubkey: PublicKey, pub version: Option, pub description: Option, pub description_long: Option, pub contact: Option>>, - pub nuts: Vec, pub motd: Option, + pub nuts: Vec, } -#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, ToSchema)] pub enum MintInfoNut { /// Cryptography and Models #[serde(rename = "0")] diff --git a/moksha-mint/Cargo.toml b/moksha-mint/Cargo.toml index a75b9c1d..ab69943f 100644 --- a/moksha-mint/Cargo.toml +++ b/moksha-mint/Cargo.toml @@ -45,6 +45,9 @@ envy = "0.4.2" fedimint-tonic-lnd = { version = "0.1.3", features = ["lightningrpc"] } uuid = { version = "1.6.1", features = ["serde", "v4"] } +utoipa = { version = "4.1.0", features = ["axum_extras"] } +utoipa-swagger-ui = { version = "5.0.0", features = ["axum"] } + [dev-dependencies] tempfile = "3.8.1" tower = { version = "0.4", features = ["util"] } diff --git a/moksha-mint/src/server.rs b/moksha-mint/src/server.rs index 62f0a8e7..8f7fc8f9 100644 --- a/moksha-mint/src/server.rs +++ b/moksha-mint/src/server.rs @@ -11,6 +11,7 @@ use axum::routing::{get_service, post}; use axum::{middleware, Router}; use axum::{routing::get, Json}; use moksha_core::keyset::{generate_hash, Keysets, V1Keysets}; +use utoipa_swagger_ui::SwaggerUi; use uuid::Uuid; use crate::mint::Mint; @@ -36,6 +37,8 @@ use tracing::{event, info, Level}; use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; +use utoipa::OpenApi; + pub async fn run_server( mint: Mint, addr: SocketAddr, @@ -73,6 +76,13 @@ pub async fn run_server( Ok(()) } +#[derive(OpenApi)] +#[openapi( + paths(get_info,), + components(schemas(MintInfoResponse, MintInfoNut, CurrencyUnit, PaymentMethod)) +)] +struct ApiDoc; + fn app(mint: Mint, serve_wallet_path: Option, prefix: Option) -> Router { let legacy_routes = Router::new() .route("/keys", get(get_legacy_keys)) @@ -84,6 +94,7 @@ fn app(mint: Mint, serve_wallet_path: Option, prefix: Option) - .route("/info", get(get_legacy_info)); let routes = Router::new() + .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi())) .route("/v1/keys", get(get_keys)) .route("/v1/keys/:id", get(get_keys_by_id)) .route("/v1/keysets", get(get_keysets)) @@ -496,6 +507,13 @@ async fn get_melt_quote_bolt11( } } +#[utoipa::path( + get, + path = "/v1/info", + responses( + (status = 200, description = "get mint info", body = [MintInfoResponse]) + ) + )] async fn get_info(State(mint): State) -> Result, MokshaMintError> { let mint_info = MintInfoResponse { name: mint.mint_info.name,