Skip to content

Commit

Permalink
Create nym-harbour-master-client crate (#310)
Browse files Browse the repository at this point in the history
* Create nym-harbour-master-client

* Add harbour master client in gateway directory

* Formatting

* Remove testing code
  • Loading branch information
octol authored Apr 19, 2024
1 parent 38cd55f commit 182bcca
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 2 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"crates/nym-connection-monitor",
"crates/nym-gateway-directory",
"crates/nym-gateway-probe",
"crates/nym-harbour-master-client",
"crates/nym-vpn-proto",
"nym-vpn-cli",
"nym-vpn-lib",
Expand All @@ -20,6 +21,7 @@ exclude = ["nym-vpn-desktop/src-tauri"]
# nym-credential-storage = { path = "../nym/common/credential-storage" }
# nym-crypto = { path = "../nym/common/crypto" }
# nym-explorer-client = { path = "../nym/explorer-api/explorer-client" }
# nym-http-api-client = { path = "../nym/common/http-api-client" }
# nym-id = { path = "../nym/common/nym-id" }
# nym-ip-packet-requests = { path = "../nym/common/ip-packet-requests" }
# nym-node-requests = { path = "../nym/nym-node/nym-node-requests" }
Expand Down Expand Up @@ -83,11 +85,12 @@ nym-credential-storage = { git = "https://github.com/nymtech/nym", rev = "b8b66f
nym-credentials = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-crypto = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-explorer-client = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-http-api-client = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-id = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-ip-packet-requests = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-node-requests = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-sdk = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-task = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-topology = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-validator-client = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-wireguard-types = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
nym-wireguard-types = { git = "https://github.com/nymtech/nym", rev = "b8b66fa" }
3 changes: 2 additions & 1 deletion crates/nym-gateway-directory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ edition.workspace = true
license.workspace = true

[dependencies]
chrono = "0.4.37"
hickory-resolver.workspace = true
itertools.workspace = true
log.workspace = true
nym-client-core.workspace = true
nym-explorer-client.workspace = true
nym-harbour-master-client = { path = "../nym-harbour-master-client" }
nym-sdk.workspace = true
nym-topology.workspace = true
nym-validator-client.workspace = true
Expand All @@ -18,4 +20,3 @@ serde.workspace = true
thiserror.workspace = true
tracing.workspace = true
url.workspace = true
chrono = "0.4.37"
6 changes: 6 additions & 0 deletions crates/nym-gateway-directory/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ pub enum Error {
#[error(transparent)]
ExplorerApiError(#[from] nym_explorer_client::ExplorerApiError),

#[error(transparent)]
HarbourMasterError(#[from] nym_harbour_master_client::HarbourMasterError),

#[error(transparent)]
HarbourMasterApiError(#[from] nym_harbour_master_client::HarbourMasterApiError),

#[error("failed to fetch location data from explorer-api: {error}")]
FailedFetchLocationData {
error: nym_explorer_client::ExplorerApiError,
Expand Down
35 changes: 35 additions & 0 deletions crates/nym-gateway-directory/src/gateway_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use crate::{
};
use itertools::Itertools;
use nym_explorer_client::{ExplorerClient, Location, PrettyDetailedGatewayBond};
use nym_harbour_master_client::{
Gateway as HmGateway, HarbourMasterApiClientExt, PagedResult as HmPagedResult,
};
use nym_validator_client::{models::DescribedGateway, NymApiClient};
use std::net::IpAddr;
use tracing::info;
Expand All @@ -17,6 +20,7 @@ use url::Url;
pub struct Config {
pub api_url: Url,
pub explorer_url: Option<Url>,
pub harbour_master_url: Option<Url>,
}

impl Default for Config {
Expand All @@ -39,6 +43,7 @@ impl Default for Config {
Config {
api_url: default_api_url,
explorer_url: default_explorer_url,
harbour_master_url: None,
}
}
}
Expand All @@ -61,11 +66,21 @@ impl Config {
self.explorer_url = Some(explorer_url);
self
}

pub fn harbour_master_url(&self) -> Option<&Url> {
self.harbour_master_url.as_ref()
}

pub fn with_custom_harbour_master_url(mut self, harbour_master_url: Url) -> Self {
self.harbour_master_url = Some(harbour_master_url);
self
}
}

pub struct GatewayClient {
api_client: NymApiClient,
explorer_client: Option<ExplorerClient>,
harbour_master_client: Option<nym_harbour_master_client::Client>,
}

impl GatewayClient {
Expand All @@ -76,10 +91,16 @@ impl GatewayClient {
} else {
None
};
let harbour_master_client = if let Some(url) = config.harbour_master_url {
Some(nym_harbour_master_client::Client::new_url(url, None)?)
} else {
None
};

Ok(GatewayClient {
api_client,
explorer_client,
harbour_master_client,
})
}

Expand All @@ -105,6 +126,20 @@ impl GatewayClient {
}
}

#[allow(unused)]
async fn lookup_gateways_in_harbour_master(&self) -> Option<Result<HmPagedResult<HmGateway>>> {
if let Some(harbour_master_client) = &self.harbour_master_client {
Some(
harbour_master_client
.get_gateways()
.await
.map_err(Error::HarbourMasterApiError),
)
} else {
None
}
}

pub async fn lookup_described_gateways_with_location(
&self,
) -> Result<Vec<DescribedGatewayWithLocation>> {
Expand Down
16 changes: 16 additions & 0 deletions crates/nym-harbour-master-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "nym-harbour-master-client"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true

[dependencies]
nym-http-api-client.workspace = true
reqwest = { workspace = true, features = ["rustls-tls"] }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
thiserror.workspace = true
24 changes: 24 additions & 0 deletions crates/nym-harbour-master-client/src/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use nym_http_api_client::{ApiClient, HttpClientError, NO_PARAMS};

pub use nym_http_api_client::Client;

use crate::{
responses::{Gateway, PagedResult},
routes,
};

// This is largely lifted from mix-fetch. The future of harbourmaster is uncertain, but ideally
// these two should be merged so they both can depend on the same crate.

pub type HarbourMasterApiError = HttpClientError;

#[allow(async_fn_in_trait)]
pub trait HarbourMasterApiClientExt: ApiClient {
// TODO: paging
async fn get_gateways(&self) -> Result<PagedResult<Gateway>, HarbourMasterApiError> {
self.get_json(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS)
.await
}
}

impl HarbourMasterApiClientExt for Client {}
9 changes: 9 additions & 0 deletions crates/nym-harbour-master-client/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate::client::HarbourMasterApiError;

#[derive(Debug, thiserror::Error)]
pub enum HarbourMasterError {
#[error("api error: {0}")]
HarbourMasterApiError(#[from] HarbourMasterApiError),
}

pub type Result<T> = std::result::Result<T, HarbourMasterError>;
12 changes: 12 additions & 0 deletions crates/nym-harbour-master-client/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::{
error::Result,
responses::{Gateway, PagedResult},
Client, HarbourMasterApiClientExt,
};

const HARBOUR_MASTER: &str = "https://harbourmaster.nymtech.net";

pub async fn get_gateways() -> Result<PagedResult<Gateway>> {
let client = Client::new_url(HARBOUR_MASTER, None)?;
Ok(client.get_gateways().await?)
}
10 changes: 10 additions & 0 deletions crates/nym-harbour-master-client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mod client;
mod error;
mod helpers;
mod responses;
mod routes;

pub use client::{Client, HarbourMasterApiClientExt, HarbourMasterApiError};
pub use error::HarbourMasterError;
pub use helpers::get_gateways;
pub use responses::{Gateway, PagedResult};
24 changes: 24 additions & 0 deletions crates/nym-harbour-master-client/src/responses.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use serde::{Deserialize, Serialize};

// TODO: these should have their own crate shared with the harbourmaster service

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PagedResult<T> {
pub page: u32,
pub size: u32,
pub total: i32,
pub items: Vec<T>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Gateway {
pub gateway_identity_key: String,
pub self_described: Option<serde_json::Value>,
pub explorer_pretty_bond: Option<serde_json::Value>,
pub last_probe_result: Option<serde_json::Value>,
pub last_probe_log: Option<String>,
pub last_testrun_utc: Option<String>,
pub last_updated_utc: String,
pub routing_score: f32,
pub config_score: u32,
}
2 changes: 2 additions & 0 deletions crates/nym-harbour-master-client/src/routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub const API_VERSION: &str = "v2";
pub const GATEWAYS: &str = "gateways";
2 changes: 2 additions & 0 deletions nym-vpn-lib/src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ async fn get_gateway_countries(
let config = nym_gateway_directory::Config {
api_url,
explorer_url: Some(explorer_url),
harbour_master_url: None,
};
let gateway_client = GatewayClient::new(config)?;

Expand All @@ -225,6 +226,7 @@ async fn get_low_latency_entry_country(
let config = nym_gateway_directory::Config {
api_url,
explorer_url: Some(explorer_url),
harbour_master_url: None,
};
let gateway_client = GatewayClient::new(config)?;
let described = gateway_client.lookup_low_latency_entry_gateway().await?;
Expand Down

0 comments on commit 182bcca

Please sign in to comment.