Compare commits

..

19 Commits

Author SHA1 Message Date
Andrej Mihajlov 81e72ba61b Add shutdown event handle 2025-10-14 20:01:47 +02:00
Jędrzej Stuczyński 0e3ffb749e using same hierarchy of trackers for client shutdown control 2025-10-14 13:13:39 +03:00
Bogdan-Ștefan Neacşu bd2e6ee812 Signal shutdown when gateway is considered unreachable 2025-10-14 12:12:16 +03:00
mfahampshire 9856198356 Patch for operators to open wg metadata port (#6106) 2025-10-13 14:47:43 +00:00
Jędrzej Stuczyński 5c33846e57 bugfix: use custom topology provider for list of init gateways (#6092) 2025-10-13 12:01:51 +01:00
Jędrzej Stuczyński 5d45544c27 bugfix: include network name in the default gateway probe config path (#6100) 2025-10-13 10:05:54 +01:00
Jędrzej Stuczyński aa6a79cb3e feat: expose obtaining reference to Mnemonic from DirectSecp256k1HdWallet (#6083)
* feat: expose obtaining reference to Mnemonic from DirectSecp256k1HdWallet

* updated getters for stringified mnemonic
2025-10-13 09:22:15 +01:00
Georgio Nicolas b3a940770a Merge pull request #5919 from nymtech/georgio/dkg-fixes
Additional DKG Fixes
2025-10-10 17:47:11 +02:00
Mark Sinclair e980f76a81 ns-api: add descriptions to dVPN gateway responses (#6102)
* ns-api: add descriptions to dVPN gateway responses

* clippy

* fmt

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2025-10-10 15:40:18 +01:00
import this 9b38fef28f [DOCs/operators] QUIC deployment script & docs (#6098)
* add quic_bridge_deployment.sh

* create a snippet with quick install steps

* add quic deployment to changelog

* add quic deployment to node config page

* add version compatibility callout

* last edits and scraped stats update

* correct name of QUIC snippet

* fix naming

* fix naming

* re-run python-prebuild.sh aka time-now updated

* attempt to fix vercel build the hard way

* rerun npm

* build with pnpm

* restore lock file and rebuild w pnpm

* chore: update pnpm lockfile

* attempt to fix build

* attempt to fix runtime builds

* update ci-docs run OS
2025-10-10 14:38:37 +00:00
Mark Sinclair 43910ca635 Update ci-docs.yml 2025-10-10 15:00:25 +01:00
Mark Sinclair d3ccd7575a NS API: use new probe download filesize and milliseconds field (#6097)
* use milliseconds field

* change score thresholds

* bump to version 4.0.8

* NS API: adjust score categories (#6103)

* testing scores

* test version

* Update Cargo.toml

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
Co-authored-by: benedetta davico <46782255+benedettadavico@users.noreply.github.com>
2025-10-10 14:47:36 +01:00
Georgio Nicolas bb06a1b7a8 Another offering for Clippy 2025-09-12 20:34:50 +02:00
Georgio Nicolas e783a5fced Offerings for clippy 2025-09-12 20:28:49 +02:00
Georgio Nicolas 8a24b45b5d Precompute BSGS table 2025-09-12 20:21:57 +02:00
Georgio Nicolas 10e4eba727 Use LazyLock to precompute generators 2025-08-08 19:14:37 +02:00
Georgio Nicolas 8ebf482f36 Fix clippy suggestion 2025-07-29 16:33:25 +02:00
Georgio Nicolas 6940ca427e Fix zeroization 2025-07-29 15:42:23 +02:00
Georgio Nicolas 24f877fda5 replace unsafe static values by function calls 2025-07-29 15:04:11 +02:00
42 changed files with 1475 additions and 329 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
build:
runs-on: arc-ubuntu-22.04
runs-on: arc-linux-latest
env:
RUSTUP_PERMIT_COPY_RENAME: 1
defaults:
Generated
+1 -2
View File
@@ -5746,7 +5746,6 @@ dependencies = [
"criterion",
"ff",
"group",
"lazy_static",
"nym-contracts-common",
"nym-pemstore",
"rand 0.8.5",
@@ -6598,7 +6597,7 @@ dependencies = [
[[package]]
name = "nym-node-status-api"
version = "4.0.7"
version = "4.0.9"
dependencies = [
"ammonia",
"anyhow",
@@ -341,14 +341,8 @@ where
debug_config.cover_traffic,
stats_tx,
);
let drop_guard = shutdown_tracker.clone_shutdown_token().drop_guard();
shutdown_tracker.try_spawn_named_with_shutdown(
async move {
let _ = drop_guard;
stream.run().await
},
"CoverTrafficStream",
);
shutdown_tracker
.try_spawn_named_with_shutdown(async move { stream.run().await }, "CoverTrafficStream");
}
#[allow(clippy::too_many_arguments)]
@@ -425,10 +419,8 @@ where
"AcknowledgementController::RetransmissionRequestListener",
);
let drop_guard = shutdown_tracker.clone_shutdown_token().drop_guard();
shutdown_tracker.try_spawn_named_with_shutdown(
async move {
let _ = drop_guard;
sent_notification_listener.run().await;
},
"AcknowledgementController::SentNotificationListener",
@@ -439,6 +431,8 @@ where
async move { ack_action_controller.run(shutdown_token).await },
"AcknowledgementController::ActionController",
);
// .start(packet_type);
}
// buffer controlling all messages fetched from provider
@@ -711,12 +705,8 @@ where
// don't spawn the refresher if we don't want to be refreshing the topology.
// only use the initial values obtained
info!("Starting topology refresher...");
let drop_guard = shutdown_tracker.clone_shutdown_token().drop_guard();
shutdown_tracker.try_spawn_named_with_shutdown(
async move {
let _ = drop_guard;
topology_refresher.run().await
},
async move { topology_refresher.run().await },
"TopologyRefresher",
);
}
@@ -936,7 +926,7 @@ where
self.user_agent.clone(),
generate_client_stats_id(*self_address.identity()),
input_sender.clone(),
&shutdown_tracker,
&shutdown_tracker.clone(),
);
// needs to be started as the first thing to block if required waiting for the gateway
@@ -946,7 +936,7 @@ where
shared_topology_accessor.clone(),
self_address.gateway(),
self.wait_for_gateway,
&shutdown_tracker,
&shutdown_tracker.clone(),
)
.await?;
@@ -966,7 +956,7 @@ where
stats_reporter.clone(),
#[cfg(unix)]
self.connection_fd_callback,
&shutdown_tracker,
&shutdown_tracker.clone(),
)
.await?;
let gateway_ws_fd = gateway_transceiver.ws_fd();
@@ -974,7 +964,7 @@ where
let reply_storage = Self::setup_persistent_reply_storage(
reply_storage_backend,
key_rotation_config,
&shutdown_tracker,
&shutdown_tracker.clone(),
)
.await?;
@@ -985,7 +975,7 @@ where
reply_storage.key_storage(),
reply_controller_sender.clone(),
stats_reporter.clone(),
&shutdown_tracker,
&shutdown_tracker.clone(),
);
// The message_sender is the transmitter for any component generating sphinx packets
@@ -994,7 +984,7 @@ where
// The MixTrafficController then sends the actual traffic
let (message_sender, client_request_sender) =
Self::start_mix_traffic_controller(gateway_transceiver, &shutdown_tracker);
Self::start_mix_traffic_controller(gateway_transceiver, &shutdown_tracker.clone());
// Channels that the websocket listener can use to signal downstream to the real traffic
// controller that connections are closed.
@@ -1023,7 +1013,7 @@ where
shared_lane_queue_lengths.clone(),
client_connection_rx,
stats_reporter.clone(),
&shutdown_tracker,
&shutdown_tracker.clone(),
);
if !self
@@ -1039,7 +1029,7 @@ where
shared_topology_accessor.clone(),
message_sender,
stats_reporter.clone(),
&shutdown_tracker,
&shutdown_tracker.clone(),
);
}
@@ -138,7 +138,6 @@ impl MixTrafficController {
pub async fn run(&mut self) {
debug!("Started MixTrafficController with graceful shutdown support");
let _drop_guard = self.shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -156,6 +155,7 @@ impl MixTrafficController {
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
// Do we need to handle the embedded mixnet client case
// separately?
self.shutdown_token.cancel();
break;
}
}
@@ -80,7 +80,6 @@ impl AcknowledgementListener {
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
debug!("Started AcknowledgementListener with graceful shutdown support");
let _drop_guard = shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -245,7 +245,6 @@ impl ActionController {
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
debug!("Started ActionController with graceful shutdown support");
let _drop_guard = shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -216,7 +216,6 @@ where
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
debug!("Started InputMessageListener with graceful shutdown support");
let _drop_guard = shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -167,7 +167,6 @@ where
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
debug!("Started RetransmissionRequestListener with graceful shutdown support");
let _drop_guard = shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -585,7 +585,6 @@ where
// avoid borrow on self
let shutdown_token = self.shutdown_token.clone();
let _drop_guard = shutdown_token.clone().drop_guard();
#[cfg(not(target_arch = "wasm32"))]
{
let mut status_timer = tokio::time::interval(Duration::from_secs(5));
@@ -497,8 +497,6 @@ impl<R: MessageReceiver> RequestReceiver<R> {
pub(crate) async fn run(&mut self) {
debug!("Started RequestReceiver with graceful shutdown support");
let _drop_guard = self.shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -542,8 +540,6 @@ impl<R: MessageReceiver> FragmentedMessageReceiver<R> {
pub(crate) async fn run(&mut self) -> Result<(), MessageRecoveryError> {
debug!("Started FragmentedMessageReceiver with graceful shutdown support");
let _drop_guard = self.shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -152,7 +152,6 @@ where
let polling_rate = self.config.key_rotation.epoch_duration / 8;
let mut invalidation_inspection = new_interval_stream(polling_rate);
let _drop_guard = shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -119,8 +119,6 @@ impl StatisticsControl {
let mut snapshot_interval =
gloo_timers::future::IntervalStream::new(SNAPSHOT_INTERVAL.as_millis() as u32);
let _drop_guard = shutdown_token.clone().drop_guard();
loop {
tokio::select! {
biased;
@@ -46,7 +46,6 @@ where
debug!("Started PersistentReplyStorage");
if let Err(err) = self.backend.start_storage_session().await {
shutdown.cancel();
error!("failed to start the storage session - {err}");
return;
}
@@ -89,8 +89,6 @@ impl PartiallyDelegatedRouter {
async fn run(mut self, mut split_stream: SplitStream<WsConn>, shutdown_token: ShutdownToken) {
let mut chunked_stream = (&mut split_stream).ready_chunks(8);
let drop_guard = shutdown_token.clone().drop_guard();
let ret: Result<_, GatewayClientError> = loop {
tokio::select! {
biased;
@@ -103,7 +101,6 @@ impl PartiallyDelegatedRouter {
// received request to stop the task and return the stream
_ = &mut self.stream_return_requester => {
log::debug!("received request to return the split ws stream");
drop_guard.disarm();
break Ok(())
}
socket_msgs = chunked_stream.next() => {
@@ -10,7 +10,7 @@ use cosmrs::tx;
use cosmrs::tx::SignDoc;
use nym_config::defaults;
use thiserror::Error;
use zeroize::{Zeroize, ZeroizeOnDrop};
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
type Secp256k1Keypair = (SigningKey, PublicKey);
@@ -128,9 +128,20 @@ impl DirectSecp256k1HdWallet {
Ok(accounts)
}
pub fn secret(&self) -> &bip39::Mnemonic {
&self.secret
}
#[deprecated(
note = "use either .secret() for obtaining &bip39::Mnemonic or .mnemonic_string() for Zeroizing wrapper around the String"
)]
pub fn mnemonic(&self) -> String {
self.secret.to_string()
}
pub fn mnemonic_string(&self) -> Zeroizing<String> {
Zeroizing::new(self.secret.to_string())
}
}
#[must_use]
@@ -18,6 +18,6 @@ pub fn create_account(args: Args, prefix: &str) {
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
// Output address and mnemonics into separate lines for easier parsing
println!("{}", wallet.mnemonic());
println!("{}", wallet.mnemonic_string().as_str());
println!("{}", wallet.try_derive_accounts().unwrap()[0].address());
}
-1
View File
@@ -17,7 +17,6 @@ nym-contracts-common = { path = "../cosmwasm-smart-contracts/contracts-common",
bs58 = { workspace = true }
lazy_static = { workspace = true }
rand = { workspace = true }
rand_chacha = { workspace = true }
rand_core = { workspace = true }
+16 -41
View File
@@ -13,9 +13,9 @@ use rand::CryptoRng;
use rand_core::RngCore;
use std::collections::HashMap;
use std::ops::Neg;
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct Ciphertexts {
pub rr: [G1Projective; NUM_CHUNKS],
pub ss: [G1Projective; NUM_CHUNKS],
@@ -164,8 +164,7 @@ impl Ciphertexts {
}
}
#[derive(Zeroize)]
#[zeroize(drop)]
#[derive(Zeroize, ZeroizeOnDrop)]
/// Randomness generated during ciphertext generation that is required for proofs of knowledge.
///
/// It must be handled with extreme care as its misuse might help malicious parties to recover
@@ -399,7 +398,7 @@ pub fn baby_step_giant_step(
#[cfg(test)]
mod tests {
use super::*;
use crate::bte::{keygen, setup, DEFAULT_BSGS_TABLE};
use crate::bte::{keygen, setup, BSGS_TABLE};
use rand_core::SeedableRng;
fn verify_hazmat_rand(ciphertext: &Ciphertexts, randomness: &HazmatRandomness) {
@@ -457,8 +456,6 @@ mod tests {
let (decryption_key1, public_key1) = keygen(&params, &mut rng);
let (decryption_key2, public_key2) = keygen(&params, &mut rng);
let lookup_table = &DEFAULT_BSGS_TABLE;
for _ in 0..10 {
let m1 = Share::random(&mut rng);
let m2 = Share::random(&mut rng);
@@ -467,22 +464,12 @@ mod tests {
let (ciphertext, hazmat) = encrypt_shares(shares, &params, &mut rng);
verify_hazmat_rand(&ciphertext, &hazmat);
let recovered1 = decrypt_share(
&params,
&decryption_key1,
0,
&ciphertext,
Some(lookup_table),
)
.unwrap();
let recovered2 = decrypt_share(
&params,
&decryption_key2,
1,
&ciphertext,
Some(lookup_table),
)
.unwrap();
let recovered1 =
decrypt_share(&params, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE))
.unwrap();
let recovered2 =
decrypt_share(&params, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE))
.unwrap();
assert_eq!(m1, recovered1);
assert_eq!(m2, recovered2);
}
@@ -498,8 +485,6 @@ mod tests {
let (decryption_key1, public_key1) = keygen(&params, &mut rng);
let (decryption_key2, public_key2) = keygen(&params, &mut rng);
let lookup_table = &DEFAULT_BSGS_TABLE;
for _ in 0..10 {
let m1 = Share::random(&mut rng);
let m2 = Share::random(&mut rng);
@@ -508,22 +493,12 @@ mod tests {
let (ciphertext, hazmat) = encrypt_shares(shares, &params, &mut rng);
verify_hazmat_rand(&ciphertext, &hazmat);
let recovered1 = decrypt_share(
&params,
&decryption_key1,
0,
&ciphertext,
Some(lookup_table),
)
.unwrap();
let recovered2 = decrypt_share(
&params,
&decryption_key2,
1,
&ciphertext,
Some(lookup_table),
)
.unwrap();
let recovered1 =
decrypt_share(&params, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE))
.unwrap();
let recovered2 =
decrypt_share(&params, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE))
.unwrap();
assert_eq!(m1, recovered1);
assert_eq!(m2, recovered2);
}
+5 -5
View File
@@ -11,7 +11,7 @@ use group::GroupEncoding;
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
use rand::CryptoRng;
use rand_core::RngCore;
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
// produces public key and a decryption key for the root of the tree
pub fn keygen(
@@ -48,7 +48,7 @@ pub fn keygen(
(dk, key_with_proof)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Zeroize)]
pub struct PublicKey(pub(crate) G1Projective);
impl PublicKey {
@@ -57,7 +57,7 @@ impl PublicKey {
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct PublicKeyWithProof {
pub(crate) key: PublicKey,
pub(crate) proof: ProofOfDiscreteLog,
@@ -136,8 +136,7 @@ impl PublicKeyWithProof {
}
}
#[derive(Debug, Zeroize)]
#[zeroize(drop)]
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct DecryptionKey {
// g1^rho
@@ -242,6 +241,7 @@ impl DecryptionKey {
}
}
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct KeyPair {
pub(crate) private_key: DecryptionKey,
pub(crate) public_key: PublicKeyWithProof,
+9 -9
View File
@@ -1,11 +1,13 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::sync::LazyLock;
use crate::bte::encryption::BabyStepGiantStepLookup;
use crate::utils::hash_g2;
use crate::{Chunk, Share};
use bls12_381::{G1Affine, G2Affine, G2Prepared, G2Projective, Gt};
use group::Curve;
use lazy_static::lazy_static;
pub mod encryption;
pub mod keys;
@@ -16,14 +18,12 @@ pub mod proof_sharing;
pub use encryption::{decrypt_share, encrypt_shares, Ciphertexts};
pub use keys::{keygen, DecryptionKey, PublicKey, PublicKeyWithProof};
lazy_static! {
pub(crate) static ref PAIRING_BASE: Gt =
bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator());
pub(crate) static ref G2_GENERATOR_PREPARED: G2Prepared =
G2Prepared::from(G2Affine::generator());
pub(crate) static ref DEFAULT_BSGS_TABLE: encryption::BabyStepGiantStepLookup =
encryption::BabyStepGiantStepLookup::default();
}
pub(crate) static PAIRING_BASE: LazyLock<Gt> =
LazyLock::new(|| bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator()));
pub(crate) static G2_GENERATOR_PREPARED: LazyLock<G2Prepared> =
LazyLock::new(|| G2Prepared::from(G2Affine::generator()));
pub static BSGS_TABLE: LazyLock<BabyStepGiantStepLookup> =
LazyLock::new(BabyStepGiantStepLookup::default);
// Domain tries to follow guidelines specified by:
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
+2 -1
View File
@@ -12,6 +12,7 @@ use ff::Field;
use group::{Group, GroupEncoding};
use rand::{CryptoRng, Rng};
use rand_core::{RngCore, SeedableRng};
use zeroize::{Zeroize, ZeroizeOnDrop};
const CHUNKING_ORACLE_DOMAIN: &[u8] =
b"NYM_COCONUT_NIDKG_V01_CS01_SHA-256_CHACHA20_CHUNKING_ORACLE";
@@ -67,7 +68,7 @@ impl<'a> Instance<'a> {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct ProofOfChunking {
y0: G1Projective,
bb: Vec<G1Projective>,
+5 -5
View File
@@ -7,14 +7,14 @@ use ff::Field;
use group::GroupEncoding;
use rand::CryptoRng;
use rand_core::RngCore;
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
// Domain tries to follow guidelines specified by:
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
const DISCRETE_LOG_DOMAIN: &[u8] =
b"NYM_COCONUT_NIDKG_V01_CS01_WITH_BLS12381_XMD:SHA-256_SSWU_RO_PROOF_DISCRETE_LOG";
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct ProofOfDiscreteLog {
pub(crate) rand_commitment: G1Projective,
pub(crate) response: Scalar,
@@ -52,9 +52,9 @@ impl ProofOfDiscreteLog {
let public_bytes = public.to_bytes();
let rand_commit_bytes = rand_commit.to_bytes();
let mut bytes = Vec::with_capacity(96);
bytes.extend_from_slice(public_bytes.as_ref());
bytes.extend_from_slice(rand_commit_bytes.as_ref());
let mut bytes = [0u8; 96];
bytes[0..48].copy_from_slice(public_bytes.as_ref());
bytes[48..96].copy_from_slice(rand_commit_bytes.as_ref());
hash_to_scalar(bytes, DISCRETE_LOG_DOMAIN)
}
+2 -1
View File
@@ -12,6 +12,7 @@ use group::GroupEncoding;
use rand::CryptoRng;
use rand_core::RngCore;
use std::collections::BTreeMap;
use zeroize::{Zeroize, ZeroizeOnDrop};
// Domain tries to follow guidelines specified by:
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
@@ -77,7 +78,7 @@ impl<'a> Instance<'a> {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct ProofOfSecretSharing {
ff: G1Projective,
aa: G2Projective,
+2 -2
View File
@@ -18,7 +18,7 @@ use rand_core::RngCore;
use std::collections::BTreeMap;
use zeroize::Zeroize;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Zeroize)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct RecoveredVerificationKeys {
pub recovered_master: G2Projective,
@@ -83,7 +83,7 @@ impl RecoveredVerificationKeys {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Zeroize)]
pub struct Dealing {
pub public_coefficients: PublicCoefficients,
pub ciphertexts: Ciphertexts,
+3 -4
View File
@@ -9,9 +9,9 @@ use group::GroupEncoding;
use rand::CryptoRng;
use rand_core::RngCore;
use std::ops::{Add, Index, IndexMut};
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct PublicCoefficients {
pub(crate) coefficients: Vec<G2Projective>,
}
@@ -111,8 +111,7 @@ impl IndexMut<usize> for PublicCoefficients {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Zeroize)]
#[zeroize(drop)]
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub struct Polynomial {
coefficients: Vec<Scalar>,
}
+3 -5
View File
@@ -6,14 +6,13 @@ use crate::error::DkgError;
use crate::interpolation::perform_lagrangian_interpolation_at_origin;
use crate::NodeIndex;
use bls12_381::Scalar;
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
// if this type is changed, one must ensure all values can fit in it
pub type Chunk = u16;
#[derive(PartialEq, Eq, Debug, Zeroize)]
#[derive(PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
#[cfg_attr(test, derive(Clone))]
#[zeroize(drop)]
pub struct Share(pub(crate) Scalar);
pub fn combine_shares(shares: Vec<Share>, node_indices: &[NodeIndex]) -> Result<Scalar, DkgError> {
@@ -66,9 +65,8 @@ impl From<Scalar> for Share {
}
}
#[derive(Default, Zeroize)]
#[derive(Default, Zeroize, ZeroizeOnDrop)]
#[cfg_attr(test, derive(Clone))]
#[zeroize(drop)]
pub(crate) struct ChunkedShare {
pub(crate) chunks: [Chunk; NUM_CHUNKS],
}
@@ -11,6 +11,7 @@ import { Alert, AlertTitle } from '@mui/material';
import { Wallet } from '@cosmos-kit/core';
import { CosmosKitLedger } from './ledger';
import { CosmosKitSign } from './sign';
import type { SignerOptions } from '@cosmos-kit/core';
const CosmosKitSetup: FC<{ children: React.ReactNode }> = ({ children }) => {
const assetsFixedUp = React.useMemo(() => {
@@ -40,14 +41,16 @@ const CosmosKitSetup: FC<{ children: React.ReactNode }> = ({ children }) => {
return chains;
}, [chains]);
// components/cosmos-kit/index.tsx
return (
<ChainProvider
chains={chainsFixedUp}
assetLists={assetsFixedUp}
wallets={[...ledger, ...keplr]}
signerOptions={{
preferredSignType: () => 'amino',
}}
signerOptions={{ preferredSignType: () => 'amino' }}
throwErrors={false}
>
{children}
</ChainProvider>
@@ -0,0 +1,141 @@
import { Steps } from 'nextra/components';
import { Callout } from 'nextra/components';
import { AccordionTemplate } from 'components/accordion-template.tsx';
<Callout type="info" emoji="️">
**QUIC bridge is a requirement for all nodes which enable Wireguard functionality. Note that it this feature is compatible with nodes from `v1.18.0` (platform release [`v2025.17-isabirra`](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.17-isabirra)) and newer!**
</ Callout>
Nym Network uses various [transport bridges](https://github.com/nymtech/nym-bridges/blob/main/README.md) for routing the packets. Right now operators need to configure [our implementation](https://github.com/nymtech/nym-bridges/tree/main/nym-bridge) of general-purpose transport layer network protocol called [QUIC](https://en.wikipedia.org/wiki/QUIC).
Operators can use [Nym Bridge Configuration Tool](https://github.com/nymtech/nym-bridges/tree/main/bridge-cfg) and compile the [Bridge Runner binary](https://github.com/nymtech/nym-bridges/tree/main/nym-bridge) themselves.
**We recommend a more convenient QUIC bridge deployment using a script [`quic_bridge_deployment.sh`](https://github.com/nymtech/nym/blob/develop/scripts/nym-node-setup/quic_bridge_deployment.sh), following the steps below.**
<Steps>
###### 1. Download [`quic_bridge_deployment.sh`](https://github.com/nymtech/nym/blob/develop/scripts/nym-node-setup/quic_bridge_deployment.sh) script
- SSH to your server
- Download the script and make executable
```sh
wget https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/quic_bridge_deployment.sh && \
chmod +x quic_bridge_deployment.sh
```
###### 2. Run the script with `full_bridge_setup` command
- Optional: open `tmux` in case you will need to run another commands on the VPS
- Run the script with a command `full_bridge_setup`
```sh
./nym-node-setup/quic_bridge_deployment.sh full_bridge_setup
```
###### 3. Follow the interactive prompts
- When you are asked for bridge binary URL, look here for one to match your system: [builds.ci.nymte.ch/QUIC](https://builds.ci.nymte.ch/QUIC/)
- When you are asked to enter forward address, it's your IPv4 used for bonding the node, alongside port `:51822` (an example: `172.232.238.161:51822`)
- To find out your IP address you can always run:
- IPv4: `curl -4 https://ifconfig.co/ip`
- IPv6: `curl -6 https://ifconfig.co/ip`
- **For all prompts with default options, we highly recommend to stick to default (press enter)**
###### 4. Restart the node service
- When done with the deployment, please restart your node systemd service
```sh
service nym-node restart && journalctl -u nym-node.service -f --all
```
</Steps>
Congratulation, you deployed QUIC transport bridge! The script offers a standalone tweaks and checks, you can always run it without any argument to see all the options:
```sh
./quic_bridge_deployment.sh
```
<br/>
<AccordionTemplate name="Command output">
```shell
root@localhost:~# ./quic_bridge_deployment.sh
iptables-persistent is already installed.
Usage: ./quic_bridge_deployment.sh [command] [options]
Nym QUIC Bridge Deployment Helper Script
Bridge Installation & Configuration:
check_bridge_installation - Check bridge installation status
show_bridge_config - Display bridge configuration files
show_bridge_keys - Display bridge key information
show_bridge_info - Show comprehensive bridge information
verify_bridge_prerequisites - Verify all prerequisites are met
Bridge Setup Commands:
install_bridge_binary - Download and install nym-bridge binary
generate_bridge_keys - Generate ED25519 bridge identity keys
create_client_params - Create client_bridge_params.json
create_bridge_config - Create bridges.toml configuration
create_bridge_service - Create systemd service file
full_bridge_setup - Interactive full bridge setup wizard
Network Configuration Commands:
adjust_ip_forwarding - Enable IPv4 and IPv6 forwarding
apply_bridge_iptables_rules - Apply iptables rules for QUIC bridge (nymwg)
configure_dns_and_icmp - Allow ICMP ping tests and configure DNS
remove_duplicate_bridge_rules - Remove duplicate iptables rules for nymwg
Network Inspection Commands:
fetch_and_display_ipv6 - Show IPv6 on default network device
fetch_wg_ipv6_address - Fetch IPv6 for nymwg interface
check_bridge_iptables - Check iptables rules for nymwg
check_ipv6_ipv4_forwarding - Check IPv4 and IPv6 forwarding status
check_ip_routing - Display IP routing tables
Testing Commands:
perform_pings - Test IPv4 and IPv6 connectivity
test_bridge_connectivity - Comprehensive bridge connectivity test
Service Management Commands:
check_bridge_service_status - Check nym-bridge and nym-node service status
show_bridge_logs [lines] - Show recent nym-bridge logs (default: 50 lines)
Quick Start:
1. Run 'verify_bridge_prerequisites' to check prerequisites
2. Run 'check_bridge_installation' to verify installation
3. Run 'test_bridge_connectivity' to test connectivity
```
</AccordionTemplate>
### Fixing Metadata Port Showing Not Open in Probe Results
If you have followed the steps outlined above, but the metadata port is not shown as open in either the Node Status API's probe results or an explorer that gets its data from the API, see below:
<Steps>
###### 1.
Ensure that in your `config.toml` file, this value is set to the default one - any other value here will cause the metadata endpoint to fail:
```
# Private IP address of the wireguard gateway.
# default: '10.1.0.1'
private_ipv4 = '10.1.0.1'
```
Then restart your node.
###### 2.
Run this command if not already done:
```
ufw allow in on nymwg to any port 51830 proto tcp
```
Check if the port is open with:
```
iptables -S | grep 51830
```
Then ensure the metadata endpoint is listening from the correct address with:
```
netstat -an | egrep LISTEN | egrep "51830"
```
###### 3.
Once the Node Status API has run a probe on your node, the probe results will reflect this - `can_query_metadata_v4` will have `true` as a value.
The quickest way to check this is by using the [NymVPN API](https://nymvpn.com/api/public/v1/directory/gateways?show_vpn_only=true) and checking the same field:
![](/images/operators/wg-metadata-port-api.png)
</Steps>
@@ -1 +1 @@
Sunday, October 5th 2025, 09:29:02 UTC
Monday, October 13th 2025, 13:24:56 UTC
+6 -3
View File
@@ -24,11 +24,11 @@
"@cosmjs/encoding": "^0.32.2",
"@cosmjs/proto-signing": "^0.32.2",
"@cosmjs/stargate": "^0.32.2",
"@cosmos-kit/core": "^2.8.9",
"@cosmos-kit/core": "^2.16.3",
"@cosmos-kit/keplr": "^2.6.9",
"@cosmos-kit/keplr-extension": "^2.7.9",
"@cosmos-kit/ledger": "^2.6.9",
"@cosmos-kit/react": "^2.10.11",
"@cosmos-kit/react": "^2.22.3",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@interchain-ui/react": "^1.8.0",
@@ -54,12 +54,15 @@
"uuid": "^9.0.0"
},
"devDependencies": {
"@next/swc-linux-x64-gnu": "15.5.0",
"@types/node": "18.11.10",
"@types/react": "^18.3.26",
"@types/react-dom": "^18.3.7",
"copy-webpack-plugin": "^11.0.0",
"eslint": "8.46.0",
"eslint-config-next": "13.4.13",
"raw-loader": "^4.0.2",
"typescript": "^4.9.3"
"typescript": "^5.9.3"
},
"private": false
}
@@ -7,6 +7,7 @@ import { AccordionTemplate } from 'components/accordion-template.tsx';
import { Steps } from 'nextra/components';
import AbuseResponse from 'components/operators/templates/dmca_response.md';
import OperatorIntroduction from 'components/operators/templates/provider_introduction.md';
import QuicDeploymentSteps from 'components/operators/snippets/quic-bridge-deployment-script-setup.mdx';
export const TestingSteps = () => (
@@ -48,6 +49,10 @@ This page displays a full list of all the changes during our release cycle from
<VarInfo />
## QUIC Transport Bridge Deployment
<QuicDeploymentSteps />
## `v2025.17-isabirra`
- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.17-isabirra)
@@ -8,6 +8,7 @@ import ExitPolicyStatusOutput from 'components/operators/snippets/wg-exit-policy
import ExitPolicyTestOutput from 'components/operators/snippets/wg-exit-policy-test-output.mdx';
import ExitPolicyTestServer from 'components/operators/snippets/wg-exit-policy-testing-from-server.mdx';
import ExitPolicyTestOutside from 'components/operators/snippets/wg-exit-policy-testing-from-outside.mdx';
import QuicDeploymentSteps from 'components/operators/snippets/quic-bridge-deployment-script-setup.mdx';
export const ManagerIPOutput = () => (
@@ -534,6 +535,9 @@ You can validate the application of the IP tables routes on your `nym-node` by c
Your node has successfully implemented wireguard exit policy with the same routing permissions like [Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) used on 5-hop (Mixnet).
## QUIC Transport Bridge Deployment
<QuicDeploymentSteps />
## Running `nym-node` as a non-root
+208 -152
View File
@@ -36,11 +36,11 @@ importers:
specifier: ^0.32.2
version: 0.32.4
'@cosmos-kit/core':
specifier: ^2.8.9
specifier: ^2.16.3
version: 2.16.3
'@cosmos-kit/keplr':
specifier: ^2.6.9
version: 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)
version: 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)
'@cosmos-kit/keplr-extension':
specifier: ^2.7.9
version: 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(starknet@7.6.4)
@@ -48,38 +48,41 @@ importers:
specifier: ^2.6.9
version: 2.14.3(@cosmjs/amino@0.32.4)(@cosmjs/crypto@0.32.4)(@cosmjs/encoding@0.32.4)(@cosmjs/proto-signing@0.32.4)
'@cosmos-kit/react':
specifier: ^2.10.11
version: 2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
specifier: ^2.22.3
version: 2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@emotion/react':
specifier: ^11.11.1
version: 11.14.0(react@18.3.1)
version: 11.14.0(@types/react@18.3.26)(react@18.3.1)
'@emotion/styled':
specifier: ^11.11.0
version: 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@interchain-ui/react':
specifier: ^1.8.0
version: 1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/icons-material':
specifier: ^5.14.9
version: 5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
version: 5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@mui/lab':
specifier: ^5.0.0-alpha.145
version: 5.0.0-alpha.177(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 5.0.0-alpha.177(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/material':
specifier: ^5.14.8
version: 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/accordion':
specifier: ^2.0.40
version: 2.2.7(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/react':
specifier: ^2.4.8
version: 2.6.11(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)
version: 2.6.11(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)
'@nymproject/contract-clients':
specifier: '>=1.2.4-rc.2 || ^1'
version: 1.4.1
'@nymproject/mix-fetch-full-fat':
specifier: file:../../dist/wasm/mix-fetch
version: '@nymproject/mix-fetch-wasm@file:../../dist/wasm/mix-fetch'
specifier: '>=1.2.4-rc.2 || ^1'
version: 1.2.3
'@nymproject/sdk-full-fat':
specifier: file:../../dist/wasm/client
version: '@nymproject/nym-client-wasm@file:../../dist/wasm/client'
specifier: '>=1.2.4-rc.2 || ^1'
version: 1.2.3
'@redocly/cli':
specifier: ^1.25.15
version: 1.34.5(ajv@8.17.1)
@@ -117,9 +120,18 @@ importers:
specifier: ^9.0.0
version: 9.0.1
devDependencies:
'@next/swc-linux-x64-gnu':
specifier: 15.5.0
version: 15.5.0
'@types/node':
specifier: 18.11.10
version: 18.11.10
'@types/react':
specifier: ^18.3.26
version: 18.3.26
'@types/react-dom':
specifier: ^18.3.7
version: 18.3.7(@types/react@18.3.26)
copy-webpack-plugin:
specifier: ^11.0.0
version: 11.0.0(webpack@5.101.3)
@@ -128,13 +140,13 @@ importers:
version: 8.46.0
eslint-config-next:
specifier: 13.4.13
version: 13.4.13(eslint@8.46.0)(typescript@4.9.5)
version: 13.4.13(eslint@8.46.0)(typescript@5.9.3)
raw-loader:
specifier: ^4.0.2
version: 4.0.2(webpack@5.101.3)
typescript:
specifier: ^4.9.3
version: 4.9.5
specifier: ^5.9.3
version: 5.9.3
packages:
@@ -1664,11 +1676,14 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
'@nymproject/mix-fetch-wasm@file:../../dist/wasm/mix-fetch':
resolution: {directory: ../../dist/wasm/mix-fetch, type: directory}
'@nymproject/contract-clients@1.4.1':
resolution: {integrity: sha512-HuJZ4Hv+Rl6ZZEtCHKgurNLJapM+QQRJlGkevFH2a4UdqUqF9omUkUi3AVes4679dPoSFgvA7plyVSDBdbgV6w==}
'@nymproject/nym-client-wasm@file:../../dist/wasm/client':
resolution: {directory: ../../dist/wasm/client, type: directory}
'@nymproject/mix-fetch-full-fat@1.2.3':
resolution: {integrity: sha512-5yAQhw33LC0cNsyV0Rj+LIa2kvJY+8jsfgOSr1aeKNfQ7dG4fngWkKnGUbPGzhUTJjqgXPTwNVeJSd6hwGim+g==}
'@nymproject/sdk-full-fat@1.2.3':
resolution: {integrity: sha512-lheA1Zk020o2t95FPVZfdUR0aSI52aD0aJQs074fjH16QkoNNEMotzhJGAnsnnczVg3bpddKghNpCLyDOWvg9A==}
'@opentelemetry/api-logs@0.53.0':
resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==}
@@ -2844,13 +2859,18 @@ packages:
'@types/prop-types@15.7.15':
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
'@types/react-dom@18.3.7':
resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
peerDependencies:
'@types/react': ^18.0.0
'@types/react-transition-group@4.4.12':
resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==}
peerDependencies:
'@types/react': '*'
'@types/react@19.1.10':
resolution: {integrity: sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==}
'@types/react@18.3.26':
resolution: {integrity: sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==}
'@types/stylis@4.2.5':
resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==}
@@ -6386,9 +6406,9 @@ packages:
typeforce@1.18.0:
resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==}
typescript@4.9.5:
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
engines: {node: '>=4.2.0'}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
ufo@1.6.1:
@@ -7159,16 +7179,16 @@ snapshots:
- uploadthing
- utf-8-validate
'@cosmos-kit/keplr-mobile@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)':
'@cosmos-kit/keplr-mobile@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)':
dependencies:
'@chain-registry/keplr': 1.74.313
'@cosmjs/amino': 0.32.4
'@cosmjs/proto-signing': 0.32.4
'@cosmos-kit/core': 2.16.3
'@cosmos-kit/keplr-extension': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(starknet@7.6.4)
'@cosmos-kit/walletconnect': 2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@4.9.5)(zod@3.25.76)
'@cosmos-kit/walletconnect': 2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@5.9.3)(zod@3.25.76)
'@keplr-wallet/provider-extension': 0.12.264(starknet@7.6.4)
'@keplr-wallet/wc-client': 0.12.264(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)
'@keplr-wallet/wc-client': 0.12.264(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -7199,10 +7219,10 @@ snapshots:
- utf-8-validate
- zod
'@cosmos-kit/keplr@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)':
'@cosmos-kit/keplr@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)':
dependencies:
'@cosmos-kit/keplr-extension': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(starknet@7.6.4)
'@cosmos-kit/keplr-mobile': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)
'@cosmos-kit/keplr-mobile': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -7270,11 +7290,13 @@ snapshots:
- uploadthing
- utf-8-validate
'@cosmos-kit/react-lite@2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@cosmos-kit/react-lite@2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@chain-registry/types': 0.46.15
'@cosmos-kit/core': 2.16.3
'@dao-dao/cosmiframe': 1.0.0(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)
'@types/react': 18.3.26
'@types/react-dom': 18.3.7(@types/react@18.3.26)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
transitivePeerDependencies:
@@ -7304,13 +7326,15 @@ snapshots:
- uploadthing
- utf-8-validate
'@cosmos-kit/react@2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@cosmos-kit/react@2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@chain-registry/types': 0.46.15
'@cosmos-kit/core': 2.16.3
'@cosmos-kit/react-lite': 2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@interchain-ui/react': 1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@cosmos-kit/react-lite': 2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@interchain-ui/react': 1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@react-icons/all-files': 4.1.0(react@18.3.1)
'@types/react': 18.3.26
'@types/react-dom': 18.3.7(@types/react@18.3.26)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
transitivePeerDependencies:
@@ -7340,14 +7364,14 @@ snapshots:
- uploadthing
- utf-8-validate
'@cosmos-kit/walletconnect@2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@4.9.5)(zod@3.25.76)':
'@cosmos-kit/walletconnect@2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@5.9.3)(zod@3.25.76)':
dependencies:
'@cosmjs/amino': 0.32.4
'@cosmjs/proto-signing': 0.32.4
'@cosmos-kit/core': 2.16.3
'@walletconnect/sign-client': 2.21.8(typescript@4.9.5)(zod@3.25.76)
'@walletconnect/sign-client': 2.21.8(typescript@5.9.3)(zod@3.25.76)
'@walletconnect/types': 2.21.8
'@walletconnect/utils': 2.21.8(typescript@4.9.5)(zod@3.25.76)
'@walletconnect/utils': 2.21.8(typescript@5.9.3)(zod@3.25.76)
events: 3.3.0
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -7436,7 +7460,7 @@ snapshots:
'@emotion/memoize@0.9.0': {}
'@emotion/react@11.14.0(react@18.3.1)':
'@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@emotion/babel-plugin': 11.13.5
@@ -7447,6 +7471,8 @@ snapshots:
'@emotion/weak-memoize': 0.4.0
hoist-non-react-statics: 3.3.2
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.26
transitivePeerDependencies:
- supports-color
@@ -7460,16 +7486,18 @@ snapshots:
'@emotion/sheet@1.4.0': {}
'@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)':
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@emotion/babel-plugin': 11.13.5
'@emotion/is-prop-valid': 1.3.1
'@emotion/react': 11.14.0(react@18.3.1)
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
'@emotion/serialize': 1.3.3
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1)
'@emotion/utils': 1.4.2
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.26
transitivePeerDependencies:
- supports-color
@@ -7702,7 +7730,7 @@ snapshots:
'@img/sharp-win32-x64@0.34.3':
optional: true
'@interchain-ui/react@1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@interchain-ui/react@1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/core': 1.7.3
'@floating-ui/dom': 1.7.3
@@ -7731,7 +7759,7 @@ snapshots:
react-aria: 3.42.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-dom: 18.3.1(react@18.3.1)
react-stately: 3.40.0(react@18.3.1)
zustand: 4.5.7(immer@10.1.1)(react@18.3.1)
zustand: 4.5.7(@types/react@18.3.26)(immer@10.1.1)(react@18.3.1)
transitivePeerDependencies:
- '@types/react'
- babel-plugin-macros
@@ -7864,11 +7892,11 @@ snapshots:
big-integer: 1.6.52
utility-types: 3.11.0
'@keplr-wallet/wc-client@0.12.264(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)':
'@keplr-wallet/wc-client@0.12.264(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)':
dependencies:
'@keplr-wallet/provider': 0.12.264(starknet@7.6.4)
'@keplr-wallet/types': 0.12.264(starknet@7.6.4)
'@walletconnect/sign-client': 2.21.8(typescript@4.9.5)(zod@3.25.76)
'@walletconnect/sign-client': 2.21.8(typescript@5.9.3)(zod@3.25.76)
'@walletconnect/types': 2.21.8
buffer: 6.0.3
deepmerge: 4.3.1
@@ -7938,56 +7966,61 @@ snapshots:
'@mdx-js/react@2.3.0(react@18.3.1)':
dependencies:
'@types/mdx': 2.0.13
'@types/react': 19.1.10
'@types/react': 18.3.26
react: 18.3.1
'@msgpack/msgpack@3.1.2': {}
'@mui/base@5.0.0-beta.40-1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@mui/base@5.0.0-beta.40-1(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@floating-ui/react-dom': 2.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.24
'@mui/utils': 5.17.1(react@18.3.1)
'@mui/types': 7.2.24(@types/react@18.3.26)
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
'@popperjs/core': 2.11.8
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@mui/core-downloads-tracker@5.18.0': {}
'@mui/icons-material@5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/material': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
'@mui/lab@5.0.0-alpha.177(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/base': 5.0.0-beta.40-1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/material': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/system': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.24
'@mui/utils': 5.17.1(react@18.3.1)
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@emotion/react': 11.14.0(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
'@types/react': 18.3.26
'@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@mui/core-downloads-tracker@5.18.0': {}
'@mui/icons-material@5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.26
'@mui/lab@5.0.0-alpha.177(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/base': 5.0.0-beta.40-1(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@mui/types': 7.2.24(@types/react@18.3.26)
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@types/react': 18.3.26
'@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/core-downloads-tracker': 5.18.0
'@mui/system': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.24
'@mui/utils': 5.17.1(react@18.3.1)
'@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@mui/types': 7.2.24(@types/react@18.3.26)
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
'@popperjs/core': 2.11.8
'@types/react-transition-group': 4.4.12
'@types/react-transition-group': 4.4.12(@types/react@18.3.26)
clsx: 2.1.1
csstype: 3.1.3
prop-types: 15.8.1
@@ -7996,17 +8029,20 @@ snapshots:
react-is: 19.1.1
react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
optionalDependencies:
'@emotion/react': 11.14.0(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@types/react': 18.3.26
'@mui/private-theming@5.17.1(react@18.3.1)':
'@mui/private-theming@5.17.1(@types/react@18.3.26)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/utils': 5.17.1(react@18.3.1)
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
prop-types: 15.8.1
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.26
'@mui/styled-engine@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)':
'@mui/styled-engine@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@emotion/cache': 11.14.0
@@ -8015,35 +8051,40 @@ snapshots:
prop-types: 15.8.1
react: 18.3.1
optionalDependencies:
'@emotion/react': 11.14.0(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@mui/system@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)':
'@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/private-theming': 5.17.1(react@18.3.1)
'@mui/styled-engine': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.24
'@mui/utils': 5.17.1(react@18.3.1)
'@mui/private-theming': 5.17.1(@types/react@18.3.26)(react@18.3.1)
'@mui/styled-engine': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.24(@types/react@18.3.26)
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
clsx: 2.1.1
csstype: 3.1.3
prop-types: 15.8.1
react: 18.3.1
optionalDependencies:
'@emotion/react': 11.14.0(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
'@types/react': 18.3.26
'@mui/types@7.2.24': {}
'@mui/types@7.2.24(@types/react@18.3.26)':
optionalDependencies:
'@types/react': 18.3.26
'@mui/utils@5.17.1(react@18.3.1)':
'@mui/utils@5.17.1(@types/react@18.3.26)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.3
'@mui/types': 7.2.24
'@mui/types': 7.2.24(@types/react@18.3.26)
'@types/prop-types': 15.7.15
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
react-is: 19.1.1
optionalDependencies:
'@types/react': 18.3.26
'@napi-rs/simple-git-android-arm-eabi@0.1.22':
optional: true
@@ -8133,8 +8174,7 @@ snapshots:
'@next/swc-linux-arm64-musl@15.5.0':
optional: true
'@next/swc-linux-x64-gnu@15.5.0':
optional: true
'@next/swc-linux-x64-gnu@15.5.0': {}
'@next/swc-linux-x64-musl@15.5.0':
optional: true
@@ -8199,12 +8239,12 @@ snapshots:
- '@nextui-org/theme'
- framer-motion
'@nextui-org/autocomplete@2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@nextui-org/autocomplete@2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@nextui-org/aria-utils': 2.2.7(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/button': 2.2.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/form': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/listbox': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/popover': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/react-utils': 2.1.3(react@18.3.1)
@@ -8516,7 +8556,7 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@nextui-org/input@2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@nextui-org/input@2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@nextui-org/form': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/react-utils': 2.1.3(react@18.3.1)
@@ -8534,7 +8574,7 @@ snapshots:
'@react-types/textfield': 3.10.0(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-textarea-autosize: 8.5.9(react@18.3.1)
react-textarea-autosize: 8.5.9(@types/react@18.3.26)(react@18.3.1)
transitivePeerDependencies:
- '@types/react'
@@ -8734,11 +8774,11 @@ snapshots:
'@nextui-org/shared-utils': 2.1.2
react: 18.3.1
'@nextui-org/react@2.6.11(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)':
'@nextui-org/react@2.6.11(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)':
dependencies:
'@nextui-org/accordion': 2.2.7(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/alert': 2.2.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/autocomplete': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/autocomplete': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/avatar': 2.2.6(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/badge': 2.2.5(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/breadcrumbs': 2.2.6(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -8756,7 +8796,7 @@ snapshots:
'@nextui-org/form': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/framer-utils': 2.1.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/image': 2.2.5(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/input-otp': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/kbd': 2.2.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@nextui-org/link': 2.2.7(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -9205,9 +9245,11 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
'@nymproject/mix-fetch-wasm@file:../../dist/wasm/mix-fetch': {}
'@nymproject/contract-clients@1.4.1': {}
'@nymproject/nym-client-wasm@file:../../dist/wasm/client': {}
'@nymproject/mix-fetch-full-fat@1.2.3': {}
'@nymproject/sdk-full-fat@1.2.3': {}
'@opentelemetry/api-logs@0.53.0':
dependencies:
@@ -11169,10 +11211,17 @@ snapshots:
'@types/prop-types@15.7.15': {}
'@types/react-transition-group@4.4.12': {}
'@types/react@19.1.10':
'@types/react-dom@18.3.7(@types/react@18.3.26)':
dependencies:
'@types/react': 18.3.26
'@types/react-transition-group@4.4.12(@types/react@18.3.26)':
dependencies:
'@types/react': 18.3.26
'@types/react@18.3.26':
dependencies:
'@types/prop-types': 15.7.15
csstype: 3.1.3
'@types/stylis@4.2.5': {}
@@ -11184,16 +11233,16 @@ snapshots:
'@types/unist@3.0.3': {}
'@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5)':
'@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 6.21.0
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/typescript-estree': 6.21.0(typescript@4.9.5)
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 6.21.0
debug: 4.4.1
eslint: 8.46.0
optionalDependencies:
typescript: 4.9.5
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -11204,7 +11253,7 @@ snapshots:
'@typescript-eslint/types@6.21.0': {}
'@typescript-eslint/typescript-estree@6.21.0(typescript@4.9.5)':
'@typescript-eslint/typescript-estree@6.21.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/visitor-keys': 6.21.0
@@ -11213,9 +11262,9 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.3
semver: 7.7.2
ts-api-utils: 1.4.3(typescript@4.9.5)
ts-api-utils: 1.4.3(typescript@5.9.3)
optionalDependencies:
typescript: 4.9.5
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -11314,7 +11363,7 @@ snapshots:
dependencies:
'@vanilla-extract/css': 1.17.4(babel-plugin-macros@3.1.0)
'@walletconnect/core@2.21.8(typescript@4.9.5)(zod@3.25.76)':
'@walletconnect/core@2.21.8(typescript@5.9.3)(zod@3.25.76)':
dependencies:
'@walletconnect/heartbeat': 1.2.2
'@walletconnect/jsonrpc-provider': 1.0.14
@@ -11328,7 +11377,7 @@ snapshots:
'@walletconnect/safe-json': 1.0.2
'@walletconnect/time': 1.0.2
'@walletconnect/types': 2.21.8
'@walletconnect/utils': 2.21.8(typescript@4.9.5)(zod@3.25.76)
'@walletconnect/utils': 2.21.8(typescript@5.9.3)(zod@3.25.76)
'@walletconnect/window-getters': 1.0.1
es-toolkit: 1.39.3
events: 3.3.0
@@ -11455,16 +11504,16 @@ snapshots:
dependencies:
tslib: 1.14.1
'@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76)':
'@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76)':
dependencies:
'@walletconnect/core': 2.21.8(typescript@4.9.5)(zod@3.25.76)
'@walletconnect/core': 2.21.8(typescript@5.9.3)(zod@3.25.76)
'@walletconnect/events': 1.0.1
'@walletconnect/heartbeat': 1.2.2
'@walletconnect/jsonrpc-utils': 1.0.8
'@walletconnect/logger': 2.1.2
'@walletconnect/time': 1.0.2
'@walletconnect/types': 2.21.8
'@walletconnect/utils': 2.21.8(typescript@4.9.5)(zod@3.25.76)
'@walletconnect/utils': 2.21.8(typescript@5.9.3)(zod@3.25.76)
events: 3.3.0
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -11550,7 +11599,7 @@ snapshots:
- ioredis
- uploadthing
'@walletconnect/utils@2.21.8(typescript@4.9.5)(zod@3.25.76)':
'@walletconnect/utils@2.21.8(typescript@5.9.3)(zod@3.25.76)':
dependencies:
'@msgpack/msgpack': 3.1.2
'@noble/ciphers': 1.3.0
@@ -11571,7 +11620,7 @@ snapshots:
detect-browser: 5.3.0
query-string: 7.1.3
uint8arrays: 3.1.1
viem: 2.31.0(typescript@4.9.5)(zod@3.25.76)
viem: 2.31.0(typescript@5.9.3)(zod@3.25.76)
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -11692,9 +11741,9 @@ snapshots:
fs-extra: 10.1.0
yargs: 17.7.2
abitype@1.0.8(typescript@4.9.5)(zod@3.25.76):
abitype@1.0.8(typescript@5.9.3)(zod@3.25.76):
optionalDependencies:
typescript: 4.9.5
typescript: 5.9.3
zod: 3.25.76
abort-controller@3.0.0:
@@ -12710,20 +12759,20 @@ snapshots:
escape-string-regexp@5.0.0: {}
eslint-config-next@13.4.13(eslint@8.46.0)(typescript@4.9.5):
eslint-config-next@13.4.13(eslint@8.46.0)(typescript@5.9.3):
dependencies:
'@next/eslint-plugin-next': 13.4.13
'@rushstack/eslint-patch': 1.12.0
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@4.9.5)
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@5.9.3)
eslint: 8.46.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.46.0)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.46.0)
eslint-plugin-react: 7.37.5(eslint@8.46.0)
eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.46.0)
optionalDependencies:
typescript: 4.9.5
typescript: 5.9.3
transitivePeerDependencies:
- eslint-import-resolver-webpack
- eslint-plugin-import-x
@@ -12748,22 +12797,22 @@ snapshots:
tinyglobby: 0.2.14
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.46.0)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0):
eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@4.9.5)
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@5.9.3)
eslint: 8.46.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0)
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.46.0):
eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -12774,7 +12823,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.46.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -12786,7 +12835,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@4.9.5)
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -14655,7 +14704,7 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
ox@0.7.1(typescript@4.9.5)(zod@3.25.76):
ox@0.7.1(typescript@5.9.3)(zod@3.25.76):
dependencies:
'@adraffy/ens-normalize': 1.11.0
'@noble/ciphers': 1.3.0
@@ -14663,10 +14712,10 @@ snapshots:
'@noble/hashes': 1.8.0
'@scure/bip32': 1.7.0
'@scure/bip39': 1.6.0
abitype: 1.0.8(typescript@4.9.5)(zod@3.25.76)
abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76)
eventemitter3: 5.0.1
optionalDependencies:
typescript: 4.9.5
typescript: 5.9.3
transitivePeerDependencies:
- zod
@@ -14978,12 +15027,12 @@ snapshots:
prop-types: 15.8.1
react: 18.3.1
react-textarea-autosize@8.5.9(react@18.3.1):
react-textarea-autosize@8.5.9(@types/react@18.3.26)(react@18.3.1):
dependencies:
'@babel/runtime': 7.28.3
react: 18.3.1
use-composed-ref: 1.4.0(react@18.3.1)
use-latest: 1.3.0(react@18.3.1)
use-composed-ref: 1.4.0(@types/react@18.3.26)(react@18.3.1)
use-latest: 1.3.0(@types/react@18.3.26)(react@18.3.1)
transitivePeerDependencies:
- '@types/react'
@@ -15710,9 +15759,9 @@ snapshots:
trough@2.2.0: {}
ts-api-utils@1.4.3(typescript@4.9.5):
ts-api-utils@1.4.3(typescript@5.9.3):
dependencies:
typescript: 4.9.5
typescript: 5.9.3
ts-dedent@2.2.0: {}
@@ -15776,7 +15825,7 @@ snapshots:
typeforce@1.18.0: {}
typescript@4.9.5: {}
typescript@5.9.3: {}
ufo@1.6.1: {}
@@ -15945,18 +15994,24 @@ snapshots:
url-template@2.0.8: {}
use-composed-ref@1.4.0(react@18.3.1):
use-composed-ref@1.4.0(@types/react@18.3.26)(react@18.3.1):
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.26
use-isomorphic-layout-effect@1.2.1(react@18.3.1):
use-isomorphic-layout-effect@1.2.1(@types/react@18.3.26)(react@18.3.1):
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.26
use-latest@1.3.0(react@18.3.1):
use-latest@1.3.0(@types/react@18.3.26)(react@18.3.1):
dependencies:
react: 18.3.1
use-isomorphic-layout-effect: 1.2.1(react@18.3.1)
use-isomorphic-layout-effect: 1.2.1(@types/react@18.3.26)(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.26
use-sync-external-store@1.5.0(react@18.3.1):
dependencies:
@@ -16010,18 +16065,18 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
viem@2.31.0(typescript@4.9.5)(zod@3.25.76):
viem@2.31.0(typescript@5.9.3)(zod@3.25.76):
dependencies:
'@noble/curves': 1.9.1
'@noble/hashes': 1.8.0
'@scure/bip32': 1.7.0
'@scure/bip39': 1.6.0
abitype: 1.0.8(typescript@4.9.5)(zod@3.25.76)
abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76)
isows: 1.0.7(ws@8.18.2)
ox: 0.7.1(typescript@4.9.5)(zod@3.25.76)
ox: 0.7.1(typescript@5.9.3)(zod@3.25.76)
ws: 8.18.2
optionalDependencies:
typescript: 4.9.5
typescript: 5.9.3
transitivePeerDependencies:
- bufferutil
- utf-8-validate
@@ -16195,10 +16250,11 @@ snapshots:
zod@3.25.76: {}
zustand@4.5.7(immer@10.1.1)(react@18.3.1):
zustand@4.5.7(@types/react@18.3.26)(immer@10.1.1)(react@18.3.1):
dependencies:
use-sync-external-store: 1.5.0(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.26
immer: 10.1.1
react: 18.3.1
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

@@ -51,12 +51,12 @@ impl AuthClientMixnetListener {
}
async fn run(mut self) -> Self {
let mixnet_cancel_token = self.mixnet_client.cancellation_token();
self.shutdown_token.run_until_cancelled(async {
let shutdown_event = self.mixnet_client.shutdown_event();
loop {
tokio::select! {
biased;
_ = mixnet_cancel_token.cancelled() => {
_ = shutdown_event.wait() => {
tracing::debug!("AuthClientMixnetListener: mixnet client was shutdown");
break;
}
@@ -100,9 +100,7 @@ impl AuthClientMixnetListener {
// Disconnects the mixnet client and effectively drop itself, since it doesn't work without one, and reconnecting isn't supported
pub async fn disconnect_mixnet_client(self) {
if !self.mixnet_client.cancellation_token().is_cancelled() {
self.mixnet_client.disconnect().await;
}
self.mixnet_client.disconnect().await;
}
pub fn start(self) -> AuthClientMixnetListenerHandle {
@@ -110,14 +108,14 @@ impl AuthClientMixnetListener {
let message_sender = self.input_message_tx.clone();
// Allows stopping only this, e.g. if we don't need it in the new bandwidth controller
let cancellation_token = self.shutdown_token.clone();
let mixnet_cancellation_token = self.mixnet_client.cancellation_token();
// let mixnet_cancellation_token = self.mixnet_client.cancellation_token();
let handle = tokio::spawn(self.run());
AuthClientMixnetListenerHandle {
message_broadcast,
message_sender,
cancellation_token,
mixnet_cancellation_token,
// mixnet_cancellation_token,
handle,
}
}
@@ -127,7 +125,7 @@ pub struct AuthClientMixnetListenerHandle {
message_broadcast: MixnetMessageBroadcastSender,
message_sender: MixnetMessageInputSender,
cancellation_token: CancellationToken,
mixnet_cancellation_token: CancellationToken,
// mixnet_cancellation_token: CancellationToken,
handle: JoinHandle<AuthClientMixnetListener>,
}
@@ -140,9 +138,9 @@ impl AuthClientMixnetListenerHandle {
self.message_broadcast.subscribe()
}
pub fn mixnet_cancel_token(&self) -> CancellationToken {
self.mixnet_cancellation_token.clone()
}
// pub fn mixnet_cancel_token(&self) -> CancellationToken {
// self.mixnet_cancellation_token.clone()
// }
pub async fn stop(self) {
// If shutdown was externally called, that call is a no-op
+15 -3
View File
@@ -7,6 +7,7 @@ use nym_config::defaults::setup_env;
use nym_gateway_probe::nodes::NymApiDirectory;
use nym_gateway_probe::{CredentialArgs, NetstackArgs, ProbeResult, TestedNode};
use nym_sdk::mixnet::NodeIdentity;
use std::path::Path;
use std::{path::PathBuf, sync::OnceLock};
use tracing::*;
@@ -69,6 +70,8 @@ struct CliArgs {
credential_args: CredentialArgs,
}
const DEFAULT_CONFIG_DIR: &str = "/tmp/nym-gateway-probe/config/";
#[derive(Subcommand, Debug)]
enum Commands {
/// Run the probe locally
@@ -77,8 +80,8 @@ enum Commands {
#[arg(long)]
mnemonic: String,
#[arg(long, default_value = "/tmp/nym-gateway-probe/config/")]
config_dir: PathBuf,
#[arg(long)]
config_dir: Option<PathBuf>,
},
}
@@ -144,8 +147,17 @@ pub(crate) async fn run() -> anyhow::Result<ProbeResult> {
mnemonic,
config_dir,
}) => {
let config_dir = config_dir
.clone()
.unwrap_or_else(|| Path::new(DEFAULT_CONFIG_DIR).join(&network.network_name));
info!(
"using the following directory for the probe config: {}",
config_dir.display()
);
Box::pin(trial.probe_run_locally(
config_dir,
&config_dir,
mnemonic,
directory,
nyxd_url,
+5 -7
View File
@@ -133,8 +133,7 @@ impl IprClientConnect {
let timeout = sleep(IPR_CONNECT_TIMEOUT);
tokio::pin!(timeout);
let mixnet_cancel_token = self.mixnet_client.cancellation_token();
let shutdown_event = self.mixnet_client.shutdown_event();
loop {
tokio::select! {
@@ -142,15 +141,14 @@ impl IprClientConnect {
error!("Cancelled while waiting for reply to connect request");
return Err(Error::Cancelled);
},
_ = mixnet_cancel_token.cancelled() => {
error!("Mixnet client stopped while waiting for reply to connect request");
return Err(Error::Cancelled);
},
_ = &mut timeout => {
error!("Timed out waiting for reply to connect request");
return Err(Error::TimeoutWaitingForConnectResponse);
},
_ = shutdown_event.wait() => {
error!("Mixnet client stopped while waiting for reply to connect request");
return Err(Error::Cancelled);
},
msgs = self.mixnet_client.wait_for_messages() => match msgs {
None => {
return Err(Error::NoMixnetMessagesReceived);
@@ -3,7 +3,7 @@
[package]
name = "nym-node-status-api"
version = "4.0.7"
version = "4.0.9"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
@@ -99,6 +99,7 @@ pub struct DVpnGatewayPerformance {
pub struct DVpnGateway {
pub identity_key: String,
pub name: String,
pub description: Option<String>,
pub ip_packet_router: Option<IpPacketRouterDetails>,
pub authenticator: Option<AuthenticatorDetails>,
pub location: Location,
@@ -326,6 +327,7 @@ impl DVpnGateway {
Ok(Self {
identity_key: gateway.gateway_identity_key,
name: gateway.description.moniker,
description: Some(gateway.description.details),
ip_packet_router: self_described.ip_packet_router,
authenticator: self_described.authenticator,
location: Location {
@@ -395,20 +397,23 @@ fn calculate_score(gateway: &Gateway, probe_outcome: &LastProbeResult) -> ScoreV
.map(|p| {
let ping_ips_performance = p.ping_ips_performance_v4 as f64;
let duration = p.download_duration_sec_v4 as f64;
let duration_sec =
p.download_duration_milliseconds_v4
.unwrap_or_else(|| p.download_duration_sec_v4 * 1000) as f64
/ 1000f64;
// get the file size downloaded in bytes and convert to MB, or default to 1MB
let file_size_mb =
p.downloaded_file_size_bytes_v4.unwrap_or(1048576) as f64 / 1024f64 / 1024f64;
let speed_mbps = file_size_mb / duration;
let speed_mbps = file_size_mb / duration_sec;
let file_download_score = if speed_mbps > 100.0 {
let file_download_score = if speed_mbps > 5.0 {
1.0
} else if speed_mbps > 50.0 {
} else if speed_mbps > 2.0 {
0.75
} else if speed_mbps > 20.0 {
} else if speed_mbps > 1.0 {
0.5
} else if speed_mbps > 10.0 {
} else if speed_mbps > 0.5 {
0.25
} else {
0.1
@@ -0,0 +1,941 @@
#!/bin/bash
# Nym QUIC Bridge Deployment Helper Script
# This script provides network configuration and troubleshooting tools for Nym QUIC bridges
network_device=$(ip route show default | awk '/default/ {print $5}')
wg_tunnel_interface="nymwg"
BRIDGE_CONFIG_DIR="/opt/nym-bridge"
BRIDGE_KEYS_DIR="$BRIDGE_CONFIG_DIR/keys"
BRIDGE_CONFIG="$BRIDGE_CONFIG_DIR/bridges.toml"
CLIENT_PARAMS="$BRIDGE_CONFIG_DIR/client_bridge_params.json"
BRIDGE_BINARY="/usr/local/bin/nym-bridge"
if ! dpkg -s iptables-persistent >/dev/null 2>&1; then
echo "Installing iptables-persistent..."
sudo apt-get update
sudo apt-get install -y iptables-persistent
else
echo "iptables-persistent is already installed."
fi
fetch_and_display_ipv6() {
ipv6_address=$(ip -6 addr show "$network_device" scope global | grep inet6 | awk '{print $2}')
if [[ -z "$ipv6_address" ]]; then
echo "No global IPv6 address found on $network_device."
else
echo "IPv6 address on $network_device: $ipv6_address"
fi
}
fetch_wg_ipv6_address() {
ipv6_global_address=$(ip -6 addr show "$wg_tunnel_interface" scope global | grep inet6 | awk '{print $2}' | head -n 1)
if [[ -z "$ipv6_global_address" ]]; then
echo "No globally routable IPv6 address found on $wg_tunnel_interface. Please configure IPv6 or check your network settings."
exit 1
else
echo "Using IPv6 address: $ipv6_global_address"
fi
}
adjust_ip_forwarding() {
ipv6_forwarding_setting="net.ipv6.conf.all.forwarding=1"
ipv4_forwarding_setting="net.ipv4.ip_forward=1"
# Remove duplicate entries for these settings from the file
sudo sed -i "/^net.ipv6.conf.all.forwarding=/d" /etc/sysctl.conf
sudo sed -i "/^net.ipv4.ip_forward=/d" /etc/sysctl.conf
echo "$ipv6_forwarding_setting" | sudo tee -a /etc/sysctl.conf
echo "$ipv4_forwarding_setting" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf
echo "IP forwarding enabled for IPv4 and IPv6."
}
apply_bridge_iptables_rules() {
echo "Applying iptables rules for QUIC bridge ($wg_tunnel_interface)..."
sleep 1
# INPUT rules - allow incoming connections TO the bridge from WireGuard clients
# CRITICAL: This allows mobile clients to reach the bandwidth controller at 10.1.0.1:51830
sudo iptables -I INPUT -i "$wg_tunnel_interface" -j ACCEPT
sudo ip6tables -I INPUT -i "$wg_tunnel_interface" -j ACCEPT
# NAT rules - for outbound traffic masquerading
sudo iptables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE
sudo ip6tables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE
# FORWARD rules - allow traffic through the bridge
sudo iptables -A FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT
sudo iptables -A FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ip6tables -A FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT
sudo ip6tables -A FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT
# Save rules
sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6
echo "Iptables rules applied successfully for QUIC bridge (including INPUT rules for bandwidth controller)."
}
check_bridge_iptables() {
echo "Inspecting iptables rules for QUIC bridge ($wg_tunnel_interface)..."
echo "---------------------------------------"
echo "IPv4 INPUT rules (for bandwidth controller):"
iptables -L INPUT -v -n | grep -E "$wg_tunnel_interface|Chain INPUT" | head -20
echo "---------------------------------------"
echo "IPv4 FORWARD rules:"
iptables -L FORWARD -v -n | awk -v dev="$wg_tunnel_interface" '/^Chain FORWARD/ || $0 ~ dev || $0 ~ "ufw-reject-forward"'
echo "---------------------------------------"
echo "IPv6 INPUT rules (for bandwidth controller):"
ip6tables -L INPUT -v -n | grep -E "$wg_tunnel_interface|Chain INPUT" | head -20
echo "---------------------------------------"
echo "IPv6 FORWARD rules:"
ip6tables -L FORWARD -v -n | awk -v dev="$wg_tunnel_interface" '/^Chain FORWARD/ || $0 ~ dev || $0 ~ "ufw6-reject-forward"'
}
remove_duplicate_bridge_rules() {
local script_name=$(basename "$0")
echo "Removing duplicate iptables rules for $wg_tunnel_interface..."
iptables-save | grep "$wg_tunnel_interface" | while read -r line; do
sudo iptables -D ${line#-A } 2>/dev/null || echo "Failed to delete rule: $line"
done
ip6tables-save | grep "$wg_tunnel_interface" | while read -r line; do
sudo ip6tables -D ${line#-A } 2>/dev/null || echo "Failed to delete rule: $line"
done
echo "Duplicates removed for $wg_tunnel_interface."
echo "!!IMPORTANT!! You need to now reapply the iptables rules."
echo "Run: ./$script_name apply_bridge_iptables_rules"
}
configure_dns_and_icmp() {
echo "Allowing ICMP (ping)..."
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
sudo iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
sudo ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
sudo ip6tables -A OUTPUT -p ipv6-icmp -j ACCEPT
echo "Allowing DNS over UDP (port 53)..."
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT
sudo ip6tables -A INPUT -p udp --dport 53 -j ACCEPT
echo "Allowing DNS over TCP (port 53)..."
sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT
sudo ip6tables -A INPUT -p tcp --dport 53 -j ACCEPT
echo "Saving iptables rules..."
sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6
echo "DNS and ICMP configuration completed."
}
check_ipv6_ipv4_forwarding() {
result_ipv4=$(cat /proc/sys/net/ipv4/ip_forward)
result_ipv6=$(cat /proc/sys/net/ipv6/conf/all/forwarding)
echo "IPv4 forwarding is $([ "$result_ipv4" == "1" ] && echo "enabled" || echo "not enabled")."
echo "IPv6 forwarding is $([ "$result_ipv6" == "1" ] && echo "enabled" || echo "not enabled")."
}
check_ip_routing() {
echo "IPv4 routing table:"
ip route
echo "---------------------------------------"
echo "IPv6 routing table:"
ip -6 route
}
perform_pings() {
echo "Performing IPv4 ping to google.com..."
ping -c 4 google.com
echo "---------------------------------------"
echo "Performing IPv6 ping to google.com..."
ping6 -c 4 google.com
}
test_bridge_connectivity() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
sleep 1
echo
echo -e "${yellow}Testing QUIC bridge connectivity on $wg_tunnel_interface...${reset}"
echo -e "${yellow}If these tests succeed, it confirms the bridge can reach the outside world via IPv4 and IPv6.${reset}"
echo -e "${yellow}However, external clients may experience different connectivity to your bridge.${reset}"
ipv4_address=$(ip addr show "$wg_tunnel_interface" | awk '/inet / {print $2}' | cut -d'/' -f1)
ipv6_address=$(ip addr show "$wg_tunnel_interface" | awk '/inet6 / && $2 !~ /^fe80/ {print $2}' | cut -d'/' -f1)
if [[ -z "$ipv4_address" && -z "$ipv6_address" ]]; then
echo -e "${red}No IP address found on $wg_tunnel_interface. Unable to test connectivity.${reset}"
echo -e "${red}Please verify your bridge configuration and ensure the interface is up.${reset}"
return 1
fi
if [[ -n "$ipv4_address" ]]; then
echo
echo -e "------------------------------------"
echo -e "Detected IPv4 address: $ipv4_address"
echo -e "Testing IPv4 connectivity..."
echo
if ping -c 1 -I "$ipv4_address" google.com >/dev/null 2>&1; then
echo -e "${green}IPv4 connectivity is working. Fetching test data...${reset}"
joke=$(curl -s -H "Accept: application/json" --interface "$ipv4_address" https://icanhazdadjoke.com/ | jq -r .joke)
[[ -n "$joke" && "$joke" != "null" ]] && echo -e "${green}IPv4 test joke: $joke${reset}" || echo -e "${red}Failed to fetch test data via IPv4.${reset}"
else
echo -e "${red}IPv4 connectivity is not working for $wg_tunnel_interface. Verify your routing and NAT settings.${reset}"
fi
else
echo -e "${yellow}No IPv4 address found on $wg_tunnel_interface. Skipping IPv4 test.${reset}"
fi
if [[ -n "$ipv6_address" ]]; then
echo
echo -e "------------------------------------"
echo -e "Detected IPv6 address: $ipv6_address"
echo -e "Testing IPv6 connectivity..."
echo
if ping6 -c 1 -I "$ipv6_address" google.com >/dev/null 2>&1; then
echo -e "${green}IPv6 connectivity is working. Fetching test data...${reset}"
joke=$(curl -s -H "Accept: application/json" --interface "$ipv6_address" https://icanhazdadjoke.com/ | jq -r .joke)
[[ -n "$joke" && "$joke" != "null" ]] && echo -e "${green}IPv6 test joke: $joke${reset}" || echo -e "${red}Failed to fetch test data via IPv6.${reset}"
else
echo -e "${red}IPv6 connectivity is not working for $wg_tunnel_interface. Verify your routing and NAT settings.${reset}"
fi
else
echo -e "${yellow}No IPv6 address found on $wg_tunnel_interface. Skipping IPv6 test.${reset}"
fi
echo -e "${green}Connectivity testing completed for $wg_tunnel_interface.${reset}"
echo -e "------------------------------------"
sleep 2
echo
echo
echo -e "${yellow}### Bridge Connectivity Testing Recommendations ###${reset}"
echo -e "${yellow}- Test UDP connectivity on port 51822 (used for Nym QUIC/WireGuard)${reset}"
echo -e "${yellow} From another machine: echo 'test message' | nc -u <your-ip-address> 51822${reset}"
echo -e "${yellow}- Test bandwidth controller access on port 51830:${reset}"
echo -e "${yellow} From inside the WireGuard tunnel: curl http://10.1.0.1:51830${reset}"
echo -e "${yellow}- If connectivity issues persist, check port forwarding and firewall rules${reset}"
echo
}
check_bridge_service_status() {
echo "Checking nym-bridge service status..."
systemctl status nym-bridge.service --no-pager
echo "---------------------------------------"
echo "Checking nym-node service status..."
systemctl status nym-node.service --no-pager
}
show_bridge_logs() {
local lines=${1:-50}
echo "Showing last $lines lines of nym-bridge logs..."
journalctl -u nym-bridge.service -n "$lines" --no-pager
}
check_bridge_installation() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Nym QUIC Bridge Installation Status ===${reset}"
echo ""
# Check binary
if [[ -f "$BRIDGE_BINARY" ]]; then
echo -e "${green}✓ Bridge binary found: $BRIDGE_BINARY${reset}"
bridge_version=$($BRIDGE_BINARY --version 2>/dev/null | head -1 || echo "Unable to determine version")
echo " Version: $bridge_version"
else
echo -e "${red}✗ Bridge binary not found at $BRIDGE_BINARY${reset}"
fi
echo ""
# Check configuration directory
if [[ -d "$BRIDGE_CONFIG_DIR" ]]; then
echo -e "${green}✓ Configuration directory exists: $BRIDGE_CONFIG_DIR${reset}"
else
echo -e "${red}✗ Configuration directory not found: $BRIDGE_CONFIG_DIR${reset}"
fi
echo ""
# Check keys directory
if [[ -d "$BRIDGE_KEYS_DIR" ]]; then
echo -e "${green}✓ Keys directory exists: $BRIDGE_KEYS_DIR${reset}"
key_count=$(ls -1 "$BRIDGE_KEYS_DIR"/*.pem 2>/dev/null | wc -l)
echo " Keys found: $key_count"
else
echo -e "${red}✗ Keys directory not found: $BRIDGE_KEYS_DIR${reset}"
fi
echo ""
# Check configuration files
if [[ -f "$BRIDGE_CONFIG" ]]; then
echo -e "${green}✓ Bridge config found: $BRIDGE_CONFIG${reset}"
else
echo -e "${red}✗ Bridge config not found: $BRIDGE_CONFIG${reset}"
fi
if [[ -f "$CLIENT_PARAMS" ]]; then
echo -e "${green}✓ Client params found: $CLIENT_PARAMS${reset}"
else
echo -e "${red}✗ Client params not found: $CLIENT_PARAMS${reset}"
fi
echo ""
# Check services
echo -e "${yellow}Service Status:${reset}"
if systemctl is-active --quiet nym-bridge.service; then
echo -e "${green}✓ nym-bridge service is running${reset}"
else
echo -e "${red}✗ nym-bridge service is not running${reset}"
fi
if systemctl is-active --quiet nym-node.service; then
echo -e "${green}✓ nym-node service is running${reset}"
else
echo -e "${red}✗ nym-node service is not running${reset}"
fi
echo ""
}
show_bridge_config() {
echo "=== Bridge Configuration ==="
echo ""
if [[ -f "$BRIDGE_CONFIG" ]]; then
echo "Bridge config ($BRIDGE_CONFIG):"
echo "---------------------------------------"
cat "$BRIDGE_CONFIG"
echo ""
else
echo "Bridge config not found at $BRIDGE_CONFIG"
fi
if [[ -f "$CLIENT_PARAMS" ]]; then
echo "Client parameters ($CLIENT_PARAMS):"
echo "---------------------------------------"
cat "$CLIENT_PARAMS"
echo ""
else
echo "Client parameters not found at $CLIENT_PARAMS"
fi
}
show_bridge_keys() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Bridge Keys Information ===${reset}"
echo ""
if [[ ! -d "$BRIDGE_KEYS_DIR" ]]; then
echo -e "${red}Keys directory not found: $BRIDGE_KEYS_DIR${reset}"
return 1
fi
echo "Keys directory: $BRIDGE_KEYS_DIR"
echo "---------------------------------------"
# List all key files
if ls -1 "$BRIDGE_KEYS_DIR"/*.pem >/dev/null 2>&1; then
for key_file in "$BRIDGE_KEYS_DIR"/*.pem; do
key_name=$(basename "$key_file")
echo -e "${green}Key file: $key_name${reset}"
# If it's a public key, show the content
if [[ "$key_name" == *"_bridge_identity.pem" ]]; then
echo " Type: ED25519 Bridge Identity (Private)"
echo " Path: $key_file"
# Extract and show public key
if command -v openssl >/dev/null 2>&1; then
echo -e "${yellow} Public key (base64):${reset}"
openssl pkey -in "$key_file" -pubout 2>/dev/null | grep -v "\---" | base64 -d | tail -c 32 | base64
fi
fi
echo ""
done
else
echo -e "${red}No key files found in $BRIDGE_KEYS_DIR${reset}"
fi
}
show_bridge_info() {
local green="\033[0;32m"
local reset="\033[0m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Nym QUIC Bridge Information ===${reset}"
echo ""
# Network interfaces
echo -e "${yellow}Network Configuration:${reset}"
echo "Primary network device: $network_device"
echo "WireGuard interface: $wg_tunnel_interface"
# Show IP addresses
echo ""
echo "IPv4 addresses:"
ip -4 addr show | grep inet | awk '{print " " $2 " on " $NF}'
echo ""
echo "IPv6 addresses:"
ip -6 addr show scope global | grep inet6 | awk '{print " " $2 " on " $NF}'
echo ""
echo -e "${yellow}Bridge Paths:${reset}"
echo "Configuration: $BRIDGE_CONFIG_DIR"
echo "Keys: $BRIDGE_KEYS_DIR"
echo "Binary: $BRIDGE_BINARY"
echo ""
echo -e "${yellow}Important Commands:${reset}"
echo " Check bridge status: systemctl status nym-bridge"
echo " Check nym-node status: systemctl status nym-node"
echo " View bridge logs: journalctl -u nym-bridge -f"
echo " View nym-node logs: journalctl -u nym-node -f"
echo ""
}
verify_bridge_prerequisites() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Verifying Bridge Prerequisites ===${reset}"
echo ""
local all_good=true
# Check IP forwarding
ipv4_forward=$(cat /proc/sys/net/ipv4/ip_forward)
ipv6_forward=$(cat /proc/sys/net/ipv6/conf/all/forwarding)
if [[ "$ipv4_forward" == "1" ]]; then
echo -e "${green}✓ IPv4 forwarding enabled${reset}"
else
echo -e "${red}✗ IPv4 forwarding disabled${reset}"
echo " Fix: Run 'nym-bridge-helper adjust_ip_forwarding'"
all_good=false
fi
if [[ "$ipv6_forward" == "1" ]]; then
echo -e "${green}✓ IPv6 forwarding enabled${reset}"
else
echo -e "${red}✗ IPv6 forwarding disabled${reset}"
echo " Fix: Run 'nym-bridge-helper adjust_ip_forwarding'"
all_good=false
fi
# Check iptables-persistent
if dpkg -s iptables-persistent >/dev/null 2>&1; then
echo -e "${green}✓ iptables-persistent installed${reset}"
else
echo -e "${red}✗ iptables-persistent not installed${reset}"
echo " Fix: This script will auto-install on first run"
all_good=false
fi
# Check required packages
for pkg in openssl jq curl wg; do
if command -v "$pkg" >/dev/null 2>&1; then
echo -e "${green}$pkg installed${reset}"
else
echo -e "${red}$pkg not installed${reset}"
if [[ "$pkg" == "wg" ]]; then
echo " Install: sudo apt install wireguard-tools"
fi
all_good=false
fi
done
echo ""
if [[ "$all_good" == true ]]; then
echo -e "${green}All prerequisites satisfied!${reset}"
else
echo -e "${yellow}Some prerequisites need attention. See above for fixes.${reset}"
fi
echo ""
}
generate_bridge_keys() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Generating Bridge Keys ===${reset}"
echo ""
# Create directories
sudo mkdir -p "$BRIDGE_CONFIG_DIR"
sudo mkdir -p "$BRIDGE_KEYS_DIR"
sudo chmod 700 "$BRIDGE_KEYS_DIR"
# Generate ED25519 private key
local key_file="$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem"
if [[ -f "$key_file" ]]; then
echo -e "${yellow}Warning: Key file already exists at $key_file${reset}"
read -p "Overwrite existing key? (yes/no): " confirm
if [[ "$confirm" != "yes" ]]; then
echo "Aborted. Keeping existing key."
return 1
fi
fi
echo "Generating ED25519 key..."
sudo openssl genpkey -algorithm ED25519 -out "$key_file"
sudo chmod 600 "$key_file"
echo -e "${green}✓ Bridge key generated at $key_file${reset}"
# Extract and display public key
echo ""
echo "Extracting public key..."
pubkey=$(sudo openssl pkey -in "$key_file" -pubout 2>/dev/null | grep -v "\---" | base64 -d | tail -c 32 | base64)
echo -e "${green}Public key (base64): $pubkey${reset}"
echo ""
echo -e "${yellow}Next steps:${reset}"
echo "1. Run 'nym-bridge-helper create_client_params' to generate client parameters"
echo "2. Run 'nym-bridge-helper create_bridge_config' to create bridge configuration"
}
create_client_params() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Creating Client Bridge Parameters ===${reset}"
echo ""
# Check if key exists
local key_file="$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem"
if [[ ! -f "$key_file" ]]; then
echo -e "${red}Error: Bridge key not found at $key_file${reset}"
echo "Run 'nym-bridge-helper generate_bridge_keys' first"
return 1
fi
# Get forward address
read -p "Enter forward address (e.g., <IPv4>:51822, can be found by running 'curl -6 https://ifconfig.co/ip'): " forward_addr
if [[ -z "$forward_addr" ]]; then
echo -e "${red}Error: Forward address is required${reset}"
return 1
fi
# Extract public key
echo "Extracting public key..."
pubkey=$(sudo openssl pkey -in "$key_file" -pubout 2>/dev/null | grep -v "\---" | base64 -d | tail -c 32 | base64)
# Create client params JSON
echo "Creating client parameters file..."
sudo tee "$CLIENT_PARAMS" > /dev/null <<EOF
{
"ed25519_bridge_identity": "$pubkey",
"forward_address": "$forward_addr",
"endpoint": {
"Quic": {
"host": "$forward_addr"
}
}
}
EOF
sudo chmod 644 "$CLIENT_PARAMS"
echo -e "${green}✓ Client parameters created at $CLIENT_PARAMS${reset}"
echo ""
echo "Content:"
cat "$CLIENT_PARAMS"
}
create_bridge_config() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Creating Bridge Configuration ===${reset}"
echo ""
# Get configuration parameters
read -p "Enter listening address (press enter for default: 0.0.0.0): " listen_addr
listen_addr=${listen_addr:-0.0.0.0}
read -p "Enter listening port (press enter for default: 51822): " listen_port
listen_port=${listen_port:-51822}
read -p "Enter tunnel device name (press enter for default: nymwg): " tunnel_dev
tunnel_dev=${tunnel_dev:-nymwg}
read -p "Enter tunnel IPv4 address (press enter for default: 10.1.0.1/24): " tunnel_ipv4
tunnel_ipv4=${tunnel_ipv4:-10.1.0.1/24}
read -p "Enter tunnel IPv6 address (optional, can be found by running 'curl -6 https://ifconfig.co/ip', press enter to skip): " tunnel_ipv6
read -p "Enter WireGuard private key (or press enter to generate): " wg_privkey
if [[ -z "$wg_privkey" ]]; then
echo "Generating WireGuard private key..."
wg_privkey=$(wg genkey)
wg_pubkey=$(echo "$wg_privkey" | wg pubkey)
echo -e "${green}Generated WireGuard public key: $wg_pubkey${reset}"
fi
# Create bridges.toml
echo "Creating bridge configuration..."
sudo tee "$BRIDGE_CONFIG" > /dev/null <<EOF
# Nym QUIC Bridge Configuration
[[bridges]]
# Listening address and port for the bridge
listening_address = "$listen_addr:$listen_port"
# WireGuard tunnel configuration
tunnel_device_name = "$tunnel_dev"
tunnel_device_address = "$tunnel_ipv4"
EOF
if [[ -n "$tunnel_ipv6" ]]; then
echo "tunnel_device_ipv6_address = \"$tunnel_ipv6\"" | sudo tee -a "$BRIDGE_CONFIG" > /dev/null
fi
sudo tee -a "$BRIDGE_CONFIG" > /dev/null <<EOF
# Bridge identity key
bridge_identity_private_key_file = "$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem"
# WireGuard private key
wireguard_private_key = "$wg_privkey"
# Additional settings
bandwidth_controller_port = 51830
EOF
sudo chmod 644 "$BRIDGE_CONFIG"
echo -e "${green}✓ Bridge configuration created at $BRIDGE_CONFIG${reset}"
echo ""
echo "Configuration preview:"
cat "$BRIDGE_CONFIG"
}
create_bridge_service() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Creating nym-bridge systemd Service ===${reset}"
echo ""
# Check if bridge binary exists
if [[ ! -f "$BRIDGE_BINARY" ]]; then
echo -e "${red}Error: Bridge binary not found at $BRIDGE_BINARY${reset}"
echo "Please install the nym-bridge binary first"
return 1
fi
# Check if config exists
if [[ ! -f "$BRIDGE_CONFIG" ]]; then
echo -e "${red}Error: Bridge config not found at $BRIDGE_CONFIG${reset}"
echo "Run 'nym-bridge-helper create_bridge_config' first"
return 1
fi
# Create systemd service file
local service_file="/etc/systemd/system/nym-bridge.service"
echo "Creating systemd service file..."
sudo tee "$service_file" > /dev/null <<EOF
[Unit]
Description=Nym QUIC Bridge
After=network.target nym-node.service
Wants=nym-node.service
[Service]
Type=simple
User=root
ExecStart=$BRIDGE_BINARY --config $BRIDGE_CONFIG
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=nym-bridge
# Security settings
NoNewPrivileges=false
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=$BRIDGE_CONFIG_DIR
# Network capabilities
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF
echo -e "${green}✓ Systemd service file created at $service_file${reset}"
# Reload systemd
echo "Reloading systemd daemon..."
sudo systemctl daemon-reload
echo ""
echo -e "${green}Service created successfully!${reset}"
echo ""
echo "To enable and start the service:"
echo " sudo systemctl enable nym-bridge"
echo " sudo systemctl start nym-bridge"
echo ""
echo "To check status:"
echo " sudo systemctl status nym-bridge"
}
install_bridge_binary() {
local green="\033[0;32m"
local reset="\033[0m"
local red="\033[0;31m"
local yellow="\033[0;33m"
echo -e "${yellow}=== Installing nym-bridge Binary ===${reset}"
echo ""
read -p "Enter bridge binary URL for your system from here https://builds.ci.nymte.ch/QUIC/: " binary_url
if [[ -z "$binary_url" ]]; then
echo -e "${red}Error: Binary URL is required${reset}"
return 1
fi
echo "Downloading nym-bridge binary..."
if sudo curl -L "$binary_url" -o "$BRIDGE_BINARY"; then
sudo chmod 755 "$BRIDGE_BINARY"
echo -e "${green}✓ Bridge binary installed at $BRIDGE_BINARY${reset}"
# Show version
echo ""
echo "Binary version:"
$BRIDGE_BINARY --version || echo "Unable to determine version"
else
echo -e "${red}✗ Failed to download bridge binary${reset}"
return 1
fi
}
full_bridge_setup() {
local green="\033[0;32m"
local reset="\033[0m"
local yellow="\033[0;33m"
echo -e "${yellow}========================================${reset}"
echo -e "${yellow} Nym QUIC Bridge - Full Setup${reset}"
echo -e "${yellow}========================================${reset}"
echo ""
echo "This will guide you through complete bridge setup"
echo ""
# Step 1: Prerequisites
echo "Step 1/7: Checking prerequisites..."
verify_bridge_prerequisites
read -p "Press Enter to continue..."
# Step 2: Install binary
echo ""
echo "Step 2/7: Installing bridge binary..."
install_bridge_binary
read -p "Press Enter to continue..."
# Step 3: Generate keys
echo ""
echo "Step 3/7: Generating bridge keys..."
generate_bridge_keys
read -p "Press Enter to continue..."
# Step 4: Create client params
echo ""
echo "Step 4/7: Creating client parameters..."
create_client_params
read -p "Press Enter to continue..."
# Step 5: Create bridge config
echo ""
echo "Step 5/7: Creating bridge configuration..."
create_bridge_config
read -p "Press Enter to continue..."
# Step 6: Create service
echo ""
echo "Step 6/7: Creating systemd service..."
create_bridge_service
read -p "Press Enter to continue..."
# Step 7: Network setup
echo ""
echo "Step 7/7: Configuring network..."
adjust_ip_forwarding
apply_bridge_iptables_rules
configure_dns_and_icmp
echo ""
echo -e "${green}========================================${reset}"
echo -e "${green} Bridge Setup Complete!${reset}"
echo -e "${green}========================================${reset}"
echo ""
echo "To start the bridge:"
echo " sudo systemctl enable nym-bridge"
echo " sudo systemctl start nym-bridge"
echo ""
echo "To check status:"
echo " nym-bridge-helper check_bridge_service_status"
}
case "$1" in
fetch_and_display_ipv6)
fetch_and_display_ipv6
;;
fetch_wg_ipv6_address)
fetch_wg_ipv6_address
;;
apply_bridge_iptables_rules)
apply_bridge_iptables_rules
;;
check_bridge_iptables)
check_bridge_iptables
;;
remove_duplicate_bridge_rules)
remove_duplicate_bridge_rules
;;
configure_dns_and_icmp)
configure_dns_and_icmp
;;
adjust_ip_forwarding)
adjust_ip_forwarding
;;
check_ipv6_ipv4_forwarding)
check_ipv6_ipv4_forwarding
;;
check_ip_routing)
check_ip_routing
;;
perform_pings)
perform_pings
;;
test_bridge_connectivity)
test_bridge_connectivity
;;
check_bridge_service_status)
check_bridge_service_status
;;
show_bridge_logs)
show_bridge_logs "$2"
;;
check_bridge_installation)
check_bridge_installation
;;
show_bridge_config)
show_bridge_config
;;
show_bridge_keys)
show_bridge_keys
;;
show_bridge_info)
show_bridge_info
;;
verify_bridge_prerequisites)
verify_bridge_prerequisites
;;
generate_bridge_keys)
generate_bridge_keys
;;
create_client_params)
create_client_params
;;
create_bridge_config)
create_bridge_config
;;
create_bridge_service)
create_bridge_service
;;
install_bridge_binary)
install_bridge_binary
;;
full_bridge_setup)
full_bridge_setup
;;
*)
echo "Usage: $0 [command] [options]"
echo ""
echo "Nym QUIC Bridge Deployment Helper Script"
echo ""
echo "Bridge Installation & Configuration:"
echo " check_bridge_installation - Check bridge installation status"
echo " show_bridge_config - Display bridge configuration files"
echo " show_bridge_keys - Display bridge key information"
echo " show_bridge_info - Show comprehensive bridge information"
echo " verify_bridge_prerequisites - Verify all prerequisites are met"
echo ""
echo "Bridge Setup Commands:"
echo " install_bridge_binary - Download and install nym-bridge binary"
echo " generate_bridge_keys - Generate ED25519 bridge identity keys"
echo " create_client_params - Create client_bridge_params.json"
echo " create_bridge_config - Create bridges.toml configuration"
echo " create_bridge_service - Create systemd service file"
echo " full_bridge_setup - Interactive full bridge setup wizard"
echo ""
echo "Network Configuration Commands:"
echo " adjust_ip_forwarding - Enable IPv4 and IPv6 forwarding"
echo " apply_bridge_iptables_rules - Apply iptables rules for QUIC bridge (nymwg)"
echo " configure_dns_and_icmp - Allow ICMP ping tests and configure DNS"
echo " remove_duplicate_bridge_rules - Remove duplicate iptables rules for nymwg"
echo ""
echo "Network Inspection Commands:"
echo " fetch_and_display_ipv6 - Show IPv6 on default network device"
echo " fetch_wg_ipv6_address - Fetch IPv6 for nymwg interface"
echo " check_bridge_iptables - Check iptables rules for nymwg"
echo " check_ipv6_ipv4_forwarding - Check IPv4 and IPv6 forwarding status"
echo " check_ip_routing - Display IP routing tables"
echo ""
echo "Testing Commands:"
echo " perform_pings - Test IPv4 and IPv6 connectivity"
echo " test_bridge_connectivity - Comprehensive bridge connectivity test"
echo ""
echo "Service Management Commands:"
echo " check_bridge_service_status - Check nym-bridge and nym-node service status"
echo " show_bridge_logs [lines] - Show recent nym-bridge logs (default: 50 lines)"
echo ""
echo "Quick Start:"
echo " 1. Run 'verify_bridge_prerequisites' to check prerequisites"
echo " 2. Run 'check_bridge_installation' to verify installation"
echo " 3. Run 'test_bridge_connectivity' to test connectivity"
echo ""
exit 1
;;
esac
echo "Operation '$1' completed successfully."
+23 -12
View File
@@ -31,6 +31,7 @@ use nym_crypto::hkdf::DerivationMaterial;
use nym_socks5_client_core::config::Socks5;
use nym_task::ShutdownTracker;
use nym_topology::provider_trait::TopologyProvider;
use nym_topology::RoutingNode;
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient, UserAgent};
use rand::rngs::OsRng;
use std::path::Path;
@@ -530,27 +531,37 @@ where
}
}
async fn new_gateway_setup(&self) -> Result<GatewaySetup, ClientCoreError> {
/// Attempt to retrieve list of all gateways available for registration
async fn available_gateways(&mut self) -> Result<Vec<RoutingNode>, ClientCoreError> {
if let Some(ref mut custom_provider) = self.custom_topology_provider {
if let Some(topology) = custom_provider.get_new_topology().await {
return Ok(topology.entry_gateways().cloned().collect());
}
}
let nym_api_endpoints = self.get_api_endpoints();
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway.clone(),
None,
self.force_tls,
);
let user_agent = self.user_agent.clone();
let topology_cfg = &self.config.debug_config.topology;
let user_agent = self.user_agent.clone();
let mut rng = OsRng;
let available_gateways = gateways_for_init(
gateways_for_init(
&mut rng,
&nym_api_endpoints,
user_agent,
topology_cfg.minimum_gateway_performance,
topology_cfg.ignore_ingress_epoch_role,
)
.await?;
.await
}
async fn new_gateway_setup(&mut self) -> Result<GatewaySetup, ClientCoreError> {
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway.clone(),
None,
self.force_tls,
);
let available_gateways = self.available_gateways().await?;
Ok(GatewaySetup::New {
specification: selection_spec,
+23 -11
View File
@@ -24,8 +24,6 @@ use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use tokio::sync::RwLockReadGuard;
use tokio_util::sync::CancellationToken;
use tokio_util::sync::WaitForCancellationFutureOwned;
/// Client connected to the Nym mixnet.
pub struct MixnetClient {
@@ -125,9 +123,9 @@ impl MixnetClient {
}
/// Get a child token of the root, to monitor unexpected shutdown, without causing one
pub fn cancellation_token(&self) -> CancellationToken {
self.shutdown_handle.child_shutdown_token().inner().clone()
}
// pub fn cancellation_token(&self) -> CancellationToken {
// self.shutdown_handle.child_shutdown_token().inner().clone()
// }
pub fn client_request_sender(&self) -> ClientRequestSender {
self.client_request_sender.clone()
@@ -200,6 +198,13 @@ impl MixnetClient {
self.client_state.topology_accessor.release_manual_control()
}
/// Returns a shutdown event handle that can be used for waiting for the client to shutdown.
pub fn shutdown_event(&self) -> ShutdownEventHandle {
ShutdownEventHandle {
shutdown_handle: self.shutdown_handle.clone(),
}
}
/// Wait for messages from the mixnet
pub async fn wait_for_messages(&mut self) -> Option<Vec<ReconstructedMessage>> {
self.reconstructed_receiver.next().await
@@ -274,12 +279,6 @@ impl MixnetClient {
}
}
}
pub fn cancelled(&self) -> WaitForCancellationFutureOwned {
self.shutdown_handle
.clone_shutdown_token()
.cancelled_owned()
}
}
#[derive(Clone)]
@@ -347,3 +346,16 @@ impl MixnetMessageSender for MixnetClientSender {
.map_err(|_| Error::MessageSendingFailure)
}
}
/// Handle for waiting on the shutdown event of the mixnet client.
pub struct ShutdownEventHandle {
shutdown_handle: ShutdownTracker,
}
impl ShutdownEventHandle {
/// Returns once mixnet client has been shut down.
/// If mixnet client is already shut down, returns immediately.
pub async fn wait(&self) {
self.shutdown_handle.wait_for_tracker().await
}
}