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_sdk_types::Digest;
9use tap::Pipe;
10
11use crate::{
12    RestService, Result,
13    openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler},
14};
15
16/// Get basic information about the state of a Node
17pub struct GetNodeInfo;
18
19impl ApiEndpoint<RestService> for GetNodeInfo {
20    fn method(&self) -> axum::http::Method {
21        axum::http::Method::GET
22    }
23
24    fn path(&self) -> &'static str {
25        "/"
26    }
27
28    fn stable(&self) -> bool {
29        true
30    }
31
32    fn operation(
33        &self,
34        generator: &mut schemars::gen::SchemaGenerator,
35    ) -> openapiv3::v3_1::Operation {
36        OperationBuilder::new()
37            .tag("General")
38            .operation_id("Get NodeInfo")
39            .response(
40                200,
41                ResponseBuilder::new()
42                    .json_content::<NodeInfo>(generator)
43                    .build(),
44            )
45            .response(500, ResponseBuilder::new().build())
46            .build()
47    }
48
49    fn handler(&self) -> crate::openapi::RouteHandler<RestService> {
50        RouteHandler::new(self.method(), get_node_info)
51    }
52}
53
54async fn get_node_info(State(state): State<RestService>) -> Result<Json<NodeInfo>> {
55    let latest_checkpoint = state.reader.inner().try_get_latest_checkpoint()?;
56    let lowest_available_checkpoint = state
57        .reader
58        .inner()
59        .try_get_lowest_available_checkpoint()?
60        .pipe(Some);
61    let lowest_available_checkpoint_objects = state
62        .reader
63        .inner()
64        .get_lowest_available_checkpoint_objects()?
65        .pipe(Some);
66
67    NodeInfo {
68        checkpoint_height: latest_checkpoint.sequence_number,
69        lowest_available_checkpoint,
70        lowest_available_checkpoint_objects,
71        timestamp_ms: latest_checkpoint.timestamp_ms,
72        epoch: latest_checkpoint.epoch(),
73        chain_id: Digest::new(state.chain_id().as_bytes().to_owned()),
74        chain: state.chain_id().chain().as_str().into(),
75        software_version: state
76            .server_version()
77            .map(ToString::to_string)
78            .unwrap_or_default()
79            .into(),
80    }
81    .pipe(Json)
82    .pipe(Ok)
83}
84
85/// Basic information about the state of a Node
86#[serde_with::serde_as]
87#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
88pub struct NodeInfo {
89    /// The chain identifier of the chain that this Node is on
90    pub chain_id: Digest,
91
92    /// Human readable name of the chain that this Node is on
93    pub chain: Cow<'static, str>,
94
95    /// Current epoch of the Node based on its highest executed checkpoint
96    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
97    #[schemars(with = "crate::_schemars::U64")]
98    pub epoch: u64,
99
100    /// Checkpoint height of the most recently executed checkpoint
101    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
102    #[schemars(with = "crate::_schemars::U64")]
103    pub checkpoint_height: u64,
104
105    /// Unix timestamp of the most recently executed checkpoint
106    #[serde_as(as = "iota_types::iota_serde::BigInt<u64>")]
107    #[schemars(with = "crate::_schemars::U64")]
108    pub timestamp_ms: u64,
109
110    /// The lowest checkpoint for which checkpoints and transaction data is
111    /// available
112    #[serde_as(as = "Option<iota_types::iota_serde::BigInt<u64>>")]
113    #[schemars(with = "Option<crate::_schemars::U64>")]
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub lowest_available_checkpoint: Option<u64>,
116
117    /// The lowest checkpoint for which object data is available
118    #[serde_as(as = "Option<iota_types::iota_serde::BigInt<u64>>")]
119    #[schemars(with = "Option<crate::_schemars::U64>")]
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub lowest_available_checkpoint_objects: Option<u64>,
122    pub software_version: Cow<'static, str>,
123    // TODO include current protocol version
124}