1use axum::{
2 extract::{Json, State},
3 http::status::StatusCode,
4 response::IntoResponse,
5};
6use std::sync::Arc;
7
8use crate::{ApiError, ApiErrorStatus, InternalState, BASE_PATH};
9
10#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
11#[schema(example = json!({
12 "price": "30000000000000000"
13}))]
14#[serde(rename_all = "camelCase")]
15pub(crate) struct TicketPriceResponse {
16 price: String,
18}
19
20#[utoipa::path(
22 get,
23 path = const_format::formatcp!("{BASE_PATH}/network/price"),
24 responses(
25 (status = 200, description = "Current ticket price", body = TicketPriceResponse),
26 (status = 401, description = "Invalid authorization token.", body = ApiError),
27 (status = 422, description = "Unknown failure", body = ApiError)
28 ),
29 security(
30 ("api_token" = []),
31 ("bearer_token" = [])
32 ),
33 tag = "Network"
34 )]
35pub(super) async fn price(State(state): State<Arc<InternalState>>) -> impl IntoResponse {
36 let hopr = state.hopr.clone();
37
38 match hopr.get_ticket_price().await {
39 Ok(Some(price)) => (
40 StatusCode::OK,
41 Json(TicketPriceResponse {
42 price: price.to_string(),
43 }),
44 )
45 .into_response(),
46 Ok(None) => (
47 StatusCode::UNPROCESSABLE_ENTITY,
48 ApiErrorStatus::UnknownFailure("The ticket price is not available".into()),
49 )
50 .into_response(),
51 Err(e) => (StatusCode::UNPROCESSABLE_ENTITY, ApiErrorStatus::from(e)).into_response(),
52 }
53}
54
55#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
56#[schema(example = json!({
57 "probability": 0.5
58}))]
59#[serde(rename_all = "camelCase")]
60pub(crate) struct TicketProbabilityResponse {
61 probability: f64,
63}
64
65#[utoipa::path(
67 get,
68 path = const_format::formatcp!("{BASE_PATH}/network/probability"),
69 responses(
70 (status = 200, description = "Minimum incoming ticket winning probability defined by the network", body = TicketProbabilityResponse),
71 (status = 401, description = "Invalid authorization token.", body = ApiError),
72 (status = 422, description = "Unknown failure", body = ApiError)
73 ),
74 security(
75 ("api_token" = []),
76 ("bearer_token" = [])
77 ),
78 tag = "Network"
79 )]
80pub(super) async fn probability(State(state): State<Arc<InternalState>>) -> impl IntoResponse {
81 let hopr = state.hopr.clone();
82
83 match hopr.get_minimum_incoming_ticket_win_probability().await {
84 Ok(probability) => (StatusCode::OK, Json(TicketProbabilityResponse { probability })).into_response(),
85 Err(e) => (StatusCode::UNPROCESSABLE_ENTITY, ApiErrorStatus::from(e)).into_response(),
86 }
87}