use crate::{
error::EyeError,
types::{EyeCell, NodeMatrixRow},
YedadEyeProvider,
};
use async_trait::async_trait;
use reqwest::Client;
use serde::Deserialize;
use std::collections::HashMap;
pub struct NetworkEyeProvider {
base_url: String,
client: Client,
}
impl NetworkEyeProvider {
pub fn new(node_url: &str) -> Self {
Self {
base_url: node_url.trim_end_matches('/').to_string(),
client: Client::builder()
.timeout(std::time::Duration::from_secs(3))
.build()
.unwrap_or_default(),
}
}
}
#[allow(dead_code)]
#[derive(Deserialize)]
struct SlotJson {
user_address: String,
pulse_id: u64,
ladder_id: u32,
step_number: u32,
balance: u64,
last_hash: String,
}
#[allow(dead_code)]
#[derive(Deserialize)]
struct ActivityResponse {
pulse_id: u32,
state_crc: u32,
prev_hash: String,
}
#[async_trait]
impl YedadEyeProvider for NetworkEyeProvider {
async fn fetch_all_active_addresses(&self) -> Result<Vec<String>, EyeError> {
let url = format!("{}/slots", self.base_url);
let res = self
.client
.get(&url)
.send()
.await
.map_err(|e| EyeError::NetworkError(e.to_string()))?;
let slots: Vec<SlotJson> = res
.json()
.await
.map_err(|e| EyeError::ParsingError(e.to_string()))?;
Ok(slots.into_iter().map(|s| s.user_address).collect())
}
async fn fetch_node_row(&self, address: &str) -> Result<NodeMatrixRow, EyeError> {
let slot_url = format!("{}/slot/{}", self.base_url, address);
let activity_url = format!("{}/activity/{}", self.base_url, address);
let slot_res = self
.client
.get(&slot_url)
.send()
.await
.map_err(|e| EyeError::NetworkError(e.to_string()))?;
let slot: SlotJson = slot_res
.json()
.await
.map_err(|e| EyeError::ParsingError(e.to_string()))?;
let act_res = self
.client
.get(&activity_url)
.send()
.await
.map_err(|e| EyeError::NetworkError(e.to_string()))?;
let activities: Vec<ActivityResponse> = act_res
.json()
.await
.map_err(|e| EyeError::ParsingError(e.to_string()))?;
let mut history_map = HashMap::new();
for act in activities {
history_map.insert(
act.pulse_id,
EyeCell {
pulse_id: act.pulse_id,
state_crc: act.state_crc,
},
);
}
Ok(NodeMatrixRow {
address: slot.user_address,
current_rank: "Unknown (Sync via Network)".to_string(),
balance: slot.balance,
step_number: slot.step_number,
history: history_map,
})
}
}