diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index c5906c376a..cf97221de4 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -23,4 +23,4 @@ pretty_env_logger = "0.4.0" mixnet-contract = { path = "../common/mixnet-contract" } network-defaults = { path = "../common/network-defaults" } -validator-client = { path = "../common/client-libs/validator-client" } +validator-client = { path = "../common/client-libs/validator-client", features=["nymd-client"] } diff --git a/explorer-api/src/mix_node/http.rs b/explorer-api/src/mix_node/http.rs index 20b5c2434c..56cb5ba848 100644 --- a/explorer-api/src/mix_node/http.rs +++ b/explorer-api/src/mix_node/http.rs @@ -6,11 +6,11 @@ use serde::Serialize; use mixnet_contract::{Addr, Coin, Layer, MixNode}; use crate::mix_node::models::{NodeDescription, NodeStats}; -use crate::mix_nodes::Location; +use crate::mix_nodes::{get_mixnode_delegations, Location}; use crate::state::ExplorerApiStateContext; pub fn mix_node_make_default_routes() -> Vec { - routes_with_openapi![get_description, get_stats, list] + routes_with_openapi![get_delegations, get_description, get_stats, list] } #[derive(Clone, Debug, Serialize, JsonSchema)] @@ -51,6 +51,12 @@ pub(crate) async fn list( ) } +#[openapi(tag = "mix_node")] +#[get("//delegations")] +pub(crate) async fn get_delegations(pubkey: &str) -> Json> { + Json(get_mixnode_delegations(pubkey).await) +} + #[openapi(tag = "mix_node")] #[get("//description")] pub(crate) async fn get_description( diff --git a/explorer-api/src/mix_nodes/mod.rs b/explorer-api/src/mix_nodes/mod.rs index 9ed89fc4d0..2c82ef22d9 100644 --- a/explorer-api/src/mix_nodes/mod.rs +++ b/explorer-api/src/mix_nodes/mod.rs @@ -8,8 +8,11 @@ use rocket::tokio::sync::RwLock; use serde::{Deserialize, Serialize}; use crate::mix_nodes::utils::map_2_letter_to_3_letter_country_code; -use mixnet_contract::MixNodeBond; -use network_defaults::default_api_endpoints; +use mixnet_contract::{Delegation, MixNodeBond}; +use network_defaults::{ + default_api_endpoints, default_nymd_endpoints, DEFAULT_MIXNET_CONTRACT_ADDRESS, +}; +use validator_client::nymd::QueryNymdClient; pub(crate) type LocationCache = HashMap; @@ -163,6 +166,32 @@ pub(crate) async fn retrieve_mixnodes() -> Vec { bonds } +pub(crate) async fn get_mixnode_delegations(pubkey: &str) -> Vec { + let client = new_nymd_client(); + let delegates = match client + .get_all_nymd_mixnode_delegations(pubkey.to_string()) + .await + { + Ok(result) => result, + Err(e) => { + error!("Could not get delegations for mix node {}: {:?}", pubkey, e); + vec![] + } + }; + delegates +} + +fn new_nymd_client() -> validator_client::Client { + let mixnet_contract = DEFAULT_MIXNET_CONTRACT_ADDRESS.to_string(); + let nymd_url = default_nymd_endpoints()[0].clone(); + let api_url = default_api_endpoints()[0].clone(); + + let client_config = + validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract.parse().unwrap())); + + validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!") +} + // TODO: inject constants fn new_validator_client() -> validator_client::ApiClient { validator_client::ApiClient::new(default_api_endpoints()[0].clone())