use num_bigint::BigInt;
use reqwest::Method;
use serde::{Deserialize, Deserializer};
use crate::client::request;
use crate::swarm::Error;
use super::DebugApi;
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Health {
pub status: String,
pub version: String,
pub api_version: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BeeVersions {
pub bee_version: String,
pub bee_api_version: String,
pub supported_api_version: String,
pub supported_bee_version_exact: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChainState {
pub block: u64,
pub chain_tip: u64,
#[serde(default, deserialize_with = "deserialize_bigint_string")]
pub current_price: BigInt,
#[serde(default, deserialize_with = "deserialize_bigint_string")]
pub total_amount: BigInt,
}
fn deserialize_bigint_string<'de, D>(d: D) -> Result<BigInt, D::Error>
where
D: Deserializer<'de>,
{
let s: String = Deserialize::deserialize(d)?;
if s.is_empty() {
return Ok(BigInt::from(0));
}
s.parse::<BigInt>().map_err(serde::de::Error::custom)
}
pub const SUPPORTED_API_VERSION: &str = "8.0.0";
pub const SUPPORTED_BEE_VERSION_EXACT: &str = "2.7.2-rc1-83612d37";
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NodeInfo {
pub bee_mode: String,
pub chequebook_enabled: bool,
pub swap_enabled: bool,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Status {
pub overlay: String,
pub proximity: i64,
pub bee_mode: String,
pub reserve_size: i64,
pub reserve_size_within_radius: i64,
pub pullsync_rate: f64,
pub storage_radius: i64,
pub connected_peers: i64,
pub neighborhood_size: i64,
pub batch_commitment: i64,
pub is_reachable: bool,
pub last_synced_block: i64,
pub committed_depth: i64,
pub is_warming_up: bool,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PeerStatus {
#[serde(flatten)]
pub status: Status,
#[serde(default)]
pub request_failed: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Neighborhood {
pub neighborhood: String,
pub reserve_size_within_radius: i64,
pub proximity: u8,
}
impl DebugApi {
pub async fn health(&self) -> Result<Health, Error> {
let builder = request(&self.inner, Method::GET, "health")?;
self.inner.send_json(builder).await
}
pub async fn versions(&self) -> Result<BeeVersions, Error> {
let h = self.health().await?;
Ok(BeeVersions {
bee_version: h.version,
bee_api_version: h.api_version,
supported_api_version: SUPPORTED_API_VERSION.to_string(),
supported_bee_version_exact: SUPPORTED_BEE_VERSION_EXACT.to_string(),
})
}
pub async fn is_supported_api_version(&self) -> Result<bool, Error> {
let h = self.health().await?;
Ok(h.api_version == SUPPORTED_API_VERSION)
}
pub async fn is_supported_exact_version(&self) -> Result<bool, Error> {
let h = self.health().await?;
Ok(h.version == SUPPORTED_BEE_VERSION_EXACT)
}
pub async fn chain_state(&self) -> Result<ChainState, Error> {
let builder = request(&self.inner, Method::GET, "chainstate")?;
self.inner.send_json(builder).await
}
pub async fn node_info(&self) -> Result<NodeInfo, Error> {
let builder = request(&self.inner, Method::GET, "node")?;
self.inner.send_json(builder).await
}
pub async fn status(&self) -> Result<Status, Error> {
let builder = request(&self.inner, Method::GET, "status")?;
self.inner.send_json(builder).await
}
pub async fn status_peers(&self) -> Result<Vec<PeerStatus>, Error> {
let builder = request(&self.inner, Method::GET, "status/peers")?;
#[derive(Deserialize)]
struct Resp {
snapshots: Vec<PeerStatus>,
}
let r: Resp = self.inner.send_json(builder).await?;
Ok(r.snapshots)
}
pub async fn status_neighborhoods(&self) -> Result<Vec<Neighborhood>, Error> {
let builder = request(&self.inner, Method::GET, "status/neighborhoods")?;
#[derive(Deserialize)]
struct Resp {
neighborhoods: Vec<Neighborhood>,
}
let r: Resp = self.inner.send_json(builder).await?;
Ok(r.neighborhoods)
}
pub async fn readiness(&self) -> Result<bool, Error> {
let builder = request(&self.inner, Method::GET, "readiness")?;
match self.inner.send(builder).await {
Ok(_) => Ok(true),
Err(e) if e.status() == Some(404) || e.status() == Some(503) => Ok(false),
Err(e) => Err(e),
}
}
pub async fn is_gateway(&self) -> Result<bool, Error> {
let builder = request(&self.inner, Method::GET, "gateway")?;
match self.inner.send(builder).await {
Ok(resp) => {
#[derive(Deserialize)]
struct Resp {
gateway: bool,
}
let r: Resp = serde_json::from_slice(&resp.bytes().await?)?;
Ok(r.gateway)
}
Err(e) if e.status() == Some(404) => Ok(false),
Err(e) => Err(e),
}
}
pub async fn is_connected(&self) -> bool {
self.check_connection().await.is_ok()
}
pub async fn check_connection(&self) -> Result<(), Error> {
let builder = self
.inner
.http
.request(Method::GET, self.inner.base_url.clone());
self.inner.send(builder).await?;
Ok(())
}
}