Feature/validator api client endpoints (#1024)

* Moved mixnode status route to node status api module

* Introduced validator-api endpoint for estimating mixnode's reward

* Stake saturation endpoint

* kebab-cased coconut routes

* Created separate crate for validator API models

* Additional routes in validator API client

* Introduced support for new queries in the wallet

* Typescript type derivation

* Fixed up date in license notice
This commit is contained in:
Jędrzej Stuczyński
2022-01-11 16:37:07 +00:00
committed by GitHub
parent 835d4f46f6
commit e2e06df4e6
27 changed files with 499 additions and 106 deletions
+1 -15
View File
@@ -20,26 +20,12 @@ use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;
use tokio::time;
use validator_api_requests::models::MixnodeStatus;
use validator_client::nymd::hash::SHA256_HASH_SIZE;
use validator_client::nymd::CosmWasmClient;
pub(crate) mod routes;
#[derive(Clone, Copy, Debug, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum MixnodeStatus {
Active, // in both the active set and the rewarded set
Standby, // only in the rewarded set
Inactive, // in neither the rewarded set nor the active set, but is bonded
NotFound, // doesn't even exist in the bonded set
}
impl MixnodeStatus {
pub fn is_active(&self) -> bool {
*self == MixnodeStatus::Active
}
}
pub struct ValidatorCacheRefresher<C> {
nymd_client: Client<C>,
cache: ValidatorCache,
+2 -2
View File
@@ -62,7 +62,7 @@ fn blind_sign(request: InternalSignRequest, key_pair: &KeyPair) -> BlindedSignat
.unwrap()
}
#[post("/blind_sign", data = "<blind_sign_request_body>")]
#[post("/blind-sign", data = "<blind_sign_request_body>")]
// Until we have serialization and deserialization traits we'll be using a crutch
pub async fn post_blind_sign(
blind_sign_request_body: Json<BlindSignRequestBody>,
@@ -79,7 +79,7 @@ pub async fn post_blind_sign(
Json(BlindedSignatureResponse::new(blinded_signature))
}
#[get("/verification_key")]
#[get("/verification-key")]
pub async fn get_verification_key(key_pair: &State<KeyPair>) -> Json<VerificationKeyResponse> {
Json(VerificationKeyResponse::new(key_pair.verification_key()))
}
@@ -1,7 +1,6 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::cache::MixnodeStatus;
use crate::node_status_api::utils::NodeUptimes;
use crate::storage::models::NodeStatus;
use rocket::http::{ContentType, Status};
@@ -272,32 +271,3 @@ impl Display for ValidatorApiStorageError {
}
}
}
#[derive(Serialize)]
pub struct CoreNodeStatus {
pub(crate) identity: String,
pub(crate) count: i32,
}
#[derive(Serialize)]
pub(crate) struct MixnodeStatusResponse {
pub(crate) status: MixnodeStatus,
}
#[derive(Serialize)]
pub(crate) struct RewardEstimationResponse {
pub(crate) estimated_total_node_reward: u128,
pub(crate) estimated_operator_reward: u128,
pub(crate) estimated_delegators_reward: u128,
pub(crate) current_epoch_start: i64,
pub(crate) current_epoch_end: i64,
pub(crate) current_epoch_uptime: Uptime,
pub(crate) as_at: i64,
}
#[derive(Serialize)]
pub(crate) struct StakeSaturationResponse {
pub(crate) saturation: f32,
pub(crate) as_at: i64,
}
+33 -29
View File
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::node_status_api::models::{
CoreNodeStatus, ErrorResponse, GatewayStatusReport, GatewayUptimeHistory, MixnodeStatusReport,
MixnodeStatusResponse, MixnodeUptimeHistory, RewardEstimationResponse, StakeSaturationResponse,
ErrorResponse, GatewayStatusReport, GatewayUptimeHistory, MixnodeStatusReport,
MixnodeUptimeHistory,
};
use crate::storage::ValidatorApiStorage;
use crate::{Epoch, ValidatorCache};
@@ -11,85 +11,89 @@ use rocket::http::Status;
use rocket::serde::json::Json;
use rocket::State;
use time::OffsetDateTime;
use validator_api_requests::models::{
CoreNodeStatusResponse, MixnodeStatusResponse, RewardEstimationResponse,
StakeSaturationResponse,
};
#[get("/mixnode/<pubkey>/report")]
#[get("/mixnode/<identity>/report")]
pub(crate) async fn mixnode_report(
storage: &State<ValidatorApiStorage>,
pubkey: &str,
identity: &str,
) -> Result<Json<MixnodeStatusReport>, ErrorResponse> {
storage
.construct_mixnode_report(pubkey)
.construct_mixnode_report(identity)
.await
.map(Json)
.map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))
}
#[get("/gateway/<pubkey>/report")]
#[get("/gateway/<identity>/report")]
pub(crate) async fn gateway_report(
storage: &State<ValidatorApiStorage>,
pubkey: &str,
identity: &str,
) -> Result<Json<GatewayStatusReport>, ErrorResponse> {
storage
.construct_gateway_report(pubkey)
.construct_gateway_report(identity)
.await
.map(Json)
.map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))
}
#[get("/mixnode/<pubkey>/history")]
#[get("/mixnode/<identity>/history")]
pub(crate) async fn mixnode_uptime_history(
storage: &State<ValidatorApiStorage>,
pubkey: &str,
identity: &str,
) -> Result<Json<MixnodeUptimeHistory>, ErrorResponse> {
storage
.get_mixnode_uptime_history(pubkey)
.get_mixnode_uptime_history(identity)
.await
.map(Json)
.map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))
}
#[get("/gateway/<pubkey>/history")]
#[get("/gateway/<identity>/history")]
pub(crate) async fn gateway_uptime_history(
storage: &State<ValidatorApiStorage>,
pubkey: &str,
identity: &str,
) -> Result<Json<GatewayUptimeHistory>, ErrorResponse> {
storage
.get_gateway_uptime_history(pubkey)
.get_gateway_uptime_history(identity)
.await
.map(Json)
.map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))
}
#[get("/mixnode/<pubkey>/core-status-count?<since>")]
#[get("/mixnode/<identity>/core-status-count?<since>")]
pub(crate) async fn mixnode_core_status_count(
storage: &State<ValidatorApiStorage>,
pubkey: &str,
identity: &str,
since: Option<i64>,
) -> Json<CoreNodeStatus> {
) -> Json<CoreNodeStatusResponse> {
let count = storage
.get_core_mixnode_status_count(pubkey, since)
.get_core_mixnode_status_count(identity, since)
.await
.unwrap_or_default();
Json(CoreNodeStatus {
identity: pubkey.to_string(),
Json(CoreNodeStatusResponse {
identity: identity.to_string(),
count,
})
}
#[get("/gateway/<pubkey>/core-status-count?<since>")]
#[get("/gateway/<identity>/core-status-count?<since>")]
pub(crate) async fn gateway_core_status_count(
storage: &State<ValidatorApiStorage>,
pubkey: &str,
identity: &str,
since: Option<i64>,
) -> Json<CoreNodeStatus> {
) -> Json<CoreNodeStatusResponse> {
let count = storage
.get_core_gateway_status_count(pubkey, since)
.get_core_gateway_status_count(identity, since)
.await
.unwrap_or_default();
Json(CoreNodeStatus {
identity: pubkey.to_string(),
Json(CoreNodeStatusResponse {
identity: identity.to_string(),
count,
})
}
@@ -104,7 +108,7 @@ pub(crate) async fn get_mixnode_status(
})
}
#[get("/mixnode/<identity>/reward_estimation")]
#[get("/mixnode/<identity>/reward-estimation")]
pub(crate) async fn get_mixnode_reward_estimation(
cache: &State<ValidatorCache>,
storage: &State<ValidatorApiStorage>,
@@ -136,7 +140,7 @@ pub(crate) async fn get_mixnode_reward_estimation(
estimated_delegators_reward,
current_epoch_start: current_epoch.start_unix_timestamp(),
current_epoch_end: current_epoch.end_unix_timestamp(),
current_epoch_uptime: uptime,
current_epoch_uptime: uptime.u8(),
as_at,
}))
} else {
@@ -147,7 +151,7 @@ pub(crate) async fn get_mixnode_reward_estimation(
}
}
#[get("/mixnode/<identity>/stake_saturation")]
#[get("/mixnode/<identity>/stake-saturation")]
pub(crate) async fn get_mixnode_stake_saturation(
cache: &State<ValidatorCache>,
identity: String,