1use num_bigint::BigInt;
4use reqwest::Method;
5use serde::{Deserialize, Deserializer};
6
7use crate::client::request;
8use crate::swarm::Error;
9
10use super::DebugApi;
11
12#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct Health {
16 pub status: String,
18 pub version: String,
20 pub api_version: String,
22}
23
24#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct BeeVersions {
28 pub bee_version: String,
30 pub bee_api_version: String,
32 pub supported_api_version: String,
34 pub supported_bee_version_exact: String,
36}
37
38#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct ChainState {
44 pub block: u64,
46 pub chain_tip: u64,
48 #[serde(default, deserialize_with = "deserialize_bigint_string")]
50 pub current_price: BigInt,
51 #[serde(default, deserialize_with = "deserialize_bigint_string")]
53 pub total_amount: BigInt,
54}
55
56fn deserialize_bigint_string<'de, D>(d: D) -> Result<BigInt, D::Error>
57where
58 D: Deserializer<'de>,
59{
60 let s: String = Deserialize::deserialize(d)?;
61 if s.is_empty() {
62 return Ok(BigInt::from(0));
63 }
64 s.parse::<BigInt>().map_err(serde::de::Error::custom)
65}
66
67pub const SUPPORTED_API_VERSION: &str = "8.0.0";
69pub const SUPPORTED_BEE_VERSION_EXACT: &str = "2.7.2-rc1-83612d37";
71
72#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
74#[serde(rename_all = "camelCase")]
75pub struct NodeInfo {
76 pub bee_mode: String,
78 pub chequebook_enabled: bool,
80 pub swap_enabled: bool,
82}
83
84#[derive(Clone, Debug, PartialEq, Default, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct Status {
89 pub overlay: String,
91 pub proximity: i64,
93 pub bee_mode: String,
95 pub reserve_size: i64,
97 pub reserve_size_within_radius: i64,
99 pub pullsync_rate: f64,
101 pub storage_radius: i64,
103 pub connected_peers: i64,
105 pub neighborhood_size: i64,
107 pub batch_commitment: i64,
109 pub is_reachable: bool,
111 pub last_synced_block: i64,
113 pub committed_depth: i64,
115 pub is_warming_up: bool,
117}
118
119#[derive(Clone, Debug, PartialEq, Default, Deserialize)]
122#[serde(rename_all = "camelCase")]
123pub struct PeerStatus {
124 #[serde(flatten)]
126 pub status: Status,
127 #[serde(default)]
129 pub request_failed: bool,
130}
131
132#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
134#[serde(rename_all = "camelCase")]
135pub struct Neighborhood {
136 pub neighborhood: String,
138 pub reserve_size_within_radius: i64,
140 pub proximity: u8,
142}
143
144impl DebugApi {
145 pub async fn health(&self) -> Result<Health, Error> {
147 let builder = request(&self.inner, Method::GET, "health")?;
148 self.inner.send_json(builder).await
149 }
150
151 pub async fn versions(&self) -> Result<BeeVersions, Error> {
153 let h = self.health().await?;
154 Ok(BeeVersions {
155 bee_version: h.version,
156 bee_api_version: h.api_version,
157 supported_api_version: SUPPORTED_API_VERSION.to_string(),
158 supported_bee_version_exact: SUPPORTED_BEE_VERSION_EXACT.to_string(),
159 })
160 }
161
162 pub async fn is_supported_api_version(&self) -> Result<bool, Error> {
165 let h = self.health().await?;
166 Ok(h.api_version == SUPPORTED_API_VERSION)
167 }
168
169 pub async fn is_supported_exact_version(&self) -> Result<bool, Error> {
172 let h = self.health().await?;
173 Ok(h.version == SUPPORTED_BEE_VERSION_EXACT)
174 }
175
176 pub async fn chain_state(&self) -> Result<ChainState, Error> {
178 let builder = request(&self.inner, Method::GET, "chainstate")?;
179 self.inner.send_json(builder).await
180 }
181
182 pub async fn node_info(&self) -> Result<NodeInfo, Error> {
184 let builder = request(&self.inner, Method::GET, "node")?;
185 self.inner.send_json(builder).await
186 }
187
188 pub async fn status(&self) -> Result<Status, Error> {
190 let builder = request(&self.inner, Method::GET, "status")?;
191 self.inner.send_json(builder).await
192 }
193
194 pub async fn status_peers(&self) -> Result<Vec<PeerStatus>, Error> {
198 let builder = request(&self.inner, Method::GET, "status/peers")?;
199 #[derive(Deserialize)]
200 struct Resp {
201 snapshots: Vec<PeerStatus>,
202 }
203 let r: Resp = self.inner.send_json(builder).await?;
204 Ok(r.snapshots)
205 }
206
207 pub async fn status_neighborhoods(&self) -> Result<Vec<Neighborhood>, Error> {
210 let builder = request(&self.inner, Method::GET, "status/neighborhoods")?;
211 #[derive(Deserialize)]
212 struct Resp {
213 neighborhoods: Vec<Neighborhood>,
214 }
215 let r: Resp = self.inner.send_json(builder).await?;
216 Ok(r.neighborhoods)
217 }
218
219 pub async fn readiness(&self) -> Result<bool, Error> {
222 let builder = request(&self.inner, Method::GET, "readiness")?;
223 match self.inner.send(builder).await {
224 Ok(_) => Ok(true),
225 Err(e) if e.status() == Some(404) || e.status() == Some(503) => Ok(false),
226 Err(e) => Err(e),
227 }
228 }
229
230 pub async fn is_gateway(&self) -> Result<bool, Error> {
233 let builder = request(&self.inner, Method::GET, "gateway")?;
234 match self.inner.send(builder).await {
235 Ok(resp) => {
236 #[derive(Deserialize)]
237 struct Resp {
238 gateway: bool,
239 }
240 let r: Resp = serde_json::from_slice(&resp.bytes().await?)?;
241 Ok(r.gateway)
242 }
243 Err(e) if e.status() == Some(404) => Ok(false),
244 Err(e) => Err(e),
245 }
246 }
247
248 pub async fn is_connected(&self) -> bool {
251 self.check_connection().await.is_ok()
252 }
253
254 pub async fn check_connection(&self) -> Result<(), Error> {
257 let builder = self
258 .inner
259 .http
260 .request(Method::GET, self.inner.base_url.clone());
261 self.inner.send(builder).await?;
262 Ok(())
263 }
264}