Feature/nymd client integration (#736)
* Calculating gas fees * Ability to set custom fees * Added extra test * Removed commented code * Moved all msg types to common contract crate * Temporarily disabling get_tx method * Finishing up nymd client API * Comment fix * Remaining fee values * Some cleanup * Removed needless borrow * Fixed imports in contract tests * Moved error types around * New ValidatorClient * Experiment with new type of defaults * Removed dead module * Dealt with unwrap * Migrated mixnode to use new validator client * Migrated gateway to use new validator client * Mixnode and gateway adjustments * More exported defaults * Clients using new validator client * Fixed mixnode upgrade * Moved default values to a new crate * Changed behaviour of validator client features * Migrated basic functions of validator api * Updated config + fixed startup * Fixed wasm client build * Integration with the explorer api * Removed tokio dev dependency * Needless borrow * Fixex wasm client build * Fixed tauri client build * Needless borrows * Fixed client upgrade print * Removed redundant comments * Made note on aggregated verification key into a doc comment * Removed mixnet contract references from verloc * Modified default validators structure * Reformatted validator-api Cargo.toml file * Removed commented code * Made the doc comment example a no-run * Fixed a upgrade print... again * Adjusted the doc example * Removed unused import
This commit is contained in:
committed by
GitHub
parent
eec211e038
commit
a274edffba
@@ -1,7 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ValidatorAPIClientError {
|
||||
pub enum ValidatorAPIError {
|
||||
#[error("There was an issue with the REST request - {source}")]
|
||||
ReqwestClientError {
|
||||
#[from]
|
||||
|
||||
@@ -1,77 +1,167 @@
|
||||
pub mod error;
|
||||
|
||||
use crate::validator_api::error::ValidatorAPIClientError;
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::validator_api::error::ValidatorAPIError;
|
||||
use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse};
|
||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
pub const VALIDATOR_API_PORT: u16 = 8080;
|
||||
pub const VALIDATOR_API_CACHE_VERSION: &str = "/v1";
|
||||
pub(crate) const VALIDATOR_API_MIXNODES: &str = "/mixnodes";
|
||||
pub(crate) const VALIDATOR_API_GATEWAYS: &str = "/gateways";
|
||||
pub const VALIDATOR_API_VERIFICATION_KEY: &str = "/verification_key";
|
||||
pub const VALIDATOR_API_BLIND_SIGN: &str = "/blind_sign";
|
||||
pub mod error;
|
||||
pub(crate) mod routes;
|
||||
|
||||
type PathSegments<'a> = &'a [&'a str];
|
||||
|
||||
pub struct Client {
|
||||
url: Url,
|
||||
reqwest_client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl Default for Client {
|
||||
fn default() -> Self {
|
||||
Client::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(url: Url) -> Self {
|
||||
let reqwest_client = reqwest::Client::new();
|
||||
Self { reqwest_client }
|
||||
Self {
|
||||
url,
|
||||
reqwest_client,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn query_validator_api<T>(
|
||||
&self,
|
||||
query: String,
|
||||
validator_url: &Url,
|
||||
) -> Result<T, ValidatorAPIClientError>
|
||||
pub fn change_url(&mut self, new_url: Url) {
|
||||
self.url = new_url
|
||||
}
|
||||
|
||||
async fn query_validator_api<T>(&self, path: PathSegments<'_>) -> Result<T, ValidatorAPIError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let mut validator_api_url = validator_url.clone();
|
||||
validator_api_url
|
||||
.set_port(Some(VALIDATOR_API_PORT))
|
||||
.unwrap();
|
||||
let query_url = format!("{}{}", validator_api_url.as_str(), query);
|
||||
Ok(self
|
||||
.reqwest_client
|
||||
.get(query_url)
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await?)
|
||||
let url = create_api_url(&self.url, path);
|
||||
Ok(self.reqwest_client.get(url).send().await?.json().await?)
|
||||
}
|
||||
|
||||
pub async fn post_validator_api<D, S>(
|
||||
async fn post_validator_api<B, T>(
|
||||
&self,
|
||||
query: String,
|
||||
json_body: &S,
|
||||
validator_url: &Url,
|
||||
) -> Result<D, ValidatorAPIClientError>
|
||||
path: PathSegments<'_>,
|
||||
json_body: &B,
|
||||
) -> Result<T, ValidatorAPIError>
|
||||
where
|
||||
for<'a> D: Deserialize<'a>,
|
||||
S: Serialize,
|
||||
B: Serialize + ?Sized,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let mut validator_api_url = validator_url.clone();
|
||||
validator_api_url
|
||||
.set_port(Some(VALIDATOR_API_PORT))
|
||||
.unwrap();
|
||||
let query_url = format!("{}{}", validator_api_url.as_str(), query);
|
||||
let url = create_api_url(&self.url, path);
|
||||
Ok(self
|
||||
.reqwest_client
|
||||
.post(query_url)
|
||||
.get(url)
|
||||
.json(json_body)
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::MIXNODES])
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::GATEWAYS])
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn blind_sign(
|
||||
&self,
|
||||
request_body: &BlindSignRequestBody,
|
||||
) -> Result<BlindedSignatureResponse, ValidatorAPIError> {
|
||||
self.post_validator_api(
|
||||
&[routes::API_VERSION, routes::COCONUT_BLIND_SIGN],
|
||||
request_body,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_coconut_verification_key(
|
||||
&self,
|
||||
) -> Result<VerificationKeyResponse, ValidatorAPIError> {
|
||||
self.query_validator_api(&[routes::API_VERSION, routes::COCONUT_VERIFICATION_KEY])
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// utility function that should solve the double slash problem in validator API forever.
|
||||
fn create_api_url(base: &Url, segments: PathSegments<'_>) -> Url {
|
||||
let mut url = base.clone();
|
||||
let mut path_segments = url
|
||||
.path_segments_mut()
|
||||
.expect("provided validator url does not have a base!");
|
||||
for segment in segments {
|
||||
let segment = segment.strip_prefix('/').unwrap_or(segment);
|
||||
let segment = segment.strip_suffix('/').unwrap_or(segment);
|
||||
|
||||
path_segments.push(segment);
|
||||
}
|
||||
// I don't understand why compiler couldn't figure out that it's no longer used
|
||||
// and can be dropped
|
||||
drop(path_segments);
|
||||
|
||||
url
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn creating_api_path() {
|
||||
let base_url: Url = "http://foomp.com".parse().unwrap();
|
||||
|
||||
// works with 1 segment
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["foo"]).as_str()
|
||||
);
|
||||
|
||||
// works with 2 segments
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "bar"]).as_str()
|
||||
);
|
||||
|
||||
// works with leading slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["/foo"]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["/foo", "bar"]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "/bar"]).as_str()
|
||||
);
|
||||
|
||||
// works with trailing slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["foo/"]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo/", "bar"]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["foo", "bar/"]).as_str()
|
||||
);
|
||||
|
||||
// works with both leading and trailing slash
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo",
|
||||
create_api_url(&base_url, &["/foo/"]).as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
"http://foomp.com/foo/bar",
|
||||
create_api_url(&base_url, &["/foo/", "/bar/"]).as_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use network_defaults::VALIDATOR_API_VERSION;
|
||||
|
||||
pub const API_VERSION: &str = VALIDATOR_API_VERSION;
|
||||
pub const MIXNODES: &str = "mixnodes";
|
||||
pub const GATEWAYS: &str = "gateways";
|
||||
|
||||
pub const COCONUT_BLIND_SIGN: &str = "blind_sign";
|
||||
pub const COCONUT_VERIFICATION_KEY: &str = "verification_key";
|
||||
Reference in New Issue
Block a user