moved for adding new gateways to separate command and made client init only first time setup related
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliNativeClient;
|
||||
use crate::error::ClientError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientAddGatewayArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientAddGatewayArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliNativeClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -20,6 +20,7 @@ use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
pub(crate) mod build_info;
|
||||
pub(crate) mod import_credential;
|
||||
pub(crate) mod init;
|
||||
@@ -77,6 +78,9 @@ pub(crate) enum Commands {
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
@@ -110,6 +114,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync
|
||||
Commands::Run(m) => run::execute(m).await?,
|
||||
Commands::ImportCredential(m) => import_credential::execute(m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliSocks5Client;
|
||||
use crate::error::Socks5ClientError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientAddGatewayArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientAddGatewayArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliSocks5Client, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -24,6 +24,7 @@ use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
pub(crate) mod build_info;
|
||||
mod import_credential;
|
||||
pub mod init;
|
||||
@@ -81,6 +82,9 @@ pub(crate) enum Commands {
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
@@ -117,6 +121,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync
|
||||
Commands::Run(m) => run::execute(m).await?,
|
||||
Commands::ImportCredential(m) => import_credential::execute(m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli_helpers::types::GatewayInfo;
|
||||
use crate::cli_helpers::{CliClient, CliClientConfig};
|
||||
use crate::client::base_client::non_wasm_helpers::setup_fs_gateways_storage;
|
||||
use crate::{
|
||||
client::{
|
||||
base_client::storage::helpers::{get_all_registered_identities, set_active_gateway},
|
||||
key_manager::persistence::OnDiskKeys,
|
||||
},
|
||||
error::ClientCoreError,
|
||||
init::types::{GatewaySelectionSpecification, GatewaySetup},
|
||||
};
|
||||
use log::info;
|
||||
use nym_client_core_gateways_storage::GatewayDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_topology::NymTopology;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CommonClientAddGatewayArgs {
|
||||
/// Id of client we want to add gateway for.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub id: String,
|
||||
|
||||
/// Explicitly specify id of the gateway to register with.
|
||||
/// If unspecified, a random gateway will be chosen instead.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub gateway: Option<identity::PublicKey>,
|
||||
|
||||
/// Specifies whether the client will attempt to enforce tls connection to the desired gateway.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub force_tls_gateway: bool,
|
||||
|
||||
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
|
||||
/// uniformly.
|
||||
#[cfg_attr(feature = "cli", clap(long, conflicts_with = "gateway"))]
|
||||
pub latency_based_selection: bool,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub force_register_gateway: bool,
|
||||
|
||||
/// Specify whether this new gateway should be set as the active one
|
||||
#[cfg_attr(feature = "cli", clap(long, default_value_t = true))]
|
||||
pub set_active: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the API validators
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(
|
||||
long,
|
||||
alias = "api_validators",
|
||||
value_delimiter = ',',
|
||||
group = "network"
|
||||
)
|
||||
)]
|
||||
pub nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Path to .json file containing custom network specification.
|
||||
#[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))]
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub async fn add_gateway<C, A>(args: A) -> Result<GatewayInfo, C::Error>
|
||||
where
|
||||
A: AsRef<CommonClientAddGatewayArgs>,
|
||||
C: CliClient,
|
||||
{
|
||||
let common_args = args.as_ref();
|
||||
let id = &common_args.id;
|
||||
|
||||
let config = C::try_load_current_config(id).await?;
|
||||
let core = config.core_config();
|
||||
let paths = config.common_paths();
|
||||
|
||||
let key_store = OnDiskKeys::new(paths.keys.clone());
|
||||
let details_store = setup_fs_gateways_storage(&paths.gateway_registrations).await?;
|
||||
|
||||
let user_wants_force_register = common_args.force_register_gateway;
|
||||
if user_wants_force_register {
|
||||
eprintln!("Instructed to force registering gateway. This might overwrite keys!");
|
||||
}
|
||||
|
||||
// Attempt to use a user-provided gateway, if possible
|
||||
let user_chosen_gateway_id = common_args.gateway;
|
||||
log::debug!("User chosen gateway id: {user_chosen_gateway_id:?}");
|
||||
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||
Some(common_args.latency_based_selection),
|
||||
common_args.force_tls_gateway,
|
||||
);
|
||||
log::debug!("Gateway selection specification: {selection_spec:?}");
|
||||
|
||||
let registered_gateways = get_all_registered_identities(&details_store).await?;
|
||||
|
||||
// if user provided gateway id (and we can't overwrite data), make sure we're not trying to register
|
||||
// with a known gateway
|
||||
if let Some(user_chosen) = user_chosen_gateway_id {
|
||||
if !common_args.force_register_gateway && registered_gateways.contains(&user_chosen) {
|
||||
return Err(ClientCoreError::AlreadyRegistered {
|
||||
gateway_id: user_chosen.to_base58_string(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let available_gateways = if let Some(custom_mixnet) = common_args.custom_mixnet.as_ref() {
|
||||
let hardcoded_topology = NymTopology::new_from_file(custom_mixnet).map_err(|source| {
|
||||
ClientCoreError::CustomTopologyLoadFailure {
|
||||
file_path: custom_mixnet.clone(),
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
|
||||
};
|
||||
|
||||
// since we're registering with a brand new gateway,
|
||||
// make sure the list of available gateways doesn't overlap the list of known gateways
|
||||
let available_gateways = if common_args.force_register_gateway {
|
||||
// if we're force registering, all bets are off
|
||||
available_gateways
|
||||
} else {
|
||||
available_gateways
|
||||
.into_iter()
|
||||
.filter(|g| !registered_gateways.contains(g.identity()))
|
||||
.collect()
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: common_args.force_register_gateway,
|
||||
wg_tun_address: None,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
crate::init::setup_gateway(gateway_setup, &key_store, &details_store).await?;
|
||||
|
||||
let address = init_details.client_address();
|
||||
|
||||
let gateway_registration = init_details.gateway_registration;
|
||||
let GatewayDetails::Remote(ref gateway_details) = gateway_registration.details else {
|
||||
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
|
||||
};
|
||||
|
||||
if common_args.set_active {
|
||||
set_active_gateway(
|
||||
&details_store,
|
||||
&gateway_details.gateway_id.to_base58_string(),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
info!("registered with new gateway {} (under address {address}), but this will not be our default address", gateway_details.gateway_id);
|
||||
}
|
||||
|
||||
Ok(GatewayInfo {
|
||||
registration: gateway_registration.registration_timestamp,
|
||||
identity: gateway_details.gateway_id,
|
||||
active: common_args.set_active,
|
||||
typ: gateway_registration.details.typ().to_string(),
|
||||
endpoint: Some(gateway_details.gateway_listener.clone()),
|
||||
wg_tun_address: gateway_details.wg_tun_address.clone(),
|
||||
})
|
||||
}
|
||||
@@ -6,8 +6,7 @@ use crate::error::ClientCoreError;
|
||||
use crate::{
|
||||
client::{
|
||||
base_client::{
|
||||
non_wasm_helpers::setup_fs_gateways_storage,
|
||||
storage::helpers::{get_all_registered_identities, set_active_gateway},
|
||||
non_wasm_helpers::setup_fs_gateways_storage, storage::helpers::set_active_gateway,
|
||||
},
|
||||
key_manager::persistence::OnDiskKeys,
|
||||
},
|
||||
@@ -52,16 +51,6 @@ pub struct CommonClientInitArgs {
|
||||
#[cfg_attr(feature = "cli", clap(long, conflicts_with = "gateway"))]
|
||||
pub latency_based_selection: bool,
|
||||
|
||||
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
|
||||
/// potentially causing loss of access.
|
||||
#[cfg_attr(feature = "cli", clap(long))]
|
||||
pub force_register_gateway: bool,
|
||||
|
||||
/// If the registration is happening against new gateway,
|
||||
/// specify whether it should be set as the currently active gateway
|
||||
#[cfg_attr(feature = "cli", clap(long, default_value_t = true))]
|
||||
pub set_active: bool,
|
||||
|
||||
/// Comma separated list of rest endpoints of the nyxd validators
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
@@ -118,28 +107,16 @@ where
|
||||
let common_args = init_args.as_ref();
|
||||
let id = &common_args.id;
|
||||
|
||||
let already_init = if C::default_config_path(id).exists() {
|
||||
// in case we're using old config, try to upgrade it
|
||||
// (if we're using the current version, it's a no-op)
|
||||
C::try_upgrade_outdated_config(id).await?;
|
||||
if C::default_config_path(id).exists() {
|
||||
eprintln!("{} client \"{id}\" was already initialised before", C::NAME);
|
||||
true
|
||||
} else {
|
||||
info!(
|
||||
"{} client {id:?} hasn't been initialised before - new keys are going to be generated",
|
||||
C::NAME
|
||||
);
|
||||
C::initialise_storage_paths(id)?;
|
||||
false
|
||||
};
|
||||
|
||||
// Usually you only register with the gateway on the first init, however you can force
|
||||
// re-registering if wanted.
|
||||
let user_wants_force_register = common_args.force_register_gateway;
|
||||
if user_wants_force_register {
|
||||
eprintln!("Instructed to force registering gateway. This might overwrite keys!");
|
||||
return Err(ClientCoreError::AlreadyInitialised {
|
||||
client_id: id.to_string(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
C::initialise_storage_paths(id)?;
|
||||
|
||||
// Attempt to use a user-provided gateway, if possible
|
||||
let user_chosen_gateway_id = common_args.gateway;
|
||||
log::debug!("User chosen gateway id: {user_chosen_gateway_id:?}");
|
||||
@@ -171,24 +148,8 @@ where
|
||||
let key_store = OnDiskKeys::new(paths.keys.clone());
|
||||
let details_store = setup_fs_gateways_storage(&paths.gateway_registrations).await?;
|
||||
|
||||
// if this is a first time client with this particular id is initialised, generated long-term keys
|
||||
if !already_init {
|
||||
let mut rng = OsRng;
|
||||
crate::init::generate_new_client_keys(&mut rng, &key_store).await?;
|
||||
}
|
||||
|
||||
let registered_gateways = get_all_registered_identities(&details_store).await?;
|
||||
|
||||
// if user provided gateway id (and we can't overwrite data), make sure we're not trying to register
|
||||
// with a known gateway
|
||||
if let Some(user_chosen) = user_chosen_gateway_id {
|
||||
if !common_args.force_register_gateway && registered_gateways.contains(&user_chosen) {
|
||||
return Err(ClientCoreError::AlreadyRegistered {
|
||||
gateway_id: user_chosen.to_base58_string(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
let mut rng = OsRng;
|
||||
crate::init::generate_new_client_keys(&mut rng, &key_store).await?;
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
@@ -205,22 +166,10 @@ where
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
|
||||
};
|
||||
|
||||
// since we're registering with a brand new gateway,
|
||||
// make sure the list of available gateways doesn't overlap the list of known gateways
|
||||
let available_gateways = if common_args.force_register_gateway {
|
||||
// if we're force registering, all bets are off
|
||||
available_gateways
|
||||
} else {
|
||||
available_gateways
|
||||
.into_iter()
|
||||
.filter(|g| !registered_gateways.contains(g.identity()))
|
||||
.collect()
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: common_args.force_register_gateway,
|
||||
overwrite_data: false,
|
||||
wg_tun_address: None,
|
||||
};
|
||||
|
||||
@@ -228,25 +177,22 @@ where
|
||||
crate::init::setup_gateway(gateway_setup, &key_store, &details_store).await?;
|
||||
|
||||
// TODO: ask the service provider we specified for its interface version and set it in the config
|
||||
|
||||
if !already_init {
|
||||
let config_save_location = config.default_store_location();
|
||||
if let Err(err) = config.save_to(&config_save_location) {
|
||||
return Err(ClientCoreError::ConfigSaveFailure {
|
||||
typ: C::NAME.to_string(),
|
||||
id: id.to_string(),
|
||||
path: config_save_location,
|
||||
source: err,
|
||||
}
|
||||
.into());
|
||||
let config_save_location = config.default_store_location();
|
||||
if let Err(err) = config.save_to(&config_save_location) {
|
||||
return Err(ClientCoreError::ConfigSaveFailure {
|
||||
typ: C::NAME.to_string(),
|
||||
id: id.to_string(),
|
||||
path: config_save_location,
|
||||
source: err,
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"Saved configuration file to {}",
|
||||
config_save_location.display()
|
||||
);
|
||||
.into());
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"Saved configuration file to {}",
|
||||
config_save_location.display()
|
||||
);
|
||||
|
||||
let address = init_details.client_address();
|
||||
|
||||
let GatewayDetails::Remote(gateway_details) = init_details.gateway_registration.details else {
|
||||
@@ -260,11 +206,7 @@ where
|
||||
init_details.gateway_registration.registration_timestamp,
|
||||
);
|
||||
|
||||
if init_args.as_ref().set_active {
|
||||
set_active_gateway(&details_store, &init_results.gateway_id).await?;
|
||||
} else {
|
||||
info!("registered with new gateway {} (under address {address}), but this will not be our default address", init_results.gateway_id);
|
||||
}
|
||||
set_active_gateway(&details_store, &init_results.gateway_id).await?;
|
||||
|
||||
Ok(InitResultsWithConfig {
|
||||
config,
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::types::GatewayInfo;
|
||||
use crate::cli_helpers::{CliClient, CliClientConfig};
|
||||
use crate::client::base_client::non_wasm_helpers::setup_fs_gateways_storage;
|
||||
use crate::client::base_client::storage::helpers::{
|
||||
get_active_gateway_identity, get_gateway_registrations,
|
||||
};
|
||||
use nym_client_core_gateways_storage::{GatewayDetails, GatewayType};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -34,38 +32,6 @@ impl Display for RegisteredGateways {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GatewayInfo {
|
||||
pub registration: OffsetDateTime,
|
||||
pub identity: identity::PublicKey,
|
||||
pub active: bool,
|
||||
|
||||
pub typ: String,
|
||||
pub endpoint: Option<Url>,
|
||||
pub wg_tun_address: Option<Url>,
|
||||
}
|
||||
|
||||
impl Display for GatewayInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.active {
|
||||
write!(f, "[ACTIVE] ")?;
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{} gateway '{}' registered at: {}",
|
||||
self.typ, self.identity, self.registration
|
||||
)?;
|
||||
if let Some(endpoint) = &self.endpoint {
|
||||
write!(f, " endpoint: {endpoint}")?;
|
||||
}
|
||||
|
||||
if let Some(wg_tun_address) = &self.wg_tun_address {
|
||||
write!(f, " wg tun address: {wg_tun_address}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_gateways<C, A>(args: A) -> Result<RegisteredGateways, C::Error>
|
||||
where
|
||||
A: AsRef<CommonClientListGatewaysArgs>,
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod client_add_gateway;
|
||||
pub mod client_import_credential;
|
||||
pub mod client_init;
|
||||
pub mod client_list_gateways;
|
||||
pub mod client_run;
|
||||
pub mod client_switch_gateway;
|
||||
pub mod traits;
|
||||
mod types;
|
||||
|
||||
pub use client_init::InitialisableClient;
|
||||
pub use traits::{CliClient, CliClientConfig};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GatewayInfo {
|
||||
pub registration: OffsetDateTime,
|
||||
pub identity: identity::PublicKey,
|
||||
pub active: bool,
|
||||
|
||||
pub typ: String,
|
||||
pub endpoint: Option<Url>,
|
||||
pub wg_tun_address: Option<Url>,
|
||||
}
|
||||
|
||||
impl Display for GatewayInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.active {
|
||||
write!(f, "[ACTIVE] ")?;
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{} gateway '{}' registered at: {}",
|
||||
self.typ, self.identity, self.registration
|
||||
)?;
|
||||
if let Some(endpoint) = &self.endpoint {
|
||||
write!(f, " endpoint: {endpoint}")?;
|
||||
}
|
||||
|
||||
if let Some(wg_tun_address) = &self.wg_tun_address {
|
||||
write!(f, " wg tun address: {wg_tun_address}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -198,6 +198,9 @@ pub enum ClientCoreError {
|
||||
source: url::ParseError,
|
||||
},
|
||||
|
||||
#[error("this client (id: '{client_id}') has already been initialised before. If you want to add additional gateway, use `add-gateway` command")]
|
||||
AlreadyInitialised { client_id: String },
|
||||
|
||||
#[error("this client has already registered with gateway {gateway_id}")]
|
||||
AlreadyRegistered { gateway_id: String },
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::IdentityKey;
|
||||
|
||||
pub struct NymNode {
|
||||
/// Network address of this mixnode, for example 1.1.1.1 or foo.nymnode.com
|
||||
/// that will used for discovering other capabilities of this node.
|
||||
pub host: String,
|
||||
|
||||
/// Base58-encoded ed25519 EdDSA public key.
|
||||
pub identity_key: IdentityKey,
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_list_gateways::{
|
||||
list_gateways, CommonClientListGatewaysArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientListGatewaysArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientListGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientListGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), IpPacketRouterError> {
|
||||
let output = args.output;
|
||||
let res = list_gateways::<CliIpPacketRouterClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use nym_ip_packet_router::config::{BaseClientConfig, Config};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
mod build_info;
|
||||
mod import_credential;
|
||||
mod init;
|
||||
@@ -69,6 +70,9 @@ pub(crate) enum Commands {
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
@@ -126,6 +130,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), IpPacketRouterError> {
|
||||
Commands::Run(m) => run::execute(&m).await?,
|
||||
Commands::ImportCredential(m) => import_credential::execute(m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::Sign(m) => sign::execute(&m).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_list_gateways::{
|
||||
list_gateways, CommonClientListGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientListGatewaysArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientListGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientListGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), NetworkRequesterError> {
|
||||
let output = args.output;
|
||||
let res = list_gateways::<CliNetworkRequesterClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -16,6 +16,7 @@ use nym_client_core::cli_helpers::CliClient;
|
||||
use nym_config::OptionalSet;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
mod build_info;
|
||||
mod import_credential;
|
||||
mod init;
|
||||
@@ -79,6 +80,9 @@ pub(crate) enum Commands {
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
@@ -178,6 +182,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> {
|
||||
Commands::Sign(m) => sign::execute(&m).await?,
|
||||
Commands::ImportCredential(m) => import_credential::execute(m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
|
||||
Reference in New Issue
Block a user