chore: refresh wasm sdk (#5353)
* make packet statistics wasm-compatible * fixed possible overflow issue in delay controller * updated wasm-client to be compatible with the current network * applied same logic to mixfetch client * removed dead imports * updated versions
This commit is contained in:
committed by
GitHub
parent
fffec65cab
commit
adb248dbcc
Generated
+5
-4
@@ -2843,7 +2843,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"gloo-utils 0.2.0",
|
||||
"http 1.1.0",
|
||||
"http 1.2.0",
|
||||
"js-sys",
|
||||
"pin-project",
|
||||
"serde",
|
||||
@@ -4223,7 +4223,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mix-fetch-wasm"
|
||||
version = "1.3.0-rc.0"
|
||||
version = "1.4.0-rc.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"futures",
|
||||
@@ -5048,7 +5048,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client-wasm"
|
||||
version = "1.3.0-rc.0"
|
||||
version = "1.4.0-rc.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
@@ -6014,7 +6014,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.3.1"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -6662,6 +6662,7 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
"time",
|
||||
"tokio",
|
||||
"wasmtimer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -472,6 +472,7 @@ where
|
||||
.claim_initial_bandwidth()
|
||||
.await
|
||||
.map_err(gateway_failure)?;
|
||||
|
||||
gateway_client
|
||||
.start_listening_for_mixnet_messages()
|
||||
.map_err(gateway_failure)?;
|
||||
|
||||
@@ -9,10 +9,12 @@ use self::{
|
||||
acknowledgement_control::AcknowledgementController, real_traffic_stream::OutQueueControl,
|
||||
};
|
||||
use crate::client::real_messages_control::message_handler::MessageHandler;
|
||||
use crate::client::replies::reply_controller;
|
||||
use crate::client::replies::reply_controller::{
|
||||
ReplyController, ReplyControllerReceiver, ReplyControllerSender,
|
||||
};
|
||||
use crate::client::replies::reply_storage::CombinedReplyStorage;
|
||||
use crate::config;
|
||||
use crate::{
|
||||
client::{
|
||||
inbound_messages::InputMessageReceiver, mix_traffic::BatchMixMessageSender,
|
||||
@@ -27,16 +29,13 @@ use nym_gateway_client::AcknowledgementReceiver;
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_statistics_common::clients::ClientStatsSender;
|
||||
use nym_task::connections::{ConnectionCommandReceiver, LaneQueueLengths};
|
||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::client::replies::reply_controller;
|
||||
use crate::config;
|
||||
pub(crate) use acknowledgement_control::{AckActionSender, Action};
|
||||
|
||||
use nym_statistics_common::clients::ClientStatsSender;
|
||||
|
||||
pub(crate) mod acknowledgement_control;
|
||||
pub(crate) mod message_handler;
|
||||
pub(crate) mod real_traffic_stream;
|
||||
|
||||
+4
-1
@@ -70,7 +70,10 @@ impl SendingDelayController {
|
||||
lower_bound,
|
||||
multiplier_elevated_counter: 0,
|
||||
time_when_logged_about_elevated_multiplier: now
|
||||
- Duration::from_secs(INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS),
|
||||
.checked_sub(Duration::from_secs(
|
||||
INTERVAL_BETWEEN_WARNING_ABOUT_ELEVATED_MULTIPLIER_SECS,
|
||||
))
|
||||
.unwrap_or(now),
|
||||
time_when_changed: now,
|
||||
time_when_backpressure_detected: now,
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
#![warn(clippy::todo)]
|
||||
#![warn(clippy::dbg_macro)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use futures::StreamExt;
|
||||
use nym_client_core_config_types::StatsReporting;
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_statistics_common::clients::{
|
||||
ClientStatsController, ClientStatsReceiver, ClientStatsSender,
|
||||
};
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{
|
||||
client::inbound_messages::{InputMessage, InputMessageSender},
|
||||
@@ -94,10 +94,32 @@ impl StatisticsControl {
|
||||
async fn run_with_shutdown(&mut self, mut task_client: nym_task::TaskClient) {
|
||||
log::debug!("Started StatisticsControl with graceful shutdown support");
|
||||
|
||||
let mut stats_report_interval =
|
||||
tokio::time::interval(self.reporting_config.reporting_interval);
|
||||
let mut local_report_interval = tokio::time::interval(LOCAL_REPORT_INTERVAL);
|
||||
let mut snapshot_interval = tokio::time::interval(SNAPSHOT_INTERVAL);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut stats_report_interval = tokio_stream::wrappers::IntervalStream::new(
|
||||
tokio::time::interval(self.reporting_config.reporting_interval),
|
||||
);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut local_report_interval = tokio_stream::wrappers::IntervalStream::new(
|
||||
tokio::time::interval(LOCAL_REPORT_INTERVAL),
|
||||
);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut snapshot_interval =
|
||||
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(SNAPSHOT_INTERVAL));
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let mut stats_report_interval = gloo_timers::future::IntervalStream::new(
|
||||
self.reporting_config.reporting_interval.as_millis() as u32,
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let mut local_report_interval =
|
||||
gloo_timers::future::IntervalStream::new(LOCAL_REPORT_INTERVAL.as_millis() as u32);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let mut snapshot_interval =
|
||||
gloo_timers::future::IntervalStream::new(SNAPSHOT_INTERVAL.as_millis() as u32);
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
@@ -108,16 +130,20 @@ impl StatisticsControl {
|
||||
break;
|
||||
}
|
||||
},
|
||||
_ = snapshot_interval.tick() => {
|
||||
_ = snapshot_interval.next() => {
|
||||
self.stats.snapshot();
|
||||
}
|
||||
_ = stats_report_interval.tick(), if self.reporting_config.enabled && self.reporting_config.provider_address.is_some() => {
|
||||
// SAFTEY : this branch executes only if reporting is not none, so unwrapp is fine
|
||||
#[allow(clippy::unwrap_used)]
|
||||
self.report_stats(self.reporting_config.provider_address.unwrap()).await;
|
||||
_ = stats_report_interval.next() => {
|
||||
let Some(recipient) = self.reporting_config.provider_address else {
|
||||
continue
|
||||
};
|
||||
|
||||
if self.reporting_config.enabled {
|
||||
self.report_stats(recipient).await;
|
||||
}
|
||||
}
|
||||
|
||||
_ = local_report_interval.tick() => {
|
||||
_ = local_report_interval.next() => {
|
||||
self.stats.local_report(&mut task_client);
|
||||
}
|
||||
_ = task_client.recv_with_delay() => {
|
||||
|
||||
@@ -17,7 +17,7 @@ use nym_topology::node::RoutingNode;
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
@@ -221,6 +221,34 @@ pub enum GatewaySetup {
|
||||
},
|
||||
}
|
||||
|
||||
impl Debug for GatewaySetup {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GatewaySetup::MustLoad { gateway_id } => f
|
||||
.debug_struct("GatewaySetup::MustLoad")
|
||||
.field("gateway_id", gateway_id)
|
||||
.finish(),
|
||||
GatewaySetup::New {
|
||||
specification,
|
||||
available_gateways,
|
||||
} => f
|
||||
.debug_struct("GatewaySetup::New")
|
||||
.field("specification", specification)
|
||||
.field("available_gateways", available_gateways)
|
||||
.field("gateways", specification)
|
||||
.finish(),
|
||||
GatewaySetup::ReuseConnection {
|
||||
gateway_details, ..
|
||||
} => f
|
||||
.debug_struct("GatewaySetup::ReuseConnection")
|
||||
.field("authenticated_ephemeral_client", &"***")
|
||||
.field("gateway_details", gateway_details)
|
||||
.field("client_keys", &"***")
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GatewaySetup {
|
||||
pub fn try_reuse_connection(init_res: InitialisationResult) -> Result<Self, ClientCoreError> {
|
||||
if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client {
|
||||
|
||||
@@ -27,3 +27,5 @@ nym-credentials-interface = { path = "../credentials-interface" }
|
||||
nym-metrics = { path = "../nym-metrics" }
|
||||
nym-task = { path = "../task" }
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
|
||||
workspace = true
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
|
||||
use super::ClientStatsEvents;
|
||||
use core::fmt;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::{collections::VecDeque, time::Duration};
|
||||
|
||||
use nym_metrics::{inc, inc_by};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -18,6 +15,51 @@ use si_scale::helpers::bibytes2;
|
||||
// Also, set it larger than the packet report interval so that we don't miss notable singular events
|
||||
const RECORDING_WINDOW_MS: u64 = 2300;
|
||||
|
||||
#[derive(PartialOrd, PartialEq, Clone, Copy, Debug)]
|
||||
struct Instant {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
inner: std::time::Instant,
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
inner: wasmtimer::std::Instant,
|
||||
}
|
||||
|
||||
impl Instant {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn inner(&self) -> &std::time::Instant {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn inner(&self) -> &wasmtimer::std::Instant {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn now() -> Self {
|
||||
Instant {
|
||||
inner: std::time::Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn now() -> Self {
|
||||
Instant {
|
||||
inner: wasmtimer::std::Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
fn checked_sub(&self, duration: Duration) -> Option<Instant> {
|
||||
self.inner()
|
||||
.checked_sub(duration)
|
||||
.map(|inner| Instant { inner })
|
||||
}
|
||||
|
||||
fn duration_since(&self, earlier: &Instant) -> Duration {
|
||||
self.inner.duration_since(*earlier.inner())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct PacketStatistics {
|
||||
// Sent
|
||||
@@ -424,7 +466,11 @@ impl PacketStatisticsControl {
|
||||
self.history.push_back((Instant::now(), self.stats.clone()));
|
||||
|
||||
// Filter out old ones
|
||||
let recording_window = Instant::now() - Duration::from_millis(RECORDING_WINDOW_MS);
|
||||
let now = Instant::now();
|
||||
let recording_window = Instant::now()
|
||||
.checked_sub(Duration::from_millis(RECORDING_WINDOW_MS))
|
||||
.unwrap_or(now);
|
||||
|
||||
while self
|
||||
.history
|
||||
.front()
|
||||
@@ -442,7 +488,7 @@ impl PacketStatisticsControl {
|
||||
|
||||
// Do basic averaging over the entire history, which just uses the first and last
|
||||
if let Some((start, start_stats)) = self.history.front() {
|
||||
let duration_secs = Instant::now().duration_since(*start).as_secs_f64();
|
||||
let duration_secs = Instant::now().duration_since(start).as_secs_f64();
|
||||
let delta = self.stats.clone() - start_stats.clone();
|
||||
let rates = PacketRates::from(delta) / duration_secs;
|
||||
Some(rates)
|
||||
@@ -458,7 +504,10 @@ impl PacketStatisticsControl {
|
||||
}
|
||||
|
||||
// Filter out old ones
|
||||
let recording_window = Instant::now() - Duration::from_millis(RECORDING_WINDOW_MS);
|
||||
let now = Instant::now();
|
||||
let recording_window = now
|
||||
.checked_sub(Duration::from_millis(RECORDING_WINDOW_MS))
|
||||
.unwrap_or(now);
|
||||
while self
|
||||
.rates
|
||||
.front()
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
||||
target_arch = "wasm32"
|
||||
@@ -5,12 +5,15 @@ use crate::error::WasmCoreError;
|
||||
use crate::storage::wasm_client_traits::WasmClientStorage;
|
||||
use crate::storage::ClientStorage;
|
||||
use js_sys::Promise;
|
||||
use nym_client_core::client::base_client::storage::helpers::set_active_gateway;
|
||||
use nym_client_core::client::base_client::storage::GatewaysDetailsStore;
|
||||
use nym_client_core::client::replies::reply_storage::browser_backend;
|
||||
use nym_client_core::config;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::init::helpers::current_gateways;
|
||||
use nym_client_core::init::types::GatewaySelectionSpecification;
|
||||
use nym_client_core::init::{
|
||||
self,
|
||||
self, setup_gateway,
|
||||
types::{GatewaySetup, InitialisationResult},
|
||||
};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
@@ -18,7 +21,7 @@ use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_topology::wasm_helpers::WasmFriendlyNymTopology;
|
||||
use nym_topology::{NymTopology, RoutingNode};
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::NymApiClient;
|
||||
use nym_validator_client::{NymApiClient, UserAgent};
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
@@ -26,6 +29,7 @@ use wasm_bindgen_futures::future_to_promise;
|
||||
use wasm_utils::error::PromisableResult;
|
||||
|
||||
pub use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use wasm_utils::console_log;
|
||||
|
||||
// don't get too excited about the name, under the hood it's just a big fat placeholder
|
||||
// with no disk_persistence
|
||||
@@ -134,6 +138,15 @@ pub async fn setup_gateway_from_api(
|
||||
setup_gateway_wasm(client_store, force_tls, chosen_gateway, gateways).await
|
||||
}
|
||||
|
||||
pub async fn current_gateways_wasm(
|
||||
nym_apis: &[Url],
|
||||
user_agent: Option<UserAgent>,
|
||||
minimum_performance: u8,
|
||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
||||
let mut rng = thread_rng();
|
||||
current_gateways(&mut rng, nym_apis, user_agent, minimum_performance).await
|
||||
}
|
||||
|
||||
pub async fn setup_from_topology(
|
||||
explicit_gateway: Option<IdentityKey>,
|
||||
force_tls: bool,
|
||||
@@ -143,3 +156,76 @@ pub async fn setup_from_topology(
|
||||
let gateways = topology.entry_capable_nodes().cloned().collect::<Vec<_>>();
|
||||
setup_gateway_wasm(client_store, force_tls, explicit_gateway, gateways).await
|
||||
}
|
||||
|
||||
pub async fn generate_new_client_keys(store: &ClientStorage) -> Result<(), WasmCoreError> {
|
||||
let mut rng = thread_rng();
|
||||
init::generate_new_client_keys(&mut rng, store).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_gateway(
|
||||
preferred_gateway: Option<IdentityKey>,
|
||||
latency_based_selection: Option<bool>,
|
||||
force_tls: bool,
|
||||
nym_apis: &[Url],
|
||||
user_agent: UserAgent,
|
||||
min_performance: u8,
|
||||
storage: &ClientStorage,
|
||||
) -> Result<(), WasmCoreError> {
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
preferred_gateway.clone(),
|
||||
latency_based_selection,
|
||||
force_tls,
|
||||
);
|
||||
|
||||
let preferred_gateway = preferred_gateway
|
||||
.as_ref()
|
||||
.map(|g| g.parse())
|
||||
.transpose()
|
||||
.map_err(|source| WasmCoreError::InvalidGatewayIdentity { source })?;
|
||||
|
||||
let registered_gateways = storage.all_gateways_identities().await.map_err(|source| {
|
||||
ClientCoreError::GatewaysDetailsStoreError {
|
||||
source: Box::new(source),
|
||||
}
|
||||
})?;
|
||||
|
||||
// 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) = preferred_gateway {
|
||||
if 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 =
|
||||
current_gateways_wasm(nym_apis, Some(user_agent), min_performance).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 = available_gateways
|
||||
.into_iter()
|
||||
.filter(|g| !registered_gateways.contains(&g.identity()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if available_gateways.is_empty() {
|
||||
return Err(ClientCoreError::NoNewGatewaysAvailable.into());
|
||||
}
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
};
|
||||
|
||||
let init_details = setup_gateway(gateway_setup, storage, storage).await?;
|
||||
let gateway = init_details.gateway_id().to_base58_string();
|
||||
set_active_gateway(storage, &gateway).await?;
|
||||
|
||||
console_log!("finished registration with gateway {gateway}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -128,8 +128,12 @@ impl GatewaysDetailsStore for ClientStorage {
|
||||
}
|
||||
|
||||
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError> {
|
||||
todo!()
|
||||
// let identities = self.all
|
||||
let identities = self.registered_gateways().await?;
|
||||
let mut registered = Vec::with_capacity(identities.len());
|
||||
for gateway_id in identities {
|
||||
registered.push(self.load_gateway_details(&gateway_id).await?);
|
||||
}
|
||||
Ok(registered)
|
||||
}
|
||||
|
||||
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
|
||||
|
||||
@@ -59,6 +59,8 @@ impl ClientStorage {
|
||||
|
||||
db.create_object_store(v2::GATEWAY_REGISTRATIONS_ACTIVE_GATEWAY_STORE)?;
|
||||
db.create_object_store(v2::GATEWAY_REGISTRATIONS_REGISTERED_GATEWAYS_STORE)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// version 1 -> unimplemented migration
|
||||
|
||||
@@ -119,6 +119,15 @@ pub trait WasmClientStorage: BaseWasmStorage {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn has_identity_key(&self) -> Result<bool, <Self as WasmClientStorage>::StorageError> {
|
||||
self.has_value(
|
||||
v1::KEYS_STORE,
|
||||
JsValue::from_str(v1::ED25519_IDENTITY_KEYPAIR),
|
||||
)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn store_identity_keypair(
|
||||
&self,
|
||||
keypair: &identity::KeyPair,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
||||
target_arch = "wasm32"
|
||||
@@ -0,0 +1,3 @@
|
||||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
||||
target_arch = "wasm32"
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nymproject/mix-fetch-node",
|
||||
"version": "1.3.0-rc.0",
|
||||
"version": "1.4.0-rc.0",
|
||||
"description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Nym Technologies SA",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nymproject/mix-fetch",
|
||||
"version": "1.3.0-rc.0",
|
||||
"version": "1.4.0-rc.0",
|
||||
"description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Nym Technologies SA",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nymproject/nodejs-client",
|
||||
"version": "1.3.0-rc.0",
|
||||
"version": "1.4.0-rc.0",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Nym Technologies SA",
|
||||
"files": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nymproject/sdk-react",
|
||||
"version": "1.3.0-rc.0",
|
||||
"version": "1.4.0-rc.0",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Nym Technologies SA",
|
||||
"files": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nymproject/sdk",
|
||||
"version": "1.3.0-rc.0",
|
||||
"version": "1.4.0-rc.0",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Nym Technologies SA",
|
||||
"files": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "nym-client-wasm"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
version = "1.3.0-rc.0"
|
||||
version = "1.4.0-rc.0"
|
||||
edition = "2021"
|
||||
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"]
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -6,7 +6,7 @@ build:
|
||||
wasm-opt -Oz -o ../../dist/wasm/client/nym_client_wasm_bg.wasm ../../dist/wasm/client/nym_client_wasm_bg.wasm
|
||||
|
||||
build-debug-dev:
|
||||
wasm-pack build --scope nymproject --target no-modules
|
||||
wasm-pack build --debug --scope nymproject --target no-modules
|
||||
|
||||
build-rust-node:
|
||||
wasm-pack build --scope nymproject --target nodejs --out-dir ../../dist/node/wasm/client
|
||||
|
||||
+3984
File diff suppressed because it is too large
Load Diff
@@ -100,69 +100,6 @@ function printAndDisplayTestResult(result) {
|
||||
});
|
||||
}
|
||||
|
||||
async function testWithNymClient() {
|
||||
const preferredGateway = "6pXQcG1Jt9hxBzMgTbQL5Y58z6mu4KXVRbA1idmibwsw";
|
||||
const topology = dummyTopology()
|
||||
|
||||
let received = 0
|
||||
|
||||
const onMessageHandler = (message) => {
|
||||
received += 1;
|
||||
self.postMessage({
|
||||
kind: 'ReceiveMessage',
|
||||
args: {
|
||||
message,
|
||||
senderTag: undefined,
|
||||
isMagicPayload: true,
|
||||
},
|
||||
});
|
||||
|
||||
// it's really up to the user to create proper callback here...
|
||||
console.log(`received ${received} packets so far`)
|
||||
};
|
||||
|
||||
console.log('Instantiating WASM client...');
|
||||
|
||||
let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, preferredGateway)
|
||||
console.log('Web worker creating WASM client...');
|
||||
let local_client = await clientBuilder.start_client();
|
||||
console.log('WASM client running!');
|
||||
|
||||
const selfAddress = local_client.self_address();
|
||||
|
||||
// set the global (I guess we don't have to anymore?)
|
||||
client = local_client;
|
||||
|
||||
console.log(`Client address is ${selfAddress}`);
|
||||
self.postMessage({
|
||||
kind: 'Ready',
|
||||
args: {
|
||||
selfAddress,
|
||||
},
|
||||
});
|
||||
|
||||
// Set callback to handle messages passed to the worker.
|
||||
self.onmessage = async event => {
|
||||
console.log(event)
|
||||
if (event.data && event.data.kind) {
|
||||
switch (event.data.kind) {
|
||||
case 'SendMessage': {
|
||||
const {message, recipient} = event.data.args;
|
||||
let uint8Array = new TextEncoder().encode(message);
|
||||
await client.send_regular_message(uint8Array, recipient);
|
||||
break;
|
||||
}
|
||||
case 'MagicPayload': {
|
||||
const {mixnodeIdentity} = event.data.args;
|
||||
const req = await client.try_construct_test_packet_request(mixnodeIdentity);
|
||||
await client.change_hardcoded_topology(req.injectable_topology());
|
||||
await client.try_send_test_packets(req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function wasm_bindgenSetup(onMessageHandler) {
|
||||
const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
@@ -196,7 +133,7 @@ async function wasm_bindgenSetup(onMessageHandler) {
|
||||
updatedTraffic.average_packet_delay_ms = 666;
|
||||
differentDebug.traffic = updatedTraffic;
|
||||
|
||||
const config = new ClientConfig( { debug: differentDebug } );
|
||||
const config = new ClientConfig({debug: differentDebug});
|
||||
//
|
||||
// // STEP 2. setup the client
|
||||
// // note, the extra optional argument is of the following type:
|
||||
@@ -210,15 +147,15 @@ async function wasm_bindgenSetup(onMessageHandler) {
|
||||
// return await NymClient.newWithConfig(config, onMessageHandler)
|
||||
//
|
||||
// #2
|
||||
return await NymClient.newWithConfig(config, onMessageHandler, { storagePassphrase: "foomp" })
|
||||
return await NymClient.newWithConfig(config, onMessageHandler, {storagePassphrase: "foomp"})
|
||||
//
|
||||
// #3
|
||||
// return await NymClient.newWithConfig(config, onMessageHandler, { storagePassphrase: "foomp", preferredGateway })
|
||||
}
|
||||
|
||||
async function nativeSetup(onMessageHandler) {
|
||||
const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
const validator = 'https://qa-nym-api.qa.nymte.ch/api';
|
||||
const preferredGateway = "8ookuLkA9oWfRTjb7Jq4tLGcWrqoXKGQxw84MjMrv2S4";
|
||||
const validator = 'https://sandbox-nym-api1.nymtech.net/api';
|
||||
|
||||
// those are just some examples, there are obviously more permutations;
|
||||
// note, the extra optional argument is of the following type:
|
||||
@@ -239,15 +176,20 @@ async function nativeSetup(onMessageHandler) {
|
||||
// return new NymClient(onMessageHandler, { nymApiUrl: validator })
|
||||
// #3
|
||||
const noCoverTrafficOverride = {
|
||||
traffic: { disableMainPoissonPacketDistribution: true },
|
||||
coverTraffic: { disableLoopCoverTrafficStream: true },
|
||||
traffic: {disableMainPoissonPacketDistribution: true},
|
||||
coverTraffic: {disableLoopCoverTrafficStream: true},
|
||||
}
|
||||
|
||||
return new NymClient(onMessageHandler, { storagePassphrase: "foomp", nymApiUrl: validator, clientId: "my-client", clientOverride: noCoverTrafficOverride } )
|
||||
return new NymClient(onMessageHandler, {
|
||||
// storagePassphrase: "foomp",
|
||||
nymApiUrl: validator,
|
||||
clientId: "my-client",
|
||||
clientOverride: noCoverTrafficOverride
|
||||
})
|
||||
}
|
||||
|
||||
async function normalNymClientUsage() {
|
||||
self.postMessage({ kind: 'DisableMagicTestButton' });
|
||||
self.postMessage({kind: 'DisableMagicTestButton'});
|
||||
|
||||
const onMessageHandler = (message) => {
|
||||
console.log(message);
|
||||
@@ -264,7 +206,7 @@ async function normalNymClientUsage() {
|
||||
let localClient = await nativeSetup(onMessageHandler)
|
||||
console.log('WASM client running!');
|
||||
|
||||
const selfAddress = localClient.self_address();
|
||||
const selfAddress = localClient.selfAddress();
|
||||
|
||||
// set the global (I guess we don't have to anymore?)
|
||||
client = localClient;
|
||||
|
||||
+386
-374
File diff suppressed because it is too large
Load Diff
+114
-53
@@ -12,31 +12,30 @@ use crate::error::WasmClientError;
|
||||
use crate::helpers::{InputSender, WasmTopologyExt};
|
||||
use crate::response_pusher::ResponsePusher;
|
||||
use js_sys::Promise;
|
||||
use nym_bin_common::bin_info;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::future_to_promise;
|
||||
use wasm_client_core::client::base_client::storage::GatewaysDetailsStore;
|
||||
use wasm_client_core::client::{
|
||||
base_client::{BaseClientBuilder, ClientInput, ClientOutput, ClientState},
|
||||
inbound_messages::InputMessage,
|
||||
};
|
||||
use wasm_client_core::config::r#override::DebugWasmOverride;
|
||||
use wasm_client_core::helpers::{
|
||||
parse_recipient, parse_sender_tag, setup_from_topology, setup_gateway_from_api,
|
||||
add_gateway, generate_new_client_keys, parse_recipient, parse_sender_tag,
|
||||
};
|
||||
use wasm_client_core::init::types::GatewaySetup;
|
||||
use wasm_client_core::nym_task::connections::TransmissionLane;
|
||||
use wasm_client_core::nym_task::TaskManager;
|
||||
use wasm_client_core::storage::core_client_traits::FullWasmClientStorage;
|
||||
use wasm_client_core::storage::wasm_client_traits::WasmClientStorage;
|
||||
use wasm_client_core::storage::ClientStorage;
|
||||
use wasm_client_core::topology::{SerializableTopologyExt, WasmFriendlyNymTopology};
|
||||
use wasm_client_core::{
|
||||
HardcodedTopologyProvider, IdentityKey, NymTopology, PacketType, QueryReqwestRpcNyxdClient,
|
||||
TopologyProvider,
|
||||
};
|
||||
use wasm_client_core::{IdentityKey, NymTopology, PacketType, QueryReqwestRpcNyxdClient};
|
||||
use wasm_utils::error::PromisableResult;
|
||||
use wasm_utils::{check_promise_result, console_log};
|
||||
use wasm_utils::{check_promise_result, console_error, console_log};
|
||||
|
||||
#[cfg(feature = "node-tester")]
|
||||
use crate::helpers::{NymClientTestRequest, WasmTopologyTestExt};
|
||||
@@ -45,6 +44,7 @@ use crate::helpers::{NymClientTestRequest, WasmTopologyTestExt};
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
|
||||
#[cfg(feature = "node-tester")]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) const NODE_TESTER_CLIENT_ID: &str = "_nym-node-tester-client";
|
||||
|
||||
#[wasm_bindgen]
|
||||
@@ -70,8 +70,8 @@ pub struct NymClient {
|
||||
pub struct NymClientBuilder {
|
||||
config: ClientConfig,
|
||||
force_tls: bool,
|
||||
custom_topology: Option<NymTopology>,
|
||||
preferred_gateway: Option<IdentityKey>,
|
||||
latency_based_selection: Option<bool>,
|
||||
|
||||
storage_passphrase: Option<String>,
|
||||
on_message: js_sys::Function,
|
||||
@@ -89,11 +89,11 @@ impl NymClientBuilder {
|
||||
NymClientBuilder {
|
||||
config,
|
||||
force_tls,
|
||||
custom_topology: None,
|
||||
storage_passphrase,
|
||||
on_message,
|
||||
// on_mix_fetch_message: Some(on_mix_fetch_message),
|
||||
preferred_gateway,
|
||||
latency_based_selection: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,29 +113,32 @@ impl NymClientBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
let full_config = ClientConfig::new_tester_config(NODE_TESTER_CLIENT_ID);
|
||||
let _ = on_message;
|
||||
// let full_config = ClientConfig::new_tester_config(NODE_TESTER_CLIENT_ID);
|
||||
// Ok(NymClientBuilder {
|
||||
// config: full_config,
|
||||
// force_tls: false,
|
||||
// custom_topology: Some(topology.try_into()?),
|
||||
// on_message,
|
||||
// storage_passphrase: None,
|
||||
// preferred_gateway: gateway,
|
||||
// latency_based_selection: None,
|
||||
// })
|
||||
|
||||
Ok(NymClientBuilder {
|
||||
config: full_config,
|
||||
force_tls: false,
|
||||
custom_topology: Some(topology.try_into()?),
|
||||
on_message,
|
||||
storage_passphrase: None,
|
||||
preferred_gateway: gateway,
|
||||
})
|
||||
Err(WasmClientError::DisabledTester)
|
||||
}
|
||||
|
||||
fn start_reconstructed_pusher(client_output: ClientOutput, on_message: js_sys::Function) {
|
||||
ResponsePusher::new(client_output, on_message).start()
|
||||
}
|
||||
|
||||
fn topology_provider(&mut self) -> Option<Box<dyn TopologyProvider + Send + Sync>> {
|
||||
if let Some(hardcoded_topology) = self.custom_topology.take() {
|
||||
Some(Box::new(HardcodedTopologyProvider::new(hardcoded_topology)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
// fn topology_provider(&mut self) -> Option<Box<dyn TopologyProvider + Send + Sync>> {
|
||||
// if let Some(hardcoded_topology) = self.custom_topology.take() {
|
||||
// Some(Box::new(HardcodedTopologyProvider::new(hardcoded_topology)))
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
|
||||
fn initialise_storage(
|
||||
config: &ClientConfig,
|
||||
@@ -144,48 +147,96 @@ impl NymClientBuilder {
|
||||
FullWasmClientStorage::new(&config.base, base_storage)
|
||||
}
|
||||
|
||||
async fn start_client_async(mut self) -> Result<NymClient, WasmClientError> {
|
||||
console_log!("Starting the wasm client");
|
||||
|
||||
let nym_api_endpoints = self.config.base.client.nym_api_urls.clone();
|
||||
|
||||
// TODO: this will have to be re-used for surbs. but this is a problem for another PR.
|
||||
async fn initialise_client_storage(&mut self) -> Result<ClientStorage, WasmClientError> {
|
||||
let client_store =
|
||||
ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take())
|
||||
.await?;
|
||||
if !client_store.has_identity_key().await? {
|
||||
console_log!(
|
||||
"no prior keys found - a new set will be generated for client {}",
|
||||
self.config.base.client.id
|
||||
);
|
||||
generate_new_client_keys(&client_store).await?;
|
||||
}
|
||||
|
||||
let user_chosen = self.preferred_gateway.clone();
|
||||
Ok(client_store)
|
||||
}
|
||||
|
||||
// if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way
|
||||
let init_res = if let Some(topology) = &self.custom_topology {
|
||||
setup_from_topology(user_chosen, self.force_tls, topology, &client_store).await?
|
||||
} else {
|
||||
setup_gateway_from_api(
|
||||
&client_store,
|
||||
self.force_tls,
|
||||
user_chosen,
|
||||
&nym_api_endpoints,
|
||||
self.config.base.debug.topology.minimum_gateway_performance,
|
||||
)
|
||||
.await?
|
||||
async fn try_set_preferred_gateway(
|
||||
&self,
|
||||
client_store: &ClientStorage,
|
||||
) -> Result<bool, WasmClientError> {
|
||||
let Some(preferred) = self.preferred_gateway.as_ref() else {
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
if client_store
|
||||
.has_gateway_details(&preferred.to_string())
|
||||
.await?
|
||||
{
|
||||
GatewaysDetailsStore::set_active_gateway(client_store, &preferred.to_string()).await?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
// async fn start_client(mut self) -> Result<NymClient, WasmClientError> {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
async fn has_active_gateway(
|
||||
&self,
|
||||
client_store: &ClientStorage,
|
||||
) -> Result<bool, WasmClientError> {
|
||||
Ok(client_store
|
||||
.get_active_gateway_id()
|
||||
.await?
|
||||
.active_gateway_id_bs58
|
||||
.is_some())
|
||||
}
|
||||
|
||||
async fn start_client_async(mut self) -> Result<NymClient, WasmClientError> {
|
||||
console_log!("Starting the wasm client");
|
||||
|
||||
// TODO: resolve this properly
|
||||
self.config.base.debug.topology.ignore_egress_epoch_role = true;
|
||||
|
||||
// TODO: this will have to be re-used for surbs. but this is a problem for another PR.
|
||||
let client_store = self.initialise_client_storage().await?;
|
||||
|
||||
// if we don't have an active gateway (i.e. no gateways), add one
|
||||
// otherwise, see if we set a preferred gateway and attempt to set its details as active
|
||||
if !self.has_active_gateway(&client_store).await?
|
||||
|| !self.try_set_preferred_gateway(&client_store).await?
|
||||
{
|
||||
add_gateway(
|
||||
self.preferred_gateway.clone(),
|
||||
self.latency_based_selection,
|
||||
self.force_tls,
|
||||
&self.config.base.client.nym_api_urls,
|
||||
bin_info!().into(),
|
||||
self.config.base.debug.topology.minimum_gateway_performance,
|
||||
&client_store,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let packet_type = self.config.base.debug.traffic.packet_type;
|
||||
let storage = Self::initialise_storage(&self.config, client_store);
|
||||
let maybe_topology_provider = self.topology_provider();
|
||||
|
||||
let mut base_builder = BaseClientBuilder::<QueryReqwestRpcNyxdClient, _>::new(
|
||||
let base_builder = BaseClientBuilder::<QueryReqwestRpcNyxdClient, _>::new(
|
||||
&self.config.base,
|
||||
storage,
|
||||
None,
|
||||
);
|
||||
if let Some(topology_provider) = maybe_topology_provider {
|
||||
base_builder = base_builder.with_topology_provider(topology_provider);
|
||||
}
|
||||
// if let Some(topology_provider) = maybe_topology_provider {
|
||||
// base_builder = base_builder.with_topology_provider(topology_provider);
|
||||
// }
|
||||
|
||||
if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) {
|
||||
base_builder = base_builder.with_gateway_setup(reuse_setup);
|
||||
}
|
||||
// if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) {
|
||||
// base_builder = base_builder.with_gateway_setup(reuse_setup);
|
||||
// }
|
||||
|
||||
let mut started_client = base_builder.start_base().await?;
|
||||
let self_address = started_client.address.to_string();
|
||||
@@ -207,7 +258,12 @@ impl NymClientBuilder {
|
||||
}
|
||||
|
||||
pub fn start_client(self) -> Promise {
|
||||
future_to_promise(async move { self.start_client_async().await.into_promise_result() })
|
||||
future_to_promise(async move {
|
||||
self.start_client_async()
|
||||
.await
|
||||
.inspect_err(|err| console_error!("failed to start the client: {err}"))
|
||||
.into_promise_result()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +280,9 @@ pub struct ClientOptsSimple {
|
||||
|
||||
#[tsify(optional)]
|
||||
pub(crate) force_tls: Option<bool>,
|
||||
|
||||
#[tsify(optional)]
|
||||
pub(crate) latency_based_selection: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)]
|
||||
@@ -281,6 +340,7 @@ impl NymClient {
|
||||
}
|
||||
.start_client_async()
|
||||
.await
|
||||
.inspect_err(|err| console_error!("failed to start the client: {err}"))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(constructor)]
|
||||
@@ -323,6 +383,7 @@ impl NymClient {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "selfAddress")]
|
||||
pub fn self_address(&self) -> String {
|
||||
self.self_address.clone()
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ impl ClientConfig {
|
||||
}
|
||||
|
||||
#[cfg(feature = "node-tester")]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new_tester_config<S: Into<String>>(id: S) -> Self {
|
||||
ClientConfig {
|
||||
base: BaseClientConfig::new(id.into(), env!("CARGO_PKG_VERSION").to_string())
|
||||
|
||||
@@ -36,6 +36,9 @@ pub enum WasmClientError {
|
||||
#[from]
|
||||
source: NetworkTestingError,
|
||||
},
|
||||
|
||||
#[error("the node testing features are currently disabled")]
|
||||
DisabledTester,
|
||||
}
|
||||
|
||||
// I dislike this so much - there must be a better way.
|
||||
|
||||
@@ -28,4 +28,6 @@ pub fn main() {
|
||||
"wasm client version used: {}",
|
||||
nym_bin_common::bin_info_owned!()
|
||||
);
|
||||
wasm_utils::console_log!("[rust main]: setting panic hook");
|
||||
wasm_utils::set_panic_hook();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "mix-fetch-wasm"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
version = "1.3.0-rc.0"
|
||||
version = "1.4.0-rc.0"
|
||||
edition = "2021"
|
||||
keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"]
|
||||
license = "Apache-2.0"
|
||||
@@ -24,7 +24,7 @@ tokio = { workspace = true, features = ["sync"] }
|
||||
url = { workspace = true }
|
||||
wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen-futures = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tsify = { workspace = true, features = ["js"] }
|
||||
|
||||
nym-bin-common = { path = "../../common/bin-common" }
|
||||
|
||||
@@ -12,6 +12,9 @@ build-rust:
|
||||
wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/mix-fetch
|
||||
wasm-opt -Oz -o ../../dist/wasm/mix-fetch/mix_fetch_wasm_bg.wasm ../../dist/wasm/mix-fetch/mix_fetch_wasm_bg.wasm
|
||||
|
||||
build-rust-debug:
|
||||
wasm-pack build --debug --scope nymproject --target no-modules
|
||||
|
||||
build-package-json:
|
||||
node build.mjs
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
build/wasm_exec.js
|
||||
build/main.wasm
|
||||
build/main.wasm
|
||||
build
|
||||
+3971
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,8 @@ const {
|
||||
disconnectMixFetch,
|
||||
setupMixFetchWithConfig,
|
||||
mix_fetch_initialised,
|
||||
finish_mixnet_connection} = wasm_bindgen;
|
||||
finish_mixnet_connection
|
||||
} = wasm_bindgen;
|
||||
|
||||
let client = null;
|
||||
let tester = null;
|
||||
@@ -69,7 +70,7 @@ async function wasm_bindgenSetup() {
|
||||
const validator = 'https://qa-nym-api.qa.nymte.ch/api';
|
||||
|
||||
// local
|
||||
const mixFetchNetworkRequesterAddress= "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
const mixFetchNetworkRequesterAddress = "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
// const mixFetchNetworkRequesterAddress= "GqiGWmKRCbGQFSqH88BzLKijvZgipnqhmbNFsmkZw84t.4L8sXFuAUyUYyHZYgMdM3AtiusKnYUft6Pd8e41rrCHA@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
|
||||
// STEP 1. construct config
|
||||
@@ -100,7 +101,7 @@ async function wasm_bindgenSetup() {
|
||||
updatedTraffic.average_packet_delay_ms = 666;
|
||||
differentDebug.traffic = updatedTraffic;
|
||||
|
||||
const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { debug: differentDebug } );
|
||||
const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, {debug: differentDebug});
|
||||
//
|
||||
// // STEP 2. setup the client
|
||||
// // note, the extra optional argument is of the following type:
|
||||
@@ -121,8 +122,8 @@ async function wasm_bindgenSetup() {
|
||||
}
|
||||
|
||||
async function nativeSetup() {
|
||||
// const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
// const validator = 'https://qa-nym-api.qa.nymte.ch/api';
|
||||
const preferredGateway = "8ookuLkA9oWfRTjb7Jq4tLGcWrqoXKGQxw84MjMrv2S4";
|
||||
const validator = 'https://sandbox-nym-api1.nymtech.net/api';
|
||||
|
||||
// local
|
||||
// const preferredNetworkRequester= "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM";
|
||||
@@ -153,17 +154,17 @@ async function nativeSetup() {
|
||||
// await setupMixFetch(preferredNetworkRequester, { nymApiUrl: validator })
|
||||
// // #3
|
||||
const noCoverTrafficOverride = {
|
||||
traffic: { disableMainPoissonPacketDistribution: true },
|
||||
coverTraffic: { disableLoopCoverTrafficStream: true },
|
||||
traffic: {disableMainPoissonPacketDistribution: true},
|
||||
coverTraffic: {disableLoopCoverTrafficStream: true},
|
||||
}
|
||||
const mixFetchOverride = {
|
||||
requestTimeoutMs: 10000
|
||||
requestTimeoutMs: 20000
|
||||
}
|
||||
|
||||
await setupMixFetch({
|
||||
// preferredNetworkRequester,
|
||||
preferredGateway: "E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM",
|
||||
storagePassphrase: "foomp",
|
||||
// preferredGateway: preferredGateway,
|
||||
// storagePassphrase: "foomp",
|
||||
forceTls: true,
|
||||
// nymApiUrl: validator,
|
||||
clientId: "my-client",
|
||||
@@ -190,7 +191,7 @@ async function testMixFetch() {
|
||||
const url = target;
|
||||
|
||||
// const args = { mode: "ors", redirect: "manual", signal }
|
||||
const args = { mode: "unsafe-ignore-cors" }
|
||||
const args = {mode: "unsafe-ignore-cors"}
|
||||
|
||||
try {
|
||||
console.log('using mixFetch...');
|
||||
@@ -200,7 +201,7 @@ async function testMixFetch() {
|
||||
|
||||
console.log('done')
|
||||
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.error("mix fetch request failure: ", e)
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ async function loadGoWasm() {
|
||||
goWasm = wasmObj.instance
|
||||
go.run(goWasm)
|
||||
} else {
|
||||
const bytes = await resp.arrayBuffer()
|
||||
const bytes = await resp.arrayBuffer()
|
||||
const wasmObj = await WebAssembly.instantiate(bytes, go.importObject)
|
||||
goWasm = wasmObj.instance
|
||||
go.run(goWasm)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,18 +9,20 @@ use crate::request_writer::RequestWriter;
|
||||
use crate::socks_helpers::{socks5_connect_request, socks5_data_request};
|
||||
use crate::{config, RequestId};
|
||||
use js_sys::Promise;
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_socks5_requests::RemoteAddress;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use tokio::sync::Mutex;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::future_to_promise;
|
||||
use wasm_client_core::client::base_client::storage::GatewaysDetailsStore;
|
||||
use wasm_client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput};
|
||||
use wasm_client_core::client::inbound_messages::InputMessage;
|
||||
use wasm_client_core::helpers::setup_gateway_from_api;
|
||||
use wasm_client_core::init::types::GatewaySetup;
|
||||
use wasm_client_core::helpers::{add_gateway, generate_new_client_keys};
|
||||
use wasm_client_core::nym_task::connections::TransmissionLane;
|
||||
use wasm_client_core::nym_task::TaskManager;
|
||||
use wasm_client_core::storage::core_client_traits::FullWasmClientStorage;
|
||||
use wasm_client_core::storage::wasm_client_traits::WasmClientStorage;
|
||||
use wasm_client_core::storage::ClientStorage;
|
||||
use wasm_client_core::{IdentityKey, QueryReqwestRpcNyxdClient, Recipient};
|
||||
use wasm_utils::console_log;
|
||||
@@ -46,6 +48,7 @@ pub struct MixFetchClient {
|
||||
pub struct MixFetchClientBuilder {
|
||||
config: MixFetchConfig,
|
||||
preferred_gateway: Option<IdentityKey>,
|
||||
latency_based_selection: Option<bool>,
|
||||
force_tls: bool,
|
||||
|
||||
storage_passphrase: Option<String>,
|
||||
@@ -63,6 +66,7 @@ impl MixFetchClientBuilder {
|
||||
MixFetchClientBuilder {
|
||||
config,
|
||||
preferred_gateway,
|
||||
latency_based_selection: None,
|
||||
force_tls,
|
||||
storage_passphrase,
|
||||
}
|
||||
@@ -79,6 +83,51 @@ impl MixFetchClientBuilder {
|
||||
RequestWriter::new(client_output, requests).start()
|
||||
}
|
||||
|
||||
async fn initialise_client_storage(&mut self) -> Result<ClientStorage, MixFetchError> {
|
||||
let client_store =
|
||||
ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take())
|
||||
.await?;
|
||||
if !client_store.has_identity_key().await? {
|
||||
console_log!(
|
||||
"no prior keys found - a new set will be generated for client {}",
|
||||
self.config.base.client.id
|
||||
);
|
||||
generate_new_client_keys(&client_store).await?;
|
||||
}
|
||||
|
||||
Ok(client_store)
|
||||
}
|
||||
|
||||
async fn try_set_preferred_gateway(
|
||||
&self,
|
||||
client_store: &ClientStorage,
|
||||
) -> Result<bool, MixFetchError> {
|
||||
let Some(preferred) = self.preferred_gateway.as_ref() else {
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
if client_store
|
||||
.has_gateway_details(&preferred.to_string())
|
||||
.await?
|
||||
{
|
||||
GatewaysDetailsStore::set_active_gateway(client_store, &preferred.to_string()).await?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
async fn has_active_gateway(
|
||||
&self,
|
||||
client_store: &ClientStorage,
|
||||
) -> Result<bool, MixFetchError> {
|
||||
Ok(client_store
|
||||
.get_active_gateway_id()
|
||||
.await?
|
||||
.active_gateway_id_bs58
|
||||
.is_some())
|
||||
}
|
||||
|
||||
// TODO: combine with normal wasm client
|
||||
async fn start_client_async(mut self) -> Result<MixFetchClient, MixFetchError> {
|
||||
console_log!("Starting the mix fetch client");
|
||||
@@ -89,34 +138,40 @@ impl MixFetchClientBuilder {
|
||||
}
|
||||
goWasmSetMixFetchRequestTimeout(timeout_ms as u32);
|
||||
|
||||
let nym_api_endpoints = self.config.base.client.nym_api_urls.clone();
|
||||
// TODO: resolve this properly
|
||||
self.config.base.debug.topology.ignore_egress_epoch_role = true;
|
||||
|
||||
// TODO: this will have to be re-used for surbs. but this is a problem for another PR.
|
||||
let client_store =
|
||||
ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take())
|
||||
.await?;
|
||||
let client_store = self.initialise_client_storage().await?;
|
||||
|
||||
let user_chosen = self.preferred_gateway.clone();
|
||||
let init_res = setup_gateway_from_api(
|
||||
&client_store,
|
||||
self.force_tls,
|
||||
user_chosen,
|
||||
&nym_api_endpoints,
|
||||
self.config.base.debug.topology.minimum_gateway_performance,
|
||||
)
|
||||
.await?;
|
||||
// if we don't have an active gateway (i.e. no gateways), add one
|
||||
// otherwise, see if we set a preferred gateway and attempt to set its details as active
|
||||
if !self.has_active_gateway(&client_store).await?
|
||||
|| !self.try_set_preferred_gateway(&client_store).await?
|
||||
{
|
||||
add_gateway(
|
||||
self.preferred_gateway.clone(),
|
||||
self.latency_based_selection,
|
||||
self.force_tls,
|
||||
&self.config.base.client.nym_api_urls,
|
||||
bin_info!().into(),
|
||||
self.config.base.debug.topology.minimum_gateway_performance,
|
||||
&client_store,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let storage = Self::initialise_storage(&self.config, client_store);
|
||||
|
||||
let mut base_builder = BaseClientBuilder::<QueryReqwestRpcNyxdClient, _>::new(
|
||||
let base_builder = BaseClientBuilder::<QueryReqwestRpcNyxdClient, _>::new(
|
||||
&self.config.base,
|
||||
storage,
|
||||
None,
|
||||
);
|
||||
|
||||
if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) {
|
||||
base_builder = base_builder.with_gateway_setup(reuse_setup);
|
||||
}
|
||||
// if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) {
|
||||
// base_builder = base_builder.with_gateway_setup(reuse_setup);
|
||||
// }
|
||||
let mut started_client = base_builder.start_base().await?;
|
||||
|
||||
let self_address = started_client.address;
|
||||
|
||||
@@ -35,4 +35,6 @@ pub fn main() {
|
||||
"mix fetch version used: {}",
|
||||
nym_bin_common::bin_info_owned!()
|
||||
);
|
||||
wasm_utils::console_log!("[rust main]: setting panic hook");
|
||||
wasm_utils::set_panic_hook();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user