diff --git a/Cargo.lock b/Cargo.lock index 470b8b1a..a59ff6bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2048,6 +2048,7 @@ dependencies = [ "opentelemetry", "opentelemetry-otlp", "opentelemetry_sdk", + "pretty_assertions", "reqwest 0.12.3", "secp256k1 0.28.2", "serde", diff --git a/moksha-core/src/keyset.rs b/moksha-core/src/keyset.rs index 1f7e0d64..46633849 100644 --- a/moksha-core/src/keyset.rs +++ b/moksha-core/src/keyset.rs @@ -88,12 +88,14 @@ impl Keysets { } } -#[derive(Clone, Debug, Serialize, Deserialize, Default, ToSchema)] +// FIXME rename to keysets +#[derive(Clone, Debug, Serialize, Deserialize, Default, ToSchema, PartialEq, Eq)] pub struct V1Keysets { pub keysets: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] +// FIXME rename to keyset +#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, PartialEq, Eq)] pub struct V1Keyset { pub id: String, // FIXME use KeysetId pub unit: CurrencyUnit, diff --git a/moksha-core/src/primitives.rs b/moksha-core/src/primitives.rs index c6795521..d97ee31c 100644 --- a/moksha-core/src/primitives.rs +++ b/moksha-core/src/primitives.rs @@ -20,15 +20,6 @@ pub struct PaymentRequest { pub hash: String, // TODO use sha256::Hash } -#[derive(Clone, Debug, Serialize, Deserialize, Default)] -pub struct PostMintResponse { - pub promises: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct PostMintRequest { - pub outputs: Vec, -} #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CheckFeesRequest { @@ -41,36 +32,6 @@ pub struct CheckFeesResponse { pub fee: u64, } -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct PostMeltRequest { - pub proofs: Proofs, - pub pr: String, - pub outputs: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize, Default)] -pub struct PostMeltResponse { - pub paid: bool, - pub preimage: String, - pub change: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct PostSplitRequest { - pub proofs: Proofs, - pub outputs: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize, Default)] -pub struct PostSplitResponse { - pub promises: Vec, -} - -impl PostSplitResponse { - pub fn with_promises(promises: Vec) -> Self { - Self { promises } - } -} #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] pub struct PostSwapRequest { @@ -89,24 +50,7 @@ pub struct CashuErrorResponse { pub detail: String, } -#[skip_serializing_none] -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] -pub struct MintLegacyInfoResponse { - pub name: Option, - pub pubkey: PublicKey, - pub version: Option, - pub description: Option, - pub description_long: Option, - pub contact: Option>>, - pub nuts: Vec, - pub motd: Option, - pub parameter: Parameter, -} -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Default)] -pub struct Parameter { - pub peg_out_only: bool, -} #[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, Default, ToSchema)] pub struct KeysResponse { @@ -581,7 +525,7 @@ mod tests { dhke::public_key_from_hex, fixture::read_fixture, primitives::{ - KeyResponse, MintInfoResponse, MintLegacyInfoResponse, Nuts, Parameter, + KeyResponse, MintInfoResponse, Nuts, PostSwapResponse, }, }; @@ -606,37 +550,7 @@ mod tests { Ok(()) } - #[test] - fn test_deserialize_legacy_mint_info() -> anyhow::Result<()> { - let mint_info = MintLegacyInfoResponse { - name: Some("Bob's Cashu mint".to_string()), - pubkey: public_key_from_hex( - "02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2", - ), - version: Some("Nutshell/0.11.0".to_string()), - description: Some("The short mint description".to_string()), - description_long: Some("A description that can be a long piece of text.".to_string()), - contact: Some(vec![ - vec!["email".to_string(), "contact@me.com".to_string()], - vec!["twitter".to_string(), "@me".to_string()], - vec!["nostr".to_string(), "npub...".to_string()], - ]), - nuts: vec![ - "NUT-07".to_string(), - "NUT-08".to_string(), - "NUT-08".to_string(), - ], - motd: Some("Message to display to users.".to_string()), - parameter: Parameter { - peg_out_only: false, - }, - }; - let out = serde_json::to_string_pretty(&mint_info)?; - println!("{}", out); - assert!(!out.is_empty()); - - Ok(()) - } + #[test] fn test_deserialize_mint_info() -> anyhow::Result<()> { diff --git a/moksha-mint/Cargo.toml b/moksha-mint/Cargo.toml index 34ec66e4..c3d5c244 100644 --- a/moksha-mint/Cargo.toml +++ b/moksha-mint/Cargo.toml @@ -59,3 +59,4 @@ hex = "0.4.3" http-body-util = "0.1.0" testcontainers = "0.15.0" testcontainers-modules = { version = "0.3.6", features = ["postgres"] } +pretty_assertions = "1.4.0" diff --git a/moksha-mint/src/fixtures/post_split_request_64_20.json b/moksha-mint/src/fixtures/post_swap_request_64_20.json similarity index 98% rename from moksha-mint/src/fixtures/post_split_request_64_20.json rename to moksha-mint/src/fixtures/post_swap_request_64_20.json index a27cee2d..7204624e 100644 --- a/moksha-mint/src/fixtures/post_split_request_64_20.json +++ b/moksha-mint/src/fixtures/post_swap_request_64_20.json @@ -1,5 +1,5 @@ { - "proofs": [ + "inputs": [ { "amount": 64, "secret": "sYYrrhUD3IwJzGFCGsUqqXXa", diff --git a/moksha-mint/src/fixtures/post_split_request_duplicate_key.json b/moksha-mint/src/fixtures/post_swap_request_duplicate_key.json similarity index 98% rename from moksha-mint/src/fixtures/post_split_request_duplicate_key.json rename to moksha-mint/src/fixtures/post_swap_request_duplicate_key.json index a18683b5..fa65fad2 100644 --- a/moksha-mint/src/fixtures/post_split_request_duplicate_key.json +++ b/moksha-mint/src/fixtures/post_swap_request_duplicate_key.json @@ -1,5 +1,5 @@ { - "proofs": [ + "inputs": [ { "amount": 64, "secret": "sYYrrhUD3IwJzGFCGsUqqXXa", diff --git a/moksha-mint/src/mint.rs b/moksha-mint/src/mint.rs index 2013b556..8a6c7a64 100644 --- a/moksha-mint/src/mint.rs +++ b/moksha-mint/src/mint.rs @@ -450,7 +450,8 @@ mod tests { use crate::model::{Invoice, PayInvoiceResult}; use moksha_core::blind::{BlindedMessage, TotalAmount}; use moksha_core::dhke; - use moksha_core::primitives::PostSplitRequest; + use moksha_core::fixture::read_fixture_as; + use moksha_core::primitives::PostSwapRequest; use moksha_core::proof::Proofs; use moksha_core::token::TokenV3; use std::str::FromStr; @@ -458,6 +459,7 @@ mod tests { use testcontainers::clients::Cli; use testcontainers::RunnableImage; use testcontainers_modules::postgres::Postgres; + use pretty_assertions::assert_eq; #[tokio::test] async fn test_fee_reserve() -> anyhow::Result<()> { @@ -495,7 +497,7 @@ mod tests { id: "00ffd48b8f5ecf80".to_owned(), }]; - let result = mint.create_blinded_signatures(&blinded_messages, &mint.keyset_legacy)?; + let result = mint.create_blinded_signatures(&blinded_messages, &mint.keyset)?; assert_eq!(1, result.len()); assert_eq!(8, result[0].amount); @@ -552,7 +554,7 @@ mod tests { ) .await?; - let outputs = create_blinded_msgs_from_fixture("blinded_messages_40.json".to_string())?; + let outputs = read_fixture_as::>("blinded_messages_40.json")?; let mut tx = mint.db.begin_tx().await?; let result = mint .mint_tokens( @@ -591,7 +593,7 @@ mod tests { } #[tokio::test] - async fn test_split_64_in_20() -> anyhow::Result<()> { + async fn test_swap_64_in_20() -> anyhow::Result<()> { let docker = Cli::default(); let image = create_postgres_image(); let node = docker.run(image); @@ -601,10 +603,10 @@ mod tests { None, ) .await?; - let request = create_request_from_fixture("post_split_request_64_20.json".to_string())?; + let request = read_fixture_as::("post_swap_request_64_20.json")?; let result = mint - .swap(&request.proofs, &request.outputs, &mint.keyset_legacy) + .swap(&request.inputs, &request.outputs, &mint.keyset) .await?; assert_eq!(result.total_amount(), 64); @@ -617,7 +619,7 @@ mod tests { } #[tokio::test] - async fn test_split_duplicate_key() -> anyhow::Result<()> { + async fn test_swap_duplicate_key() -> anyhow::Result<()> { let docker = Cli::default(); let image = create_postgres_image(); let node = docker.run(image); @@ -627,10 +629,10 @@ mod tests { ) .await?; let request = - create_request_from_fixture("post_split_request_duplicate_key.json".to_string())?; + read_fixture_as::("post_swap_request_duplicate_key.json")?; let result = mint - .swap(&request.proofs, &request.outputs, &mint.keyset_legacy) + .swap(&request.inputs, &request.outputs, &mint.keyset) .await; assert!(result.is_err()); Ok(()) @@ -673,10 +675,10 @@ mod tests { Some(Arc::new(MockBtcOnchain::default())), ); - let tokens = create_token_from_fixture("token_60.cashu".to_string())?; + let tokens = create_token_from_fixture("token_60.cashu").expect("can not read fixture"); let invoice = "some invoice".to_string(); let change = - create_blinded_msgs_from_fixture("blinded_messages_blank_4000.json".to_string())?; + read_fixture_as::>("blinded_messages_blank_4000.json")?; let mut tx = mint.db.begin_tx().await?; let (paid, _payment_hash, change) = mint @@ -695,26 +697,12 @@ mod tests { Ok(()) } - // FIXME refactor helper functions - fn create_token_from_fixture(fixture: String) -> Result { + fn create_token_from_fixture(fixture: &str) -> Result { let base_dir = std::env::var("CARGO_MANIFEST_DIR")?; let raw_token = std::fs::read_to_string(format!("{base_dir}/src/fixtures/{fixture}"))?; Ok(raw_token.trim().to_string().try_into()?) } - - fn create_request_from_fixture(fixture: String) -> Result { - let base_dir = std::env::var("CARGO_MANIFEST_DIR")?; - let raw_token = std::fs::read_to_string(format!("{base_dir}/src/fixtures/{fixture}"))?; - Ok(serde_json::from_str::(&raw_token)?) - } - - fn create_blinded_msgs_from_fixture( - fixture: String, - ) -> Result, anyhow::Error> { - let base_dir = std::env::var("CARGO_MANIFEST_DIR")?; - let raw_token = std::fs::read_to_string(format!("{base_dir}/src/fixtures/{fixture}"))?; - Ok(serde_json::from_str::>(&raw_token)?) - } + async fn create_mint_from_mocks( mock_db: PostgresDB, diff --git a/moksha-mint/src/model.rs b/moksha-mint/src/model.rs index 365e7a08..37f74f3d 100644 --- a/moksha-mint/src/model.rs +++ b/moksha-mint/src/model.rs @@ -1,14 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Serialize, Deserialize)] -pub struct GetMintQuery { - pub amount: u64, -} -#[derive(Debug, Serialize, Deserialize)] -pub struct PostMintQuery { - pub hash: String, -} #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Invoice { diff --git a/moksha-mint/src/routes/legacy.rs b/moksha-mint/src/routes/legacy.rs deleted file mode 100644 index c5d90f6c..00000000 --- a/moksha-mint/src/routes/legacy.rs +++ /dev/null @@ -1,120 +0,0 @@ -use std::collections::HashMap; - -use axum::{ - extract::{Query, State}, - Json, -}; -use moksha_core::{ - keyset::{generate_hash, Keysets}, - primitives::{ - CheckFeesRequest, CheckFeesResponse, PaymentMethod, PaymentRequest, PostMeltRequest, - PostMeltResponse, PostMintRequest, PostMintResponse, PostSplitRequest, PostSplitResponse, - }, -}; -use secp256k1::PublicKey; -use tracing::{event, Level}; - -use crate::database::Database; -use crate::{ - error::MokshaMintError, - mint::Mint, - model::{GetMintQuery, PostMintQuery}, -}; - -pub async fn get_legacy_keys( - State(mint): State, -) -> Result>, MokshaMintError> { - Ok(Json(mint.keyset_legacy.public_keys)) -} - -pub async fn get_legacy_keysets( - State(mint): State, -) -> Result, MokshaMintError> { - Ok(Json(Keysets::new(vec![mint.keyset_legacy.keyset_id]))) -} - -pub async fn get_legacy_mint( - State(mint): State, - Query(mint_query): Query, -) -> Result, MokshaMintError> { - let (pr, hash) = mint - .create_invoice(generate_hash(), mint_query.amount) - .await?; - Ok(Json(PaymentRequest { pr, hash })) -} - -pub async fn post_legacy_mint( - State(mint): State, - Query(mint_query): Query, - Json(blinded_messages): Json, -) -> Result, MokshaMintError> { - event!( - Level::INFO, - "post_mint: {mint_query:#?} {blinded_messages:#?}" - ); - let mut tx = mint.db.begin_tx().await?; - - let promises = mint - .mint_tokens( - &mut tx, - PaymentMethod::Bolt11, - mint_query.hash, - &blinded_messages.outputs, - &mint.keyset_legacy, - true, - ) - .await?; - Ok(Json(PostMintResponse { promises })) -} - -pub async fn post_legacy_split( - State(mint): State, - Json(swap_request): Json, -) -> Result, MokshaMintError> { - let response = mint - .swap( - &swap_request.proofs, - &swap_request.outputs, - &mint.keyset_legacy, - ) - .await?; - - Ok(Json(PostSplitResponse::with_promises(response))) -} - -pub async fn post_legacy_melt( - State(mint): State, - Json(melt_request): Json, -) -> Result, MokshaMintError> { - let mut tx = mint.db.begin_tx().await?; - let (paid, preimage, change) = mint - .melt_bolt11( - &mut tx, - melt_request.pr, - 0, // FIXME set correct fee reserve for legacy api - &melt_request.proofs, - &melt_request.outputs, - &mint.keyset_legacy, - ) - .await?; - - tx.commit().await?; - Ok(Json(PostMeltResponse { - paid, - preimage, - change, - })) -} - -pub async fn post_legacy_check_fees( - State(mint): State, - Json(_check_fees): Json, -) -> Result, MokshaMintError> { - let invoice = mint.lightning.decode_invoice(_check_fees.pr).await?; - - Ok(Json(CheckFeesResponse { - fee: mint.fee_reserve(invoice.amount_milli_satoshis().ok_or_else(|| { - crate::error::MokshaMintError::InvalidAmount("invalid invoice".to_owned()) - })?), - })) -} diff --git a/moksha-mint/src/routes/mod.rs b/moksha-mint/src/routes/mod.rs index 8c40175e..9e643136 100644 --- a/moksha-mint/src/routes/mod.rs +++ b/moksha-mint/src/routes/mod.rs @@ -1,3 +1,2 @@ pub mod btconchain; pub mod default; -pub mod legacy; diff --git a/moksha-mint/src/server.rs b/moksha-mint/src/server.rs index 8eacb3cf..a1758817 100644 --- a/moksha-mint/src/server.rs +++ b/moksha-mint/src/server.rs @@ -1,4 +1,4 @@ -use crate::error::MokshaMintError; + use crate::routes::btconchain::{ get_melt_btconchain, get_melt_quote_btconchain, get_mint_quote_btconchain, post_melt_btconchain, post_melt_quote_btconchain, post_mint_btconchain, @@ -8,13 +8,13 @@ use crate::routes::default::{ get_info, get_keys, get_keys_by_id, get_keysets, get_melt_quote_bolt11, get_mint_quote_bolt11, post_melt_bolt11, post_melt_quote_bolt11, post_mint_bolt11, post_mint_quote_bolt11, post_swap, }; -use axum::extract::{Request, State}; +use axum::extract::Request; use axum::http::{HeaderName, HeaderValue, StatusCode}; use axum::middleware::Next; use axum::response::IntoResponse; -use axum::routing::{get_service, post}; +use axum::routing::{get_service, post, get}; use axum::{middleware, Router}; -use axum::{routing::get, Json}; + use moksha_core::keyset::{V1Keyset, V1Keysets}; use moksha_core::proof::Proofs; @@ -28,7 +28,7 @@ use moksha_core::blind::BlindedMessage; use moksha_core::blind::BlindedSignature; use moksha_core::primitives::{ CurrencyUnit, GetMeltBtcOnchainResponse, KeyResponse, KeysResponse, MintInfoResponse, - MintLegacyInfoResponse, Nut10, Nut11, Nut12, Nut17, Nut18, Nut4, Nut5, Nut7, Nut8, Nut9, Nuts, + Nut10, Nut11, Nut12, Nut17, Nut18, Nut4, Nut5, Nut7, Nut8, Nut9, Nuts, PaymentMethod, PostMeltBolt11Request, PostMeltBolt11Response, PostMeltQuoteBolt11Request, PostMeltQuoteBolt11Response, PostMeltQuoteBtcOnchainRequest, PostMeltQuoteBtcOnchainResponse, PostMintBolt11Request, PostMintBolt11Response, PostMintQuoteBolt11Request, @@ -43,10 +43,6 @@ use tracing::info; use utoipa::OpenApi; -use crate::routes::legacy::{ - get_legacy_keys, get_legacy_keysets, get_legacy_mint, post_legacy_check_fees, post_legacy_melt, - post_legacy_mint, post_legacy_split, -}; pub async fn run_server(mint: Mint) -> anyhow::Result<()> { if let Some(ref buildtime) = mint.build_params.build_time { @@ -163,15 +159,7 @@ pub async fn run_server(mint: Mint) -> anyhow::Result<()> { struct ApiDoc; fn app(mint: Mint) -> Router { - let legacy_routes = Router::new() - .route("/keys", get(get_legacy_keys)) - .route("/keysets", get(get_legacy_keysets)) - .route("/mint", get(get_legacy_mint).post(post_legacy_mint)) - .route("/checkfees", post(post_legacy_check_fees)) - .route("/melt", post(post_legacy_melt)) - .route("/split", post(post_legacy_split)) - .route("/info", get(get_legacy_info)); - + let default_routes = Router::new() .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi())) .route("/v1/keys", get(get_keys)) @@ -217,7 +205,6 @@ fn app(mint: Mint) -> Router { let prefix = server_config.api_prefix.unwrap_or_else(|| "".to_owned()); let router = Router::new() - .nest(&prefix, legacy_routes) .nest(&prefix, default_routes) .nest(&prefix, btconchain_routes) .nest("", general_routes) @@ -266,35 +253,6 @@ async fn add_response_headers( Ok(res) } -async fn get_legacy_info( - State(mint): State, -) -> Result, MokshaMintError> { - let mint_info = MintLegacyInfoResponse { - name: mint.config.info.name, - pubkey: mint.keyset_legacy.mint_pubkey, - version: match mint.config.info.version { - true => Some(mint.build_params.full_version()), - _ => None, - }, - description: mint.config.info.description, - description_long: mint.config.info.description_long, - contact: None, // FIXME set contact - nuts: vec![ - "NUT-00".to_string(), - "NUT-01".to_string(), - "NUT-02".to_string(), - "NUT-03".to_string(), - "NUT-04".to_string(), - "NUT-05".to_string(), - "NUT-06".to_string(), - "NUT-08".to_string(), - "NUT-09".to_string(), - ], - motd: mint.config.info.motd, - parameter: Default::default(), - }; - Ok(Json(mint_info)) -} #[utoipa::path( get, @@ -311,7 +269,7 @@ async fn get_health() -> impl IntoResponse { #[cfg(test)] mod tests { - use std::{collections::HashMap, sync::Arc}; + use std::sync::Arc; use crate::{ btconchain::MockBtcOnchain, @@ -325,10 +283,10 @@ mod tests { }; use http_body_util::BodyExt; use moksha_core::{ - keyset::{Keysets, V1Keysets}, - primitives::{CurrencyUnit, KeysResponse, MintLegacyInfoResponse}, + keyset::V1Keysets, + primitives::{CurrencyUnit, KeysResponse, MintInfoResponse}, }; - use secp256k1::PublicKey; + use testcontainers::{clients::Cli, RunnableImage}; use testcontainers_modules::postgres::Postgres; use tower::ServiceExt; @@ -338,6 +296,7 @@ mod tests { lightning::{LightningType, MockLightning}, mint::Mint, }; + use pretty_assertions::assert_eq; #[tokio::test] async fn test_get_keys() -> anyhow::Result<()> { @@ -347,13 +306,13 @@ mod tests { let app = app(create_mock_mint(Default::default(), node.get_host_port_ipv4(5432)).await?); let response = app - .oneshot(Request::builder().uri("/keys").body(Body::empty())?) + .oneshot(Request::builder().uri("/v1/keys").body(Body::empty())?) .await?; assert_eq!(response.status(), StatusCode::OK); let body = response.into_body().collect().await?.to_bytes(); - let keys: HashMap = serde_json::from_slice(&body)?; - assert_eq!(64, keys.len()); + let keys: KeysResponse = serde_json::from_slice(&body)?; + assert_eq!(64, keys.keysets[0].keys.len()); Ok(()) } @@ -365,47 +324,16 @@ mod tests { let app = app(create_mock_mint(Default::default(), node.get_host_port_ipv4(5432)).await?); let response = app - .oneshot(Request::builder().uri("/keysets").body(Body::empty())?) + .oneshot(Request::builder().uri("/v1/keysets").body(Body::empty())?) .await?; - assert_eq!(response.status(), StatusCode::OK); let body = response.into_body().collect().await?.to_bytes(); - let keysets = serde_json::from_slice::(&body)?; - assert_eq!(Keysets::new(vec!["53eJP2+qJyTd".to_string()]), keysets); + let keysets = serde_json::from_slice::(&body)?; + assert_eq!(V1Keysets::new("00f545318e4fad2b".to_owned(), CurrencyUnit::Sat, true), keysets); Ok(()) } - #[tokio::test] - async fn test_get_info() -> anyhow::Result<()> { - let docker = Cli::default(); - let image = create_postgres_image(); - let node = docker.run(image); - - let mint_info_settings = MintInfoConfig { - name: Some("Bob's Cashu mint".to_string()), - version: true, - description: Some("A mint for testing".to_string()), - description_long: Some("A mint for testing long".to_string()), - ..Default::default() - }; - let app = app(create_mock_mint(mint_info_settings, node.get_host_port_ipv4(5432)).await?); - let response = app - .oneshot(Request::builder().uri("/info").body(Body::empty())?) - .await?; - - assert_eq!(response.status(), StatusCode::OK); - let body = response.into_body().collect().await?.to_bytes(); - let info = serde_json::from_slice::(&body)?; - assert!(!info.parameter.peg_out_only); - assert_eq!(info.nuts.len(), 9); - assert_eq!(info.name, Some("Bob's Cashu mint".to_string())); - assert_eq!(info.description, Some("A mint for testing".to_string())); - assert_eq!( - info.description_long, - Some("A mint for testing long".to_string()) - ); - Ok(()) - } + // FIXME remove duplicated code from mint.rs async fn create_mock_db_empty(port: u16) -> anyhow::Result { @@ -595,4 +523,34 @@ mod tests { assert_eq!(response.status(), StatusCode::OK); Ok(()) } + + #[tokio::test] + async fn test_get_info() -> anyhow::Result<()> { + let docker = Cli::default(); + let image = create_postgres_image(); + let node = docker.run(image); + + let mint_info_settings = MintInfoConfig { + name: Some("Bob's Cashu mint".to_string()), + version: true, + description: Some("A mint for testing".to_string()), + description_long: Some("A mint for testing long".to_string()), + ..Default::default() + }; + let app = app(create_mock_mint(mint_info_settings, node.get_host_port_ipv4(5432)).await?); + let response = app + .oneshot(Request::builder().uri("/v1/info").body(Body::empty())?) + .await?; + + assert_eq!(response.status(), StatusCode::OK); + let body = response.into_body().collect().await?.to_bytes(); + let info = serde_json::from_slice::(&body)?; + assert_eq!(info.name, Some("Bob's Cashu mint".to_string())); + assert_eq!(info.description, Some("A mint for testing".to_string())); + assert_eq!( + info.description_long, + Some("A mint for testing long".to_string()) + ); + Ok(()) + } }