1use 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 }