diff --git a/nym-vpn-core/Cargo.lock b/nym-vpn-core/Cargo.lock index 1d0b434116..4dbae67958 100644 --- a/nym-vpn-core/Cargo.lock +++ b/nym-vpn-core/Cargo.lock @@ -3949,7 +3949,6 @@ version = "1.2.0-dev" dependencies = [ "chrono", "nym-http-api-client", - "reqwest 0.11.27", "serde", "serde_json", "thiserror 2.0.11", @@ -4708,7 +4707,6 @@ dependencies = [ "nym-vpn-network-config", "nym-vpn-store", "nym-wg-gateway-client", - "reqwest 0.11.27", "serde", "serde_json", "si-scale", @@ -4742,7 +4740,6 @@ dependencies = [ "nym-ecash-time", "nym-http-api-client", "nym-validator-client", - "reqwest 0.11.27", "serde", "serde_json", "sha2 0.10.8", @@ -4751,6 +4748,7 @@ dependencies = [ "thiserror 2.0.11", "tokio", "tracing", + "url", "zeroize", ] @@ -4855,7 +4853,7 @@ dependencies = [ "itertools 0.13.0", "nym-config", "nym-sdk", - "reqwest 0.11.27", + "nym-vpn-api-client", "serde", "serde_json", "tempfile", diff --git a/nym-vpn-core/crates/nym-harbour-master-client/Cargo.toml b/nym-vpn-core/crates/nym-harbour-master-client/Cargo.toml index 197d877a31..3783a3d761 100644 --- a/nym-vpn-core/crates/nym-harbour-master-client/Cargo.toml +++ b/nym-vpn-core/crates/nym-harbour-master-client/Cargo.toml @@ -11,7 +11,6 @@ license.workspace = true [dependencies] chrono.workspace = true nym-http-api-client.workspace = true -reqwest = { workspace = true, features = ["rustls-tls"] } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true thiserror.workspace = true diff --git a/nym-vpn-core/crates/nym-vpn-account-controller/Cargo.toml b/nym-vpn-core/crates/nym-vpn-account-controller/Cargo.toml index d58690ed5b..4fa8049b03 100644 --- a/nym-vpn-core/crates/nym-vpn-account-controller/Cargo.toml +++ b/nym-vpn-core/crates/nym-vpn-account-controller/Cargo.toml @@ -25,7 +25,6 @@ nym-vpn-api-client = { path = "../nym-vpn-api-client" } nym-vpn-network-config = { path = "../nym-vpn-network-config" } nym-vpn-store = { path = "../nym-vpn-store" } nym-wg-gateway-client = { path = "../nym-wg-gateway-client" } -reqwest.workspace = true serde.workspace = true serde_json.workspace = true si-scale.workspace = true diff --git a/nym-vpn-core/crates/nym-vpn-api-client/Cargo.toml b/nym-vpn-core/crates/nym-vpn-api-client/Cargo.toml index 6de446e241..3765666622 100644 --- a/nym-vpn-core/crates/nym-vpn-api-client/Cargo.toml +++ b/nym-vpn-core/crates/nym-vpn-api-client/Cargo.toml @@ -24,7 +24,6 @@ nym-crypto = { workspace = true, features = ["asymmetric", "stream_cipher"] } nym-ecash-time.workspace = true nym-http-api-client.workspace = true nym-validator-client.workspace = true -reqwest = { workspace = true, features = ["rustls-tls", "json"] } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true sha2.workspace = true @@ -32,6 +31,7 @@ strum.workspace = true strum_macros.workspace = true thiserror.workspace = true tracing.workspace = true +url.workspace = true zeroize.workspace = true [dev-dependencies] diff --git a/nym-vpn-core/crates/nym-vpn-api-client/src/client.rs b/nym-vpn-core/crates/nym-vpn-api-client/src/client.rs index 750abb4ea7..a34b094241 100644 --- a/nym-vpn-core/crates/nym-vpn-api-client/src/client.rs +++ b/nym-vpn-core/crates/nym-vpn-api-client/src/client.rs @@ -6,11 +6,14 @@ use std::{fmt, time::Duration}; use backon::Retryable; use nym_credential_proxy_requests::api::v1::ticketbook::models::PartialVerificationKeysResponse; use nym_http_api_client::{HttpClientError, Params, PathSegments, UserAgent, NO_PARAMS}; -use reqwest::Url; use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use url::Url; use crate::request::{UpdateDeviceRequestBody, UpdateDeviceRequestStatus}; -use crate::response::{NymVpnHealthResponse, NymVpnUsagesResponse}; +use crate::response::{ + DiscoveryResponse, NymNetworkDetailsResponse, NymVpnHealthResponse, NymVpnUsagesResponse, + NymWellknownDiscoveryItem, RegisteredNetworksResponse, +}; use crate::types::DeviceStatus; use crate::{ error::{Result, VpnApiClientError}, @@ -867,6 +870,81 @@ impl VpnApiClient { } } +// Bootstrapping Environments and Network Discovery +impl VpnApiClient { + /// Hard coded well known URL for bootstrapping environment and discovery config + /// allowing more refined URL usage. + // hard coded for now. + const WELLKNOWN_URL: &str = "https://nymvpn.com/api"; + + /// Returns a VpnApiClient Based on locally set well known url and empty user agent. + /// + /// THIS SHOULD ONLY BE USED FOR BOOTSTRAPPING. + pub fn well_known() -> Result { + let user_agent = UserAgent { + application: String::new(), + version: String::new(), + platform: String::new(), + git_commit: String::new(), + }; + Self::new(Self::WELLKNOWN_URL.parse().unwrap(), user_agent) + } + + pub async fn get_network_envs(&self) -> Result { + self.inner + .get_json( + &[ + routes::PUBLIC, + routes::V1, + routes::WELLKNOWN, + routes::ENVS_FILE, + ], + NO_PARAMS, + ) + .await + .map_err(VpnApiClientError::FailedToGetNetworkEnvs) + } + + pub async fn get_discovery_init(&self, network_name: &str) -> Result { + self.inner + .get_json( + &[ + routes::PUBLIC, + routes::V1, + routes::WELLKNOWN, + network_name, + routes::DISCOVERY_FILE, + ], + NO_PARAMS, + ) + .await + .map_err(VpnApiClientError::FailedToGetDiscoveryInfo) + } + + pub async fn get_nym_network_details(&self) -> Result { + self.inner + .get_json(&[routes::V1, routes::NETWORK, routes::DETAILS], NO_PARAMS) + .await + .map_err(VpnApiClientError::FailedToGetNetworkDetails) + } + + pub async fn get_nym_vpn_network_details(&self) -> Result { + tracing::debug!("Fetching nym vpn network details"); + self.inner + .get_json( + &[ + routes::PUBLIC, + routes::V1, + routes::WELLKNOWN, + routes::CURRENT_ENV, + ], + NO_PARAMS, + ) + .await + .map_err(VpnApiClientError::FailedToGetVPNNetworkDetails) + } +} + #[cfg(test)] mod tests { use nym_crypto::asymmetric::ed25519; diff --git a/nym-vpn-core/crates/nym-vpn-api-client/src/error.rs b/nym-vpn-core/crates/nym-vpn-api-client/src/error.rs index 46a4c0be6b..5d20c4ede5 100644 --- a/nym-vpn-core/crates/nym-vpn-api-client/src/error.rs +++ b/nym-vpn-core/crates/nym-vpn-api-client/src/error.rs @@ -105,6 +105,18 @@ pub enum VpnApiClientError { #[error("failed to get usage")] FailedToGetUsage(#[source] HttpClientError), + + #[error("failed to get registered network environments")] + FailedToGetNetworkEnvs(#[source] HttpClientError), + + #[error("failed to get discovery info")] + FailedToGetDiscoveryInfo(#[source] HttpClientError), + + #[error("failed to get network Details")] + FailedToGetNetworkDetails(#[source] HttpClientError), + + #[error("failed to get vpn network Details")] + FailedToGetVPNNetworkDetails(#[source] HttpClientError), } pub type Result = std::result::Result; diff --git a/nym-vpn-core/crates/nym-vpn-api-client/src/response.rs b/nym-vpn-core/crates/nym-vpn-api-client/src/response.rs index d7776f7e28..7b53768fd2 100644 --- a/nym-vpn-core/crates/nym-vpn-api-client/src/response.rs +++ b/nym-vpn-core/crates/nym-vpn-api-client/src/response.rs @@ -6,6 +6,7 @@ use itertools::Itertools; use nym_contracts_common::Percent; use nym_credential_proxy_requests::api::v1::ticketbook::models::TicketbookWalletSharesResponse; use serde::{Deserialize, Serialize}; +use std::collections::HashSet; use std::fmt; use std::net::IpAddr; @@ -552,3 +553,53 @@ fn extract_error_response_inner( _ => None, } } + +// The response type we fetch from the discovery endpoint +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub struct DiscoveryResponse { + pub network_name: String, + pub nym_api_url: String, + pub nym_vpn_api_url: String, + pub account_management: Option, + pub feature_flags: Option, + pub system_messages: Option>, +} + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +pub struct AccountManagementResponse { + pub url: String, + pub paths: AccountManagementPathsResponse, +} + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +pub struct AccountManagementPathsResponse { + pub sign_up: String, + pub sign_in: String, + pub account: String, +} + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SystemMessageResponse { + pub name: String, + pub display_from: String, + pub display_until: String, + pub message: String, + pub properties: serde_json::Value, +} + +// The response type we fetch from the network details endpoint. This will be added to and exported +// from nym-api-requests. +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub struct NymNetworkDetailsResponse { + pub network: nym_config::defaults::NymNetworkDetails, +} + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub struct NymWellknownDiscoveryItem { + pub network_name: String, + pub nym_api_url: String, + pub nym_vpn_api_url: String, +} + +pub type RegisteredNetworksResponse = HashSet; diff --git a/nym-vpn-core/crates/nym-vpn-api-client/src/routes.rs b/nym-vpn-core/crates/nym-vpn-api-client/src/routes.rs index 500922140c..84024d7c8a 100644 --- a/nym-vpn-core/crates/nym-vpn-api-client/src/routes.rs +++ b/nym-vpn-core/crates/nym-vpn-api-client/src/routes.rs @@ -7,6 +7,8 @@ pub(crate) const ACCOUNT: &str = "account"; pub(crate) const HEALTH: &str = "health"; pub(crate) const SUMMARY: &str = "summary"; pub(crate) const DEVICE: &str = "device"; +pub(crate) const NETWORK: &str = "network"; +pub(crate) const DETAILS: &str = "details"; pub(crate) const ACTIVE: &str = "active"; pub(crate) const ZKNYM: &str = "zknym"; pub(crate) const AVAILABLE: &str = "available"; @@ -25,3 +27,8 @@ pub(crate) const PARTIAL_VERIFICATION_KEYS: &str = "partial-verification-keys"; pub(crate) const SHOW_VPN_ONLY: &str = "show_vpn_only"; pub(crate) const VPN_MIN_PERFORMANCE: &str = "vpn_min_performance"; pub(crate) const MIXNET_MIN_PERFORMANCE: &str = "mixnet_min_performance"; + +pub(crate) const WELLKNOWN: &str = ".wellknown"; +pub(crate) const ENVS_FILE: &str = "envs.json"; +pub(crate) const DISCOVERY_FILE: &str = "discovery.json"; +pub(crate) const CURRENT_ENV: &str = "current-env.json"; diff --git a/nym-vpn-core/crates/nym-vpn-network-config/Cargo.toml b/nym-vpn-core/crates/nym-vpn-network-config/Cargo.toml index 95baa6b2aa..bf4e678f49 100644 --- a/nym-vpn-core/crates/nym-vpn-network-config/Cargo.toml +++ b/nym-vpn-core/crates/nym-vpn-network-config/Cargo.toml @@ -14,11 +14,6 @@ futures-util.workspace = true itertools.workspace = true nym-config.workspace = true nym-sdk.workspace = true -reqwest = { workspace = true, default-features = false, features = [ - "blocking", - "rustls-tls", - "json", -] } serde.workspace = true serde_json.workspace = true tempfile.workspace = true @@ -28,5 +23,7 @@ tokio-util.workspace = true tracing.workspace = true url = { workspace = true, features = ["serde"] } +nym-vpn-api-client = { path = "../nym-vpn-api-client" } + [build-dependencies] serde_json.workspace = true diff --git a/nym-vpn-core/crates/nym-vpn-network-config/src/account_management.rs b/nym-vpn-core/crates/nym-vpn-network-config/src/account_management.rs index 917265b987..79d69c5c6b 100644 --- a/nym-vpn-core/crates/nym-vpn-network-config/src/account_management.rs +++ b/nym-vpn-core/crates/nym-vpn-network-config/src/account_management.rs @@ -5,7 +5,7 @@ use std::fmt; use url::Url; -use crate::response::{AccountManagementPathsResponse, AccountManagementResponse}; +use nym_vpn_api_client::response::{AccountManagementPathsResponse, AccountManagementResponse}; #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct AccountManagement { diff --git a/nym-vpn-core/crates/nym-vpn-network-config/src/discovery.rs b/nym-vpn-core/crates/nym-vpn-network-config/src/discovery.rs index d6e5010d47..2f3da32a19 100644 --- a/nym-vpn-core/crates/nym-vpn-network-config/src/discovery.rs +++ b/nym-vpn-core/crates/nym-vpn-network-config/src/discovery.rs @@ -4,30 +4,21 @@ use std::path::{Path, PathBuf}; use anyhow::Context; +use nym_sdk::UserAgent; use url::Url; -use crate::{ +use nym_vpn_api_client::{ response::{DiscoveryResponse, NymNetworkDetailsResponse, NymWellknownDiscoveryItem}, - AccountManagement, FeatureFlags, SystemMessages, + VpnApiClient, }; +use crate::{AccountManagement, FeatureFlags, SystemMessages}; + use super::{nym_network::NymNetwork, MAX_FILE_AGE, NETWORKS_SUBDIR}; // TODO: integrate with nym-vpn-api-client const DISCOVERY_FILE: &str = "discovery.json"; -const DISCOVERY_WELLKNOWN: &str = "https://nymvpn.com/api/public/v1/.wellknown"; - -const NYM_NETWORK_DETAILS_PATH: &str = "/v1/network/details"; -const NYM_VP_NETWORK_CURRENT_ENV_PATH: &str = "/public/v1/.wellknown/current-env.json"; - -fn nym_network_details_endpoint(nym_api_url: &Url) -> String { - format!("{}/{}", nym_api_url, NYM_NETWORK_DETAILS_PATH) -} - -fn nym_vpn_network_details_endpoint(nym_vpn_api_url: &Url) -> String { - format!("{}/{}", nym_vpn_api_url, NYM_VP_NETWORK_CURRENT_ENV_PATH) -} #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] pub struct Discovery { @@ -60,36 +51,19 @@ impl Discovery { } } - fn endpoint(network_name: &str) -> anyhow::Result { - format!( - "{}/{}/{}", - DISCOVERY_WELLKNOWN, network_name, DISCOVERY_FILE - ) - .parse() - .map_err(Into::into) - } - pub fn fetch(network_name: &str) -> anyhow::Result { - let discovery: DiscoveryResponse = { - let url = Self::endpoint(network_name)?; - - tracing::debug!("Fetching nym network discovery from: {}", url); - let response = reqwest::blocking::get(url.clone()) - .inspect_err(|err| tracing::warn!("{}", err)) - .with_context(|| format!("Failed to fetch discovery from {}", url))? - .error_for_status() - .inspect_err(|err| tracing::warn!("{}", err)) - .with_context(|| "Discovery endpoint returned error response".to_owned())?; - - let text_response = response - .text() - .inspect_err(|err| tracing::warn!("{}", err)) - .with_context(|| "Failed to read response text")?; - tracing::debug!("Discovery response: {:#?}", text_response); - - serde_json::from_str(&text_response) - .with_context(|| "Failed to parse discovery response") - }?; + let client = VpnApiClient::well_known()?; + + tracing::debug!("Fetching nym network discovery"); + let rt = tokio::runtime::Runtime::new()?; + + // Spawn the root task + let discovery: DiscoveryResponse = rt + .block_on(client.get_discovery_init(network_name)) + .with_context(|| "Failed to read response text")?; + + tracing::debug!("Discovery response: {:#?}", discovery); + if discovery.network_name != network_name { anyhow::bail!("Network name mismatch between requested and fetched discovery") } @@ -161,13 +135,17 @@ impl Discovery { } pub fn fetch_nym_network_details(&self) -> anyhow::Result { - // TODO: integrate with validator-client and/or nym-vpn-api-client - let url = nym_network_details_endpoint(&self.nym_api_url); - tracing::debug!("Fetching nym network details from: {}", url); - let network_details: NymNetworkDetailsResponse = reqwest::blocking::get(url.clone()) - .with_context(|| format!("Failed to fetch network details from {}", url))? - .json() - .with_context(|| "Failed to parse network details")?; + tracing::debug!("Fetching nym network details"); + let rt = tokio::runtime::Runtime::new()?; + + // Spawn the root task + let network_details = rt + .block_on( + VpnApiClient::new(self.nym_api_url.clone(), empty_user_agent())? + .get_nym_network_details(), + ) + .with_context(|| "Discovery endpoint returned error response".to_owned())?; + if network_details.network.network_name != self.network_name { anyhow::bail!("Network name mismatch between requested and fetched network details") } @@ -209,32 +187,33 @@ impl TryFrom for Discovery { } } +fn empty_user_agent() -> UserAgent { + UserAgent { + application: String::new(), + version: String::new(), + platform: String::new(), + git_commit: String::new(), + } +} + pub(crate) async fn fetch_nym_network_details( nym_api_url: &Url, ) -> anyhow::Result { - // TODO: integrate with validator-client and/or nym-vpn-api-client - let url = nym_network_details_endpoint(nym_api_url); - tracing::debug!("Fetching nym network details from: {}", url); - reqwest::get(&url) - .await - .with_context(|| format!("Failed to fetch network details from {}", url))? - .json() + tracing::debug!("Fetching nym network details"); + VpnApiClient::new(nym_api_url.clone(), empty_user_agent())? + .get_nym_network_details() .await - .with_context(|| "Failed to parse network details") + .with_context(|| "Discovery endpoint returned error response".to_owned()) } pub(crate) async fn fetch_nym_vpn_network_details( nym_vpn_api_url: &Url, ) -> anyhow::Result { - // TODO: integrate with nym-vpn-api-client - let url = nym_vpn_network_details_endpoint(nym_vpn_api_url); - tracing::debug!("Fetching nym vpn network details from: {}", url); - reqwest::get(&url) + tracing::debug!("Fetching nym vpn network details"); + VpnApiClient::new(nym_vpn_api_url.clone(), empty_user_agent())? + .get_nym_vpn_network_details() .await - .with_context(|| format!("Failed to fetch vpn network details from {url}"))? - .json() - .await - .with_context(|| "Failed to parse vpn network details") + .with_context(|| "Discovery endpoint returned error response".to_owned()) } #[cfg(test)] @@ -250,18 +229,6 @@ mod tests { use super::*; - #[test] - fn test_discovery_endpoint() { - let network_name = "mainnet"; - let url = Discovery::endpoint(network_name).unwrap(); - assert_eq!( - url, - "https://nymvpn.com/api/public/v1/.wellknown/mainnet/discovery.json" - .parse() - .unwrap() - ); - } - #[test] fn test_discovery_fetch() { let network_name = "mainnet"; diff --git a/nym-vpn-core/crates/nym-vpn-network-config/src/envs.rs b/nym-vpn-core/crates/nym-vpn-network-config/src/envs.rs index 54e90e0108..f40ea71dc0 100644 --- a/nym-vpn-core/crates/nym-vpn-network-config/src/envs.rs +++ b/nym-vpn-core/crates/nym-vpn-network-config/src/envs.rs @@ -9,13 +9,13 @@ use std::{ use anyhow::Context; use itertools::Itertools; +use nym_vpn_api_client::VpnApiClient; use super::{MAX_FILE_AGE, NETWORKS_SUBDIR}; // TODO: integrate with nym-vpn-api-client const ENVS_FILE: &str = "envs.json"; -const ENVS_WELLKNOWN: &str = "https://nymvpn.com/api/public/v1/.wellknown/envs.json"; #[derive(Debug, Clone, PartialEq, Eq)] pub struct RegisteredNetworks { @@ -63,28 +63,18 @@ impl RegisteredNetworks { } } - fn endpoint() -> anyhow::Result { - ENVS_WELLKNOWN.parse().map_err(Into::into) - } - fn fetch() -> anyhow::Result { - let url = Self::endpoint()?; - tracing::debug!("Fetching registered networks from: {}", url); - - let response = reqwest::blocking::get(url.clone()) - .inspect_err(|err| tracing::warn!("{}", err)) - .with_context(|| format!("Failed to fetch envs from {}", url))? - .error_for_status() - .inspect_err(|err| tracing::warn!("{}", err)) - .with_context(|| "Envs endpoint returned error response".to_owned())?; - - let text_response = response - .text() - .inspect_err(|err| tracing::warn!("{}", err)) - .with_context(|| "Failed to read response text")?; - tracing::debug!("Envs response: {:#?}", text_response); - - serde_json::from_str(&text_response).with_context(|| "Failed to parse envs response") + tracing::debug!("Fetching registered networks"); + // Create the runtime + let rt = tokio::runtime::Runtime::new()?; + + // Spawn the root task + let inner = rt + .block_on(VpnApiClient::well_known()?.get_network_envs()) + .with_context(|| "Failed to fetch envs")?; + tracing::debug!("Envs response: {:#?}", inner); + + Ok(Self { inner }) } fn read_from_file(config_dir: &Path) -> anyhow::Result { @@ -156,12 +146,6 @@ impl RegisteredNetworks { mod tests { use super::*; - #[test] - fn test_registered_networks_endpoint() { - let endpoint = RegisteredNetworks::endpoint().unwrap(); - assert_eq!(endpoint, ENVS_WELLKNOWN); - } - #[test] fn test_registered_networks_serialization() { let registered_networks = RegisteredNetworks { diff --git a/nym-vpn-core/crates/nym-vpn-network-config/src/lib.rs b/nym-vpn-core/crates/nym-vpn-network-config/src/lib.rs index 3ae8453df7..a80c70698f 100644 --- a/nym-vpn-core/crates/nym-vpn-network-config/src/lib.rs +++ b/nym-vpn-core/crates/nym-vpn-network-config/src/lib.rs @@ -5,8 +5,6 @@ pub mod feature_flags; pub mod system_messages; -pub(crate) mod response; - mod account_management; mod discovery; mod envs; diff --git a/nym-vpn-core/crates/nym-vpn-network-config/src/response.rs b/nym-vpn-core/crates/nym-vpn-network-config/src/response.rs deleted file mode 100644 index 9762d75589..0000000000 --- a/nym-vpn-core/crates/nym-vpn-network-config/src/response.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2024 - Nym Technologies SA -// SPDX-License-Identifier: GPL-3.0-only - -use nym_config::defaults::NymNetworkDetails; - -// The response type we fetch from the discovery endpoint -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] -pub(super) struct DiscoveryResponse { - pub(super) network_name: String, - pub(super) nym_api_url: String, - pub(super) nym_vpn_api_url: String, - pub(super) account_management: Option, - pub(super) feature_flags: Option, - pub(super) system_messages: Option>, -} - -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] -pub(super) struct AccountManagementResponse { - pub(super) url: String, - pub(super) paths: AccountManagementPathsResponse, -} - -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] -pub(super) struct AccountManagementPathsResponse { - pub(super) sign_up: String, - pub(super) sign_in: String, - pub(super) account: String, -} - -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub(super) struct SystemMessageResponse { - pub(super) name: String, - pub(super) display_from: String, - pub(super) display_until: String, - pub(super) message: String, - pub(super) properties: serde_json::Value, -} - -// The response type we fetch from the network details endpoint. This will be added to and exported -// from nym-api-requests. -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] -pub(super) struct NymNetworkDetailsResponse { - pub(super) network: NymNetworkDetails, -} - -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] -pub(super) struct NymWellknownDiscoveryItem { - pub(super) network_name: String, - pub(super) nym_api_url: String, - pub(super) nym_vpn_api_url: String, -} diff --git a/nym-vpn-core/crates/nym-vpn-network-config/src/system_messages.rs b/nym-vpn-core/crates/nym-vpn-network-config/src/system_messages.rs index e6a219dcc2..908d62a036 100644 --- a/nym-vpn-core/crates/nym-vpn-network-config/src/system_messages.rs +++ b/nym-vpn-core/crates/nym-vpn-network-config/src/system_messages.rs @@ -7,7 +7,7 @@ use anyhow::Context; use serde::{Deserialize, Serialize}; use time::{format_description::well_known::Rfc3339, OffsetDateTime}; -use crate::response::SystemMessageResponse; +use nym_vpn_api_client::response::SystemMessageResponse; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default)] pub struct SystemMessages {