iota_rest_api/
info.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::borrow::Cow;
6
7use axum::{Json, extract::State};
8use iota_sdk2::types::CheckpointDigest;
9use tap::Pipe;
10
11use crate::{
12    RestService, Result,
13    openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler},
14};
15
16pub struct GetNodeInfo;
17
18impl ApiEndpoint<RestService> for GetNodeInfo {
19    fn method(&self) -> axum::http::Method {
20        axum::http::Method::GET
21    }
22
23    fn path(&self) -> &'static str {
24        "/"
25    }
26
27    fn operation(
28        &self,
29        generator: &mut schemars::gen::SchemaGenerator,
30    ) -> openapiv3::v3_1::Operation {
31        OperationBuilder::new()
32            .tag("General")
33            .operation_id("GetNodeInfo")
34            .response(
35                200,
36                ResponseBuilder::new()
37                    .json_content::<NodeInfo>(generator)
38                    .build(),
39            )
40            .build()
41    }
42
43    fn handler(&self) -> crate::openapi::RouteHandler<RestService> {
44        RouteHandler::new(self.method(), get_node_info)
45    }
46}
47
48async fn get_node_info(State(state): State<RestService>) -> Result<Json<NodeInfo>> {
49    let latest_checkpoint = state.reader.inner().get_latest_checkpoint()?;
50    let lowest_available_checkpoint = state.reader.inner().get_lowest_available_checkpoint()?;
51    let lowest_available_checkpoint_objects = state
52        .reader
53        .inner()
54        .get_lowest_available_checkpoint_objects()?;
55
56    NodeInfo {
57        checkpoint_height: latest_checkpoint.sequence_number,
58        lowest_available_checkpoint,
59        lowest_available_checkpoint_objects,
60        timestamp_ms: latest_checkpoint.timestamp_ms,
61        epoch: latest_checkpoint.epoch(),
62        chain_id: CheckpointDigest::new(state.chain_id().as_bytes().to_owned()),
63        chain: state.chain_id().chain().as_str().into(),
64        software_version: state.software_version().into(),
65    }
66    .pipe(Json)
67    .pipe(Ok)
68}
69
70#[serde_with::serde_as]
71#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
72pub struct NodeInfo {
73    pub chain_id: CheckpointDigest,
74    pub chain: Cow<'static, str>,
75    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
76    #[schemars(with = "crate::_schemars::U64")]
77    pub epoch: u64,
78    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
79    #[schemars(with = "crate::_schemars::U64")]
80    pub checkpoint_height: u64,
81    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
82    #[schemars(with = "crate::_schemars::U64")]
83    pub timestamp_ms: u64,
84    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
85    #[schemars(with = "crate::_schemars::U64")]
86    pub lowest_available_checkpoint: u64,
87    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
88    #[schemars(with = "crate::_schemars::U64")]
89    pub lowest_available_checkpoint_objects: u64,
90    pub software_version: Cow<'static, str>,
91    // TODO include current protocol version
92}