hoprd_api/
network.rs

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 of the ticket in HOPR tokens.
17    price: String,
18}
19
20/// Obtains the current ticket price.
21#[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    /// Winning probability of a ticket.
62    probability: f64,
63}
64
65/// Gets the current minimum incoming ticket winning probability defined by the network.
66#[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}