mina_node_native/http_server/routes/
stats.rs1use axum::{
8 extract::{Query, State},
9 Json,
10};
11use serde::Deserialize;
12use utoipa_axum::{router::OpenApiRouter, routes};
13
14use mina_node::rpc::{
15 ActionStatsQuery, RpcActionStatsGetResponse, RpcBlockProducerStatsGetResponse, RpcRequest,
16 RpcSyncStatsGetResponse, SyncStatsQuery,
17};
18
19use crate::http_server::{AppError, AppResult, AppState, JsonErrorResponse};
20
21pub fn routes() -> OpenApiRouter<AppState> {
23 OpenApiRouter::new()
24 .routes(routes!(actions))
25 .routes(routes!(sync))
26 .routes(routes!(block_producer))
27}
28
29#[derive(Deserialize, Default)]
30struct ActionQueryParams {
31 id: Option<String>,
33}
34
35#[utoipa::path(
37 get,
38 path = "/stats/actions",
39 tag = "stats",
40 params(
41 ("id" = Option<String>, Query, description = "\"latest\" for latest block, or numeric block ID")
42 ),
43 responses(
44 (status = 200, description = "Action statistics", body = inline(RpcActionStatsGetResponse)),
46 (status = 400, description = "Invalid id parameter", body = JsonErrorResponse,
47 example = json!({"error": "'id' must be an u64 integer: invalid digit found in string, instead passed: foo"}))
48 )
49)]
50async fn actions(
51 State(state): State<AppState>,
52 Query(params): Query<ActionQueryParams>,
53) -> AppResult<Json<RpcActionStatsGetResponse>> {
54 let query = match params.id.as_deref() {
55 None => ActionStatsQuery::SinceStart,
56 Some("latest") => ActionStatsQuery::ForLatestBlock,
57 Some(id) => {
58 let id: u64 = id.parse().map_err(|err| {
59 AppError::BadRequest(format!(
60 "'id' must be an u64 integer: {err}, instead passed: {id}"
61 ))
62 })?;
63 ActionStatsQuery::ForBlockWithId(id)
64 }
65 };
66
67 jsonify_rpc!(state, RpcRequest::ActionStatsGet(query))
68}
69
70#[derive(Deserialize, Default)]
71struct SyncQueryParams {
72 limit: Option<usize>,
74}
75
76#[utoipa::path(
78 get,
79 path = "/stats/sync",
80 tag = "stats",
81 params(
82 ("limit" = Option<usize>, Query, description = "Max number of sync snapshots to return")
83 ),
84 responses(
85 (status = 200, description = "Sync statistics", body = inline(RpcSyncStatsGetResponse))
87 )
88)]
89async fn sync(
90 State(state): State<AppState>,
91 Query(SyncQueryParams { limit }): Query<SyncQueryParams>,
92) -> AppResult<Json<RpcSyncStatsGetResponse>> {
93 jsonify_rpc!(state, RpcRequest::SyncStatsGet(SyncStatsQuery { limit }))
94}
95
96#[utoipa::path(
98 get,
99 path = "/stats/block_producer",
100 tag = "stats",
101 responses(
102 (status = 200, description = "Block producer statistics", body = inline(RpcBlockProducerStatsGetResponse))
104 )
105)]
106async fn block_producer(
107 State(state): State<AppState>,
108) -> AppResult<Json<RpcBlockProducerStatsGetResponse>> {
109 jsonify_rpc!(state, RpcRequest::BlockProducerStatsGet)
110}