diff --git a/bindings/nodejs/lib/types/models/api/node.ts b/bindings/nodejs/lib/types/models/api/node.ts index f9fc055530..8940faf6f7 100644 --- a/bindings/nodejs/lib/types/models/api/node.ts +++ b/bindings/nodejs/lib/types/models/api/node.ts @@ -13,6 +13,10 @@ export interface StatusResponse { * Tells whether the node is healthy or not. */ isHealthy: boolean; + /** + * Tells whether the network is healthy (finalization is not delayed). + */ + isNetworkHealthy: boolean; /** * A notion of time that is anchored to the latest accepted block. */ diff --git a/bindings/python/iota_sdk/types/node_info.py b/bindings/python/iota_sdk/types/node_info.py index 3f7ef621dd..12f6621d01 100644 --- a/bindings/python/iota_sdk/types/node_info.py +++ b/bindings/python/iota_sdk/types/node_info.py @@ -16,6 +16,7 @@ class StatusResponse: Attributes: is_healthy: Tells whether the node is healthy or not. + is_network_healthy: Tells whether the network is healthy (finalization is not delayed). accepted_tangle_time: A notion of time that is anchored to the latest accepted block. relative_accepted_tangle_time: The time after Accepted Tangle Time has advanced with the system clock. confirmed_tangle_time: A notion of time that is anchored to the latest confirmed block. @@ -27,6 +28,7 @@ class StatusResponse: pruning_epoch: The index of the epoch before which the tangle history is pruned. """ is_healthy: bool + is_network_healthy: bool accepted_tangle_time: int = field(metadata=config( encoder=str )) diff --git a/sdk/examples/how_tos/client/get_health.rs b/sdk/examples/how_tos/client/get_health.rs index 96570fdbba..fc5936e0c6 100644 --- a/sdk/examples/how_tos/client/get_health.rs +++ b/sdk/examples/how_tos/client/get_health.rs @@ -29,8 +29,9 @@ async fn main() -> Result<(), Box> { // Get node health. let is_healthy = client.get_health(&node_url).await?; + let is_network_healthy = client.get_network_health().await?; - println!("Healthy: {is_healthy}"); + println!("Healthy: node {is_healthy}, network {is_network_healthy}"); Ok(()) } diff --git a/sdk/src/client/node_api/core/routes.rs b/sdk/src/client/node_api/core/routes.rs index 098d57ed5e..98e1798ad0 100644 --- a/sdk/src/client/node_api/core/routes.rs +++ b/sdk/src/client/node_api/core/routes.rs @@ -96,6 +96,25 @@ impl ClientInner { self.get_request(PATH, None, false).await } + + /// Returns whether the network is healthy (finalization is not delayed). + /// GET /api/core/v3/network/health + pub async fn get_network_health(&self) -> Result { + const PATH: &str = "api/core/v3/network/health"; + + let nodes = self.node_manager.read().await.get_nodes(PATH, None)?; + let client = crate::client::node_manager::http_client::HttpClient::new(DEFAULT_USER_AGENT.to_string()); + + for node in &nodes { + if let Ok(res) = client.get(node, DEFAULT_API_TIMEOUT).await { + if res.status() == 200 { + return Ok(true); + } + } + } + + Ok(false) + } } impl Client { diff --git a/sdk/src/client/node_manager/mod.rs b/sdk/src/client/node_manager/mod.rs index 3f61d8619a..ecc022b084 100644 --- a/sdk/src/client/node_manager/mod.rs +++ b/sdk/src/client/node_manager/mod.rs @@ -104,7 +104,7 @@ impl NodeManager { NodeManagerBuilder::new() } - fn get_nodes(&self, path: &str, query: Option<&str>) -> Result, ClientError> { + pub(crate) fn get_nodes(&self, path: &str, query: Option<&str>) -> Result, ClientError> { let mut nodes_with_modified_url: Vec = Vec::new(); // Set primary nodes first, so they will also be used first for requests. diff --git a/sdk/src/types/api/core.rs b/sdk/src/types/api/core.rs index 04d24589c6..b47b39b75e 100644 --- a/sdk/src/types/api/core.rs +++ b/sdk/src/types/api/core.rs @@ -89,6 +89,7 @@ impl PermanodeInfoResponse { #[serde(rename_all = "camelCase")] pub struct StatusResponse { pub is_healthy: bool, + pub is_network_healthy: bool, #[serde(with = "option_string")] pub accepted_tangle_time: Option, #[serde(with = "option_string")]