Skip to main content

fuel_core_client/client/schema/
node_info.rs

1use crate::client::schema::{
2    U32,
3    U64,
4    schema,
5};
6#[cfg(feature = "std")]
7use fuel_core_types::services::p2p::{
8    HeartbeatData,
9    PeerId,
10};
11#[cfg(feature = "std")]
12use std::{
13    str::FromStr,
14    time::{
15        Duration,
16        UNIX_EPOCH,
17    },
18};
19
20#[derive(cynic::QueryFragment, Clone, Debug)]
21#[cynic(schema_path = "./assets/schema.sdl")]
22pub struct NodeInfo {
23    pub utxo_validation: bool,
24    pub vm_backtrace: bool,
25    pub max_tx: U64,
26    pub max_gas: U64,
27    pub max_size: U64,
28    pub max_depth: U64,
29    pub node_version: String,
30    pub indexation: IndexationFlags,
31    pub tx_pool_stats: TxPoolStats,
32}
33
34#[derive(cynic::QueryFragment, Clone, Debug)]
35#[cynic(schema_path = "./assets/schema.sdl", graphql_type = "Query")]
36pub struct QueryNodeInfo {
37    pub node_info: NodeInfo,
38}
39
40// Use a separate GQL query for showing peer info, as the endpoint is bulky and may return an error
41// if the `p2p` feature is disabled.
42
43#[derive(cynic::QueryFragment, Clone, Debug)]
44#[cynic(schema_path = "./assets/schema.sdl", graphql_type = "NodeInfo")]
45pub struct PeersInfo {
46    pub peers: Vec<PeerInfo>,
47}
48
49#[derive(cynic::QueryFragment, Clone, Debug)]
50#[cynic(schema_path = "./assets/schema.sdl", graphql_type = "Query")]
51pub struct QueryPeersInfo {
52    pub node_info: PeersInfo,
53}
54
55#[derive(cynic::QueryFragment, Clone, Debug)]
56#[cynic(schema_path = "./assets/schema.sdl")]
57pub struct PeerInfo {
58    pub id: String,
59    pub addresses: Vec<String>,
60    pub client_version: Option<String>,
61    pub block_height: Option<U32>,
62    pub last_heartbeat_ms: U64,
63    pub app_score: f64,
64}
65
66#[cfg(feature = "std")]
67impl From<PeerInfo> for fuel_core_types::services::p2p::PeerInfo {
68    fn from(info: PeerInfo) -> Self {
69        Self {
70            id: PeerId::from_str(info.id.as_str()).unwrap_or_default(),
71            peer_addresses: info.addresses.into_iter().collect(),
72            client_version: info.client_version,
73            heartbeat_data: HeartbeatData {
74                block_height: info.block_height.map(|h| h.0.into()),
75                last_heartbeat: UNIX_EPOCH
76                    .checked_add(Duration::from_millis(info.last_heartbeat_ms.0))
77                    .unwrap_or(UNIX_EPOCH),
78            },
79            app_score: info.app_score,
80        }
81    }
82}
83
84#[derive(cynic::QueryFragment, Clone, Debug, PartialEq, Eq)]
85#[cynic(schema_path = "./assets/schema.sdl")]
86pub struct TxPoolStats {
87    pub tx_count: U64,
88    pub total_gas: U64,
89    pub total_size: U64,
90}
91
92#[derive(cynic::QueryFragment, Clone, Debug, PartialEq, Eq)]
93#[cynic(schema_path = "./assets/schema.sdl")]
94pub struct IndexationFlags {
95    pub balances: bool,
96    pub coins_to_spend: bool,
97    pub asset_metadata: bool,
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn node_info_query_gql_output() {
106        use cynic::QueryBuilder;
107        let operation = QueryNodeInfo::build(());
108        insta::assert_snapshot!(operation.query)
109    }
110
111    #[test]
112    fn peers_info_query_gql_output() {
113        use cynic::QueryBuilder;
114        let operation = QueryPeersInfo::build(());
115        insta::assert_snapshot!(operation.query)
116    }
117}