Compare commits

..

9 Commits

Author SHA1 Message Date
Dave Hrycyszyn 8486324e5e Getting ready to release v1.1.1 of nym-connect 2022-11-30 11:02:28 +00:00
Dave Hrycyszyn e4f34833ef Bumping final version numbers for 1.1.1 2022-11-29 17:22:33 +00:00
Dave Hrycyszyn 5044764a80 Changelog for v1.1.1 2022-11-29 17:21:05 +00:00
Dave Hrycyszyn c178438f06 Bumping version numbers 2022-11-29 17:18:57 +00:00
Fouad 22f3c8aa40 Update CHANGELOG.md 2022-11-29 14:57:04 +00:00
Jon Häggblad de2e721ba7 Fix typo in changelog 2022-11-29 15:36:54 +01:00
Jon Häggblad b94fbcb6db More entries in nym-connect CHANGELOG 2022-11-29 15:36:14 +01:00
Jon Häggblad 7735f64c6d Fix links in nym-connect changelog 2022-11-29 15:29:59 +01:00
Jon Häggblad 3857313808 Add socks5-client changes to nym-connect changelog 2022-11-29 15:19:34 +01:00
43 changed files with 255 additions and 632 deletions
+4 -4
View File
@@ -9,12 +9,12 @@ jobs:
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
# creates the matrix strategy from nightly_build_matrix_includes.json
# creates the matrix strategy from nightly_build_release_matrix.json
- uses: actions/checkout@v3
- id: set-matrix
uses: JoshuaTheMiller/conditional-build-matrix@main
with:
inputFile: '.github/workflows/nightly_build_matrix_includes.json'
inputFile: '.github/workflows/nightly_build_release_matrix.json'
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
get_release:
runs-on: ubuntu-latest
@@ -174,7 +174,7 @@ jobs:
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-targets -- -D warnings
notification:
needs: [build,get_release]
needs: build
runs-on: ubuntu-latest
steps:
- name: Collect jobs status
@@ -192,7 +192,7 @@ jobs:
NYM_PROJECT_NAME: "Nym nightly build on latest release"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "https://github.com/nymtech/nym/tree/${{needs.get_release.outputs.output1}}"
GIT_BRANCH: "${GITHUB_REF##*/}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
@@ -1,203 +0,0 @@
name: Nightly builds on second latest release
on:
schedule:
- cron: '24 2 * * *'
jobs:
matrix_prep:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
# creates the matrix strategy from nightly_build_matrix_includes.json
- uses: actions/checkout@v3
- id: set-matrix
uses: JoshuaTheMiller/conditional-build-matrix@main
with:
inputFile: '.github/workflows/nightly_build_matrix_includes.json'
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
get_release:
runs-on: ubuntu-latest
needs: matrix_prep
outputs:
output1: ${{ steps.step2.outputs.latest_release }}
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Fetch all branches
run: git fetch --all
- name: Set output variable to latest release branch
id: step2
run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+' | tail -n 2 | head -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT
build:
needs: [get_release,matrix_prep]
strategy:
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.rust == 'stable' }}
steps:
- name: Install Dependencies (Linux)
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
if: matrix.os == 'ubuntu-latest'
- name: Check out latest release branch
uses: actions/checkout@v3
with:
ref: ${{needs.get_release.outputs.output1}}
- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
components: rustfmt, clippy
- name: Build all binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run expensive tests
if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master'
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --all-features -- --ignored
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- uses: actions-rs/clippy-check@v1
name: Clippy checks
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
- name: Run clippy
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets -- -D warnings
- name: Reclaim some disk space
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-latest' }}
with:
command: clean
# COCONUT stuff
- name: Build all binaries with coconut enabled
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run all tests with coconut enabled
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace --features=coconut
- name: Reclaim some disk space (because Windows is being annoying)
uses: actions-rs/cargo@v1
if: ${{ matrix.os == 'windows-latest' }}
with:
command: clean
- name: Run clippy with coconut enabled
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --workspace --all-targets --features=coconut -- -D warnings
# nym-wallet (the rust part)
- name: Build nym-wallet rust code
uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path nym-wallet/Cargo.toml --workspace
- name: Run nym-wallet tests
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path nym-wallet/Cargo.toml --workspace
- name: Check nym-wallet formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path nym-wallet/Cargo.toml --all -- --check
- name: Run clippy for nym-wallet
uses: actions-rs/cargo@v1
if: ${{ matrix.rust != 'nightly' }}
with:
command: clippy
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-targets -- -D warnings
notification:
needs: [build,get_release]
runs-on: ubuntu-latest
steps:
- name: Collect jobs status
uses: technote-space/workflow-conclusion-action@v2
- name: Check out repository code
uses: actions/checkout@v3
- name: Keybase - Node Install
if: env.WORKFLOW_CONCLUSION == 'failure'
run: npm install
working-directory: .github/workflows/support-files
- name: Keybase - Send Notification
if: env.WORKFLOW_CONCLUSION == 'failure'
env:
NYM_NOTIFICATION_KIND: nightly
NYM_PROJECT_NAME: "Nym nightly build on latest release"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "https://github.com/nymtech/nym/tree/${{needs.get_release.outputs.output1}}"
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
@@ -0,0 +1,50 @@
[
{
"os":"ubuntu-latest",
"rust":"stable",
"runOnEvent":"workflow_dispatch"
},
{
"os":"windows-latest",
"rust":"stable",
"runOnEvent":"workflow_dispatch"
},
{
"os":"macos-latest",
"rust":"stable",
"runOnEvent":"workflow_dispatch"
},
{
"os":"ubuntu-latest",
"rust":"beta",
"runOnEvent":"workflow_dispatch"
},
{
"os":"windows-latest",
"rust":"beta",
"runOnEvent":"workflow_dispatch"
},
{
"os":"macos-latest",
"rust":"beta",
"runOnEvent":"workflow_dispatch"
},
{
"os":"ubuntu-latest",
"rust":"nightly",
"runOnEvent":"workflow_dispatch"
},
{
"os":"windows-latest",
"rust":"nightly",
"runOnEvent":"workflow_dispatch"
},
{
"os":"macos-latest",
"rust":"nightly",
"runOnEvent":"workflow_dispatch"
}
]
+1 -6
View File
@@ -2,7 +2,7 @@
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29)
### Added
@@ -17,11 +17,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- clients,validator-api: take coconut signers from the chain instead of specifying them via CLI ([#1747])
- multisig contract: add DKG contract to the list of addresses that can create proposals ([#1747])
- socks5-client: wait closing inbound connection until data is sent, and throttle incoming data in general ([#1783])
- nym-cli: improve error reporting/handling and changed `vesting-schedule` queries to use query client instead of signing client
### Fixed
- gateway-client: fix decrypting stored messages on reconnect ([#1786])
### Fixed
Generated
+8 -10
View File
@@ -586,7 +586,7 @@ dependencies = [
[[package]]
name = "client-core"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"client-connections",
"config",
@@ -1633,7 +1633,7 @@ dependencies = [
[[package]]
name = "explorer-api"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"chrono",
"clap 3.2.8",
@@ -3139,7 +3139,6 @@ dependencies = [
"pretty_env_logger",
"serde",
"serde_json",
"tap",
"tokio",
"validator-client",
]
@@ -3165,7 +3164,6 @@ dependencies = [
"rand 0.6.5",
"serde",
"serde_json",
"tap",
"thiserror",
"time 0.3.14",
"toml",
@@ -3176,7 +3174,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"clap 3.2.8",
"client-connections",
@@ -3216,7 +3214,7 @@ dependencies = [
[[package]]
name = "nym-gateway"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"anyhow",
"async-trait",
@@ -3263,7 +3261,7 @@ dependencies = [
[[package]]
name = "nym-mixnode"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"anyhow",
"bs58",
@@ -3305,7 +3303,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"async-trait",
"clap 3.2.8",
@@ -3353,7 +3351,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"clap 3.2.8",
"client-connections",
@@ -3420,7 +3418,7 @@ dependencies = [
[[package]]
name = "nym-validator-api"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"anyhow",
"async-trait",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "client-core"
version = "1.1.0"
version = "1.1.1"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.0"
version = "1.1.1"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.0"
version = "1.1.1"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021"
@@ -42,28 +42,19 @@ pub struct StringMessage {
/// Create a new binary message with a user-specified `kind`.
#[wasm_bindgen]
pub fn create_binary_message(kind: u8, payload: Vec<u8>, headers: Option<String>) -> Vec<u8> {
create_binary_message_with_headers(kind, payload, headers)
pub fn create_binary_message(kind: u8, payload: Vec<u8>) -> Vec<u8> {
create_binary_message_with_headers(kind, payload, "".to_string())
}
/// Create a new message with a UTF-8 encoded string `payload` and a user-specified `kind`.
#[wasm_bindgen]
pub fn create_binary_message_from_string(
kind: u8,
payload: String,
headers: Option<String>,
) -> Vec<u8> {
create_binary_message_with_headers(kind, payload.as_bytes().to_vec(), headers)
pub fn create_binary_message_from_string(kind: u8, payload: String) -> Vec<u8> {
create_binary_message_with_headers(kind, payload.as_bytes().to_vec(), "".to_string())
}
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
#[wasm_bindgen]
pub fn create_binary_message_with_headers(
kind: u8,
payload: Vec<u8>,
headers: Option<String>,
) -> Vec<u8> {
let headers = headers.unwrap_or_else(|| "".to_string());
pub fn create_binary_message_with_headers(kind: u8, payload: Vec<u8>, headers: String) -> Vec<u8> {
let headers = headers.as_bytes().to_vec();
let size = (headers.len() as u64).to_be_bytes().to_vec();
vec![vec![kind], size, headers, payload].concat()
@@ -178,7 +169,7 @@ mod tests {
let message_as_bytes = create_binary_message_with_headers(
42u8,
vec![0u8, 1u8, 2u8],
Some("test headers".to_string()),
"test headers".to_string(),
);
// calculate header size
@@ -206,7 +197,7 @@ mod tests {
#[wasm_bindgen_test]
fn test_binary_with_empty_headers() {
let message_as_bytes =
create_binary_message_with_headers(42u8, vec![0u8, 1u8, 2u8], Some("".to_string()));
create_binary_message_with_headers(42u8, vec![0u8, 1u8, 2u8], "".to_string());
let expected_size = 0;
-2
View File
@@ -9,8 +9,6 @@ pub mod binary_message_helper;
mod client;
#[cfg(target_arch = "wasm32")]
pub mod gateway_selector;
#[cfg(target_arch = "wasm32")]
pub mod validation;
#[wasm_bindgen]
pub fn set_panic_hook() {
-35
View File
@@ -1,35 +0,0 @@
use nymsphinx::addressing::clients::Recipient;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn validate_recipient(recipient: String) -> Result<(), JsError> {
match Recipient::try_from_base58_string(recipient) {
Ok(_) => Ok(()),
Err(e) => Err(JsError::new(format!("{}", e).as_str())),
}
}
#[cfg(test)]
mod tests {
use super::validate_recipient;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_recipient_validation_ok() {
let res = validate_recipient("DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string());
assert!(res.is_ok())
}
#[wasm_bindgen_test]
fn test_recipient_validation_fails() {
assert!(validate_recipient(" DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string()).is_err());
assert!(validate_recipient(
"DyQmXnst5NGGjzUZxRC5BjbRiizr2.GH6YTBP2NXU3AVqd8WD@336yuXAeGEgedRfqTJZQH1bHv1SjCZYarc9"
.to_string()
)
.is_err());
assert!(validate_recipient("🙀🙀🙀🙀".to_string()).is_err());
assert!(validate_recipient("".to_string()).is_err());
assert!(validate_recipient(" ".to_string()).is_err());
}
}
@@ -14,7 +14,7 @@ use futures::{FutureExt, SinkExt, StreamExt};
use gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
use gateway_requests::iv::IV;
use gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse, PROTOCOL_VERSION};
use gateway_requests::{BinaryRequest, ClientControlRequest, ServerResponse};
use log::*;
use network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN};
use nymsphinx::forwarding::packet::MixPacket;
@@ -447,33 +447,6 @@ impl GatewayClient {
}
}
fn check_gateway_protocol(
&self,
gateway_protocol: Option<u8>,
) -> Result<(), GatewayClientError> {
// right now there are no failure cases here, but this might change in the future
match gateway_protocol {
None => {
warn!("the gateway we're connected to has not specified its protocol version. It's probably running version < 1.1.X, but that's still fine for now. It will become a hard error in 1.2.0");
// note: in 1.2.0 we will have to return a hard error here
Ok(())
}
Some(v) if v != PROTOCOL_VERSION => {
let err = GatewayClientError::IncompatibleProtocol {
gateway: Some(v),
current: PROTOCOL_VERSION,
};
error!("{err}");
Err(err)
}
Some(_) => {
info!("the gateway is using exactly the same protocol version as we are. We're good to continue!");
Ok(())
}
}
}
async fn register(&mut self) -> Result<(), GatewayClientError> {
if !self.connection.is_established() {
return Err(GatewayClientError::ConnectionNotEstablished);
@@ -496,20 +469,11 @@ impl GatewayClient {
.map_err(GatewayClientError::RegistrationFailure),
_ => unreachable!(),
}?;
let (authentication_status, gateway_protocol) = match self.read_control_response().await? {
ServerResponse::Register {
protocol_version,
status,
} => (status, protocol_version),
ServerResponse::Error { message } => {
return Err(GatewayClientError::GatewayError(message))
}
_ => return Err(GatewayClientError::UnexpectedResponse),
};
self.check_gateway_protocol(gateway_protocol)?;
self.authenticated = authentication_status;
self.authenticated = match self.read_control_response().await? {
ServerResponse::Register { status } => Ok(status),
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
_ => Err(GatewayClientError::UnexpectedResponse),
}?;
if self.authenticated {
self.shared_key = Some(Arc::new(shared_key));
}
@@ -548,11 +512,9 @@ impl GatewayClient {
match self.send_websocket_message(msg).await? {
ServerResponse::Authenticate {
protocol_version,
status,
bandwidth_remaining,
} => {
self.check_gateway_protocol(protocol_version)?;
self.authenticated = status;
self.bandwidth_remaining = bandwidth_remaining;
Ok(())
@@ -85,9 +85,6 @@ pub enum GatewayClientError {
#[error("Failed to send mixnet message")]
MixnetMsgSenderFailedToSend,
#[error("Attempted to negotiate connection with gateway using incompatible protocol version. Ours is {current} and the gateway reports {gateway:?}")]
IncompatibleProtocol { gateway: Option<u8>, current: u8 },
}
impl GatewayClientError {
-1
View File
@@ -22,7 +22,6 @@ thiserror = "1"
time = { version = "0.3.6", features = ["parsing", "formatting"] }
toml = "0.5.6"
url = "2.2"
tap = "1"
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
cosmwasm-std = { version = "1.0.0" }
-6
View File
@@ -15,10 +15,4 @@ pub enum ContextError {
// TODO: improve this to return known errors
#[error("failed to create client - {0}")]
NymdError(String),
#[error("{0}")]
NymdErrorPassthrough(#[from] validator_client::nymd::error::NymdError),
#[error("{0}")]
ValidatorClientError(#[from] validator_client::ValidatorClientError),
}
+4 -5
View File
@@ -6,7 +6,6 @@ use network_defaults::{
var_names::{API_VALIDATOR, MIXNET_CONTRACT_ADDRESS, NYMD_VALIDATOR, VESTING_CONTRACT_ADDRESS},
NymNetworkDetails,
};
use tap::prelude::*;
use validator_client::nymd::{self, AccountId, NymdClient, QueryNymdClient, SigningNymdClient};
pub use validator_client::validator_api::Client as ValidatorApiClient;
@@ -59,7 +58,7 @@ pub fn create_signing_client(
network_details: &NymNetworkDetails,
) -> Result<SigningClient, ContextError> {
let client_config = nymd::Config::try_from_nym_network_details(network_details)
.tap_err(|e| log::error!("Failed to get client config - {:?}", e))?;
.expect("failed to construct valid validator client config with the provided network");
// get mnemonic
let mnemonic = match std::env::var("MNEMONIC") {
@@ -88,7 +87,7 @@ pub fn create_query_client(
network_details: &NymNetworkDetails,
) -> Result<QueryClient, ContextError> {
let client_config = nymd::Config::try_from_nym_network_details(network_details)
.tap_err(|e| log::error!("Failed to get client config - {:?}", e))?;
.expect("failed to construct valid validator client config with the provided network");
let nymd_url = network_details
.endpoints
@@ -108,7 +107,7 @@ pub fn create_signing_client_with_validator_api(
network_details: &NymNetworkDetails,
) -> Result<SigningClientWithValidatorAPI, ContextError> {
let client_config = validator_client::Config::try_from_nym_network_details(network_details)
.tap_err(|e| log::error!("Failed to get client config - {:?}", e))?;
.expect("failed to construct valid validator client config with the provided network");
// get mnemonic
let mnemonic = match std::env::var("MNEMONIC") {
@@ -130,7 +129,7 @@ pub fn create_query_client_with_validator_api(
network_details: &NymNetworkDetails,
) -> Result<QueryClientWithValidatorAPI, ContextError> {
let client_config = validator_client::Config::try_from_nym_network_details(network_details)
.tap_err(|e| log::error!("Failed to get client config - {:?}", e))?;
.expect("failed to construct valid validator client config with the provided network");
match validator_client::client::Client::new_query(client_config) {
Ok(client) => Ok(client),
@@ -3,11 +3,11 @@
use clap::Parser;
use cosmrs::AccountId;
use log::{error, info};
use log::info;
use validator_client::nymd::{Coin, VestingQueryClient};
use crate::context::QueryClient;
use crate::context::SigningClient;
use crate::utils::show_error;
use crate::utils::{pretty_coin, pretty_cosmwasm_coin};
@@ -18,16 +18,8 @@ pub struct Args {
pub address: Option<AccountId>,
}
pub async fn balance(args: Args, client: QueryClient, address_from_mnemonic: Option<AccountId>) {
if args.address.is_none() && address_from_mnemonic.is_none() {
error!("Please specify an account address or a mnemonic to get the balance for");
return;
}
let account_id = args
.address
.unwrap_or_else(|| address_from_mnemonic.expect("please provide a mnemonic"));
pub async fn balance(args: Args, client: SigningClient) {
let account_id = args.address.unwrap_or_else(|| client.address().clone());
let vesting_address = account_id.to_string();
let denom = client.current_chain_details().mix_denom.base.as_str();
@@ -4,11 +4,11 @@
use clap::Parser;
use cosmrs::AccountId;
use cosmwasm_std::Coin as CosmWasmCoin;
use log::{error, info};
use log::info;
use validator_client::nymd::{Coin, VestingQueryClient};
use crate::context::QueryClient;
use crate::context::SigningClient;
use crate::utils::show_error;
use crate::utils::{pretty_coin, pretty_cosmwasm_coin};
@@ -19,18 +19,8 @@ pub struct Args {
pub address: Option<AccountId>,
}
pub async fn query(args: Args, client: QueryClient, address_from_mnemonic: Option<AccountId>) {
if args.address.is_none() && address_from_mnemonic.is_none() {
error!("Please specify an account address or a mnemonic to get the balance for");
return;
}
let account_id = args
.address
.unwrap_or_else(|| address_from_mnemonic.expect("please provide a mnemonic"));
info!("Checking account {} for a vesting schedule...", account_id);
pub async fn query(args: Args, client: SigningClient) {
let account_id = args.address.unwrap_or_else(|| client.address().clone());
let vesting_address = account_id.to_string();
let denom = client.current_chain_details().mix_denom.base.as_str();
+20
View File
@@ -0,0 +1,20 @@
CONFIGURED=true
RUST_LOG=info
RUST_BACKTRACE=1
BECH32_PREFIX=n
MIX_DENOM=unym
MIX_DENOM_DISPLAY=nym
STAKE_DENOM=unyx
STAKE_DENOM_DISPLAY=nyx
DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g
VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
MULTISIG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://127.0.0.1:8090"
NYMD_VALIDATOR="https://rpc.nyx.nodes.guru/"
API_VALIDATOR="https://validator.nymtech.net/api/"
+20
View File
@@ -0,0 +1,20 @@
CONFIGURED=true
RUST_LOG=info
RUST_BACKTRACE=1
BECH32_PREFIX=n
MIX_DENOM=unym
MIX_DENOM_DISPLAY=nym
STAKE_DENOM=unyx
STAKE_DENOM_DISPLAY=nyx
DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep
VESTING_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw
MULTISIG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs
REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYMD_VALIDATOR="https://qa-validator.nymtech.net"
API_VALIDATOR="https://qa-validator-api.nymtech.net/api"
-8
View File
@@ -85,10 +85,6 @@ pub fn export_to_env() {
var_names::MULTISIG_CONTRACT_ADDRESS,
MULTISIG_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::COCONUT_DKG_CONTRACT_ADDRESS,
COCONUT_DKG_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
@@ -129,10 +125,6 @@ pub fn export_to_env_if_not_set() {
var_names::MULTISIG_CONTRACT_ADDRESS,
MULTISIG_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::COCONUT_DKG_CONTRACT_ADDRESS,
COCONUT_DKG_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
+7 -3
View File
@@ -209,14 +209,18 @@ impl NymTopology {
#[must_use]
pub fn filter_system_version(&self, expected_version: &str) -> Self {
self.filter_node_versions(expected_version)
self.filter_node_versions(expected_version, expected_version)
}
#[must_use]
pub fn filter_node_versions(&self, expected_mix_version: &str) -> Self {
pub fn filter_node_versions(
&self,
expected_mix_version: &str,
expected_gateway_version: &str,
) -> Self {
NymTopology {
mixes: self.mixes.filter_by_version(expected_mix_version),
gateways: self.gateways.clone(),
gateways: self.gateways.filter_by_version(expected_gateway_version),
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "explorer-api"
version = "1.1.0"
version = "1.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+1 -1
View File
@@ -34,7 +34,7 @@ export const MobileNav: React.FC<{ children: React.ReactNode }> = ({ children }:
const { navState, updateNavState } = useMainContext();
const [drawerOpen, setDrawerOpen] = React.useState(false);
// Set maintenance banner to false by default to don't display it
const [openMaintenance, setOpenMaintenance] = React.useState(false);
const [openMaintenance, setOpenMaintenance] = React.useState(true);
const toggleDrawer = () => {
setDrawerOpen(!drawerOpen);
+1 -1
View File
@@ -235,7 +235,7 @@ export const Nav: React.FC = ({ children }) => {
const [drawerIsOpen, setDrawerToOpen] = React.useState(false);
const [fixedOpen, setFixedOpen] = React.useState(false);
// Set maintenance banner to false by default to don't display it
const [openMaintenance, setOpenMaintenance] = React.useState(false);
const [openMaintenance, setOpenMaintenance] = React.useState(true);
const theme = useTheme();
const setToActive = (id: number) => {
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-gateway"
version = "1.1.0"
version = "1.1.1"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+1 -5
View File
@@ -1,4 +1,4 @@
// Copyright 2020-2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use crypto::generic_array;
@@ -12,10 +12,6 @@ pub mod iv;
pub mod registration;
pub mod types;
/// Defines the current version of the communication protocol between gateway and clients.
/// It has to be incremented for any breaking change.
pub const PROTOCOL_VERSION: u8 = 1;
pub type GatewayMac = HmacOutput<GatewayIntegrityHmacAlgorithm>;
// TODO: could using `Mac` trait here for OutputSize backfire?
@@ -210,10 +210,7 @@ impl<'a, S> State<'a, S> {
match msg {
WsMessage::Text(ws_msg) => match types::RegistrationHandshake::try_from(ws_msg) {
Ok(reg_handshake_msg) => return match reg_handshake_msg {
// hehe, that's a bit disgusting that the type system requires we explicitly ignore the
// protocol_version field that we actually never attach at this point
// yet another reason for the overdue refactor
types::RegistrationHandshake::HandshakePayload { data, .. } => Ok(data),
types::RegistrationHandshake::HandshakePayload { data } => Ok(data),
types::RegistrationHandshake::HandshakeError { message } => Err(HandshakeError::RemoteError(message)),
},
Err(_) => error!("Received a non-handshake message during the registration handshake! It's getting dropped."),
+7 -48
View File
@@ -4,7 +4,7 @@
use crate::authentication::encrypted_address::EncryptedAddressBytes;
use crate::iv::IV;
use crate::registration::handshake::SharedKeys;
use crate::{GatewayMacSize, PROTOCOL_VERSION};
use crate::GatewayMacSize;
use crypto::generic_array::typenum::Unsigned;
use crypto::hmac::recompute_keyed_hmac_and_verify_tag;
use crypto::symmetric::stream_cipher;
@@ -28,22 +28,13 @@ use credentials::token::bandwidth::TokenCredential;
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum RegistrationHandshake {
HandshakePayload {
#[serde(default)]
protocol_version: Option<u8>,
data: Vec<u8>,
},
HandshakeError {
message: String,
},
HandshakePayload { data: Vec<u8> },
HandshakeError { message: String },
}
impl RegistrationHandshake {
pub fn new_payload(data: Vec<u8>) -> Self {
RegistrationHandshake::HandshakePayload {
protocol_version: Some(PROTOCOL_VERSION),
data,
}
RegistrationHandshake::HandshakePayload { data }
}
pub fn new_error<S: Into<String>>(message: S) -> Self {
@@ -124,16 +115,12 @@ pub enum ClientControlRequest {
// TODO: should this also contain a MAC considering that at this point we already
// have the shared key derived?
Authenticate {
#[serde(default)]
protocol_version: Option<u8>,
address: String,
enc_address: String,
iv: String,
},
#[serde(alias = "handshakePayload")]
RegisterHandshakeInitRequest {
#[serde(default)]
protocol_version: Option<u8>,
data: Vec<u8>,
},
BandwidthCredential {
@@ -150,7 +137,6 @@ impl ClientControlRequest {
iv: IV,
) -> Self {
ClientControlRequest::Authenticate {
protocol_version: Some(PROTOCOL_VERSION),
address: address.as_base58_string(),
enc_address: enc_address.to_base58_string(),
iv: iv.to_base58_string(),
@@ -237,14 +223,10 @@ impl TryInto<String> for ClientControlRequest {
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ServerResponse {
Authenticate {
#[serde(default)]
protocol_version: Option<u8>,
status: bool,
bandwidth_remaining: i64,
},
Register {
#[serde(default)]
protocol_version: Option<u8>,
status: bool,
},
Bandwidth {
@@ -399,37 +381,14 @@ mod tests {
#[test]
fn handshake_payload_can_be_deserialized_into_register_handshake_init_request() {
let handshake_data = vec![1, 2, 3, 4, 5, 6];
let handshake_payload_with_protocol = RegistrationHandshake::HandshakePayload {
protocol_version: Some(42),
let handshake_payload = RegistrationHandshake::HandshakePayload {
data: handshake_data.clone(),
};
let serialized = serde_json::to_string(&handshake_payload_with_protocol).unwrap();
let serialized = serde_json::to_string(&handshake_payload).unwrap();
let deserialized = ClientControlRequest::try_from(serialized).unwrap();
match deserialized {
ClientControlRequest::RegisterHandshakeInitRequest {
protocol_version,
data,
} => {
assert_eq!(protocol_version, Some(42));
assert_eq!(data, handshake_data)
}
_ => unreachable!("this branch shouldn't have been reached!"),
}
let handshake_payload_without_protocol = RegistrationHandshake::HandshakePayload {
protocol_version: None,
data: handshake_data.clone(),
};
let serialized = serde_json::to_string(&handshake_payload_without_protocol).unwrap();
let deserialized = ClientControlRequest::try_from(serialized).unwrap();
match deserialized {
ClientControlRequest::RegisterHandshakeInitRequest {
protocol_version,
data,
} => {
assert!(protocol_version.is_none());
ClientControlRequest::RegisterHandshakeInitRequest { data } => {
assert_eq!(data, handshake_data)
}
_ => unreachable!("this branch shouldn't have been reached!"),
@@ -18,7 +18,7 @@ use gateway_requests::iv::{IVConversionError, IV};
use gateway_requests::registration::handshake::error::HandshakeError;
use gateway_requests::registration::handshake::{gateway_handshake, SharedKeys};
use gateway_requests::types::{ClientControlRequest, ServerResponse};
use gateway_requests::{BinaryResponse, PROTOCOL_VERSION};
use gateway_requests::BinaryResponse;
use log::*;
use mixnet_client::forwarder::MixForwardingSender;
use nymsphinx::DestinationAddressBytes;
@@ -55,9 +55,6 @@ enum InitialAuthenticationError {
#[error("Experienced connection error - {0}")]
ConnectionError(#[from] WsError),
#[error("Attempted to negotiate connection with client using incompatible protocol version. Ours is {current} and the client reports {client:?}")]
IncompatibleProtocol { client: Option<u8>, current: u8 },
}
impl InitialAuthenticationError {
@@ -282,7 +279,10 @@ where
// push them to the client
if let Err(err) = self.push_packets_to_client(shared_keys, messages).await {
warn!("We failed to send stored messages to fresh client - {err}",);
warn!(
"We failed to send stored messages to fresh client - {}",
err
);
return Err(InitialAuthenticationError::ConnectionError(err));
} else {
// if it was successful - remove them from the store
@@ -342,33 +342,6 @@ where
}
}
fn check_client_protocol(
&self,
client_protocol: Option<u8>,
) -> Result<(), InitialAuthenticationError> {
// right now there are no failure cases here, but this might change in the future
match client_protocol {
None => {
warn!("the client we're connected to has not specified its protocol version. It's probably running version < 1.1.X, but that's still fine for now. It will become a hard error in 1.2.0");
// note: in 1.2.0 we will have to return a hard error here
Ok(())
}
Some(v) if v != PROTOCOL_VERSION => {
let err = InitialAuthenticationError::IncompatibleProtocol {
client: Some(v),
current: PROTOCOL_VERSION,
};
error!("{err}");
Err(err)
}
Some(_) => {
info!("the client is using exactly the same protocol version as we are. We're good to continue!");
Ok(())
}
}
}
/// Using the received challenge data, i.e. client's address as well the ciphertext of it plus
/// a fresh IV, attempts to authenticate the client by checking whether the ciphertext matches
/// the expected value if encrypted with the shared key.
@@ -416,7 +389,6 @@ where
/// * `iv`: fresh IV received with the request.
async fn handle_authenticate(
&mut self,
client_protocol_version: Option<u8>,
address: String,
enc_address: String,
iv: String,
@@ -424,8 +396,6 @@ where
where
S: AsyncRead + AsyncWrite + Unpin,
{
self.check_client_protocol(client_protocol_version)?;
let address = DestinationAddressBytes::try_from_base58_string(address)
.map_err(|err| InitialAuthenticationError::MalformedClientAddress(err.to_string()))?;
let encrypted_address = EncryptedAddressBytes::try_from_base58_string(enc_address)?;
@@ -450,7 +420,6 @@ where
Ok(InitialAuthResult::new(
client_details,
ServerResponse::Authenticate {
protocol_version: Some(PROTOCOL_VERSION),
status,
bandwidth_remaining,
},
@@ -505,14 +474,11 @@ where
/// * `init_data`: init payload of the registration handshake.
async fn handle_register(
&mut self,
client_protocol_version: Option<u8>,
init_data: Vec<u8>,
) -> Result<InitialAuthResult, InitialAuthenticationError>
where
S: AsyncRead + AsyncWrite + Unpin + Send,
{
self.check_client_protocol(client_protocol_version)?;
let remote_identity = Self::extract_remote_identity_from_register_init(&init_data)?;
let remote_address = remote_identity.derive_destination_address();
@@ -527,10 +493,7 @@ where
Ok(InitialAuthResult::new(
Some(client_details),
ServerResponse::Register {
protocol_version: Some(PROTOCOL_VERSION),
status,
},
ServerResponse::Register { status },
))
}
@@ -550,18 +513,13 @@ where
if let Ok(request) = ClientControlRequest::try_from(raw_request) {
match request {
ClientControlRequest::Authenticate {
protocol_version,
address,
enc_address,
iv,
} => {
self.handle_authenticate(protocol_version, address, enc_address, iv)
.await
} => self.handle_authenticate(address, enc_address, iv).await,
ClientControlRequest::RegisterHandshakeInitRequest { data } => {
self.handle_register(data).await
}
ClientControlRequest::RegisterHandshakeInitRequest {
protocol_version,
data,
} => self.handle_register(protocol_version, data).await,
// won't accept anything else (like bandwidth) without prior authentication
_ => Err(InitialAuthenticationError::InvalidRequest),
}
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-mixnode"
version = "1.1.0"
version = "1.1.1"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
+21 -1
View File
@@ -1,3 +1,23 @@
## [nym-connect-v1.1.1](https://github.com/nymtech/nym/tree/nym-connect-v1.1.1) (2022-11-29)
- socks5-client: fix multiplex concurrent connections ([#1720], [#1777])
- socks5-client: fix wait closing inbound connection until data is sent, and throttle incoming data in general ([#1772], [#1783],[#1789])
- socks5-client: fix shutting down all background workers if anyone of them panics or errors out. This fixes an issue where the nym-connect UI was showing connected even though the socks5 tunnel was non-functional. ([#1805])
- gateway-libs: fix decryping messages stored on the gateway between reconnects ([#1786])
- nymconnect: updated UI
- nymconnect: new help area
- nymconnect: listen for service errors and display on frontend
[#1720]: https://github.com/nymtech/nym/pull/1720
[#1772]: https://github.com/nymtech/nym/pull/1772
[#1777]: https://github.com/nymtech/nym/pull/1777
[#1783]: https://github.com/nymtech/nym/pull/1783
[#1786]: https://github.com/nymtech/nym/pull/1786
[#1789]: https://github.com/nymtech/nym/pull/1789
[#1805]: https://github.com/nymtech/nym/pull/1805
## [nym-connect-v1.1.0](https://github.com/nymtech/nym/tree/nym-connect-v1.1.0) (2022-11-09)
- nym-connect: rework of rewarding changes the directory data structures that describe the mixnet topology ([#1472])
@@ -39,4 +59,4 @@
- nym-connect: reuse config id instead of creating a new id on each connection
[#1427]: https://github.com/nymtech/nym/pull/1427
[#1427]: https://github.com/nymtech/nym/pull/1427
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@nym/nym-connect",
"version": "1.0.0",
"version": "1.1.1",
"main": "index.js",
"license": "MIT",
"scripts": {
@@ -107,4 +107,4 @@
"webpack-favicons": "^1.3.8",
"webpack-merge": "^5.8.0"
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-connect"
version = "1.1.0"
version = "1.1.1"
description = "nym-connect"
authors = ["Nym Technologies SA"]
license = ""
+12 -4
View File
@@ -1,7 +1,7 @@
{
"package": {
"productName": "nym-connect",
"version": "1.1.0"
"version": "1.1.1"
},
"build": {
"distDir": "../dist",
@@ -19,7 +19,13 @@
"active": true,
"targets": "all",
"identifier": "net.nymtech.connect",
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"resources": [],
"externalBin": [],
"copyright": "Copyright © 2021-2022 Nym Technologies SA",
@@ -44,7 +50,9 @@
},
"updater": {
"active": true,
"endpoints": ["https://nymtech.net/.wellknown/connect/updater.json"],
"endpoints": [
"https://nymtech.net/.wellknown/connect/updater.json"
],
"dialog": true,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IENCNzQ2M0E5N0VFODE2NApSV1JrZ2U2WE9rYTNETTg1OTBKdE5uWUEra0hML2syOVUvQ2lxZmFZRzZ1T3NWbGM0eVRzUTVhVwo="
},
@@ -74,4 +82,4 @@
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'"
}
}
}
}
@@ -5,12 +5,9 @@ import {
Chip,
CircularProgress,
Container,
FormControlLabel,
FormGroup,
InputAdornment,
Link,
Stack,
Switch,
TextField,
Tooltip,
Typography,
@@ -23,8 +20,6 @@ import CallReceivedIcon from '@mui/icons-material/CallReceived';
import PersonIcon from '@mui/icons-material/Person';
import PersonOffIcon from '@mui/icons-material/PersonOff';
import ErrorIcon from '@mui/icons-material/Error';
import VisibilityIcon from '@mui/icons-material/Visibility';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import { NymLogo } from '@nymproject/react/logo/NymLogo';
import { NymThemeProvider } from '@nymproject/mui-theme';
import { useTheme } from '@mui/material/styles';
@@ -33,10 +28,9 @@ import { DropzoneDialog } from 'react-mui-dropzone';
import UploadFileIcon from '@mui/icons-material/UploadFile';
import ArticleIcon from '@mui/icons-material/Article';
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
import { Headers } from '@nymproject/sdk';
import { ThemeToggle } from './ThemeToggle';
import { AppContextProvider, useAppContext } from './context';
import { BinaryMessageHeaders, MixnetContextProvider, useMixnetContext } from './context/mixnet';
import { MixnetContextProvider, parseBinaryMessageHeaders, useMixnetContext } from './context/mixnet';
export const AppTheme: React.FC = ({ children }) => {
const { mode } = useAppContext();
@@ -51,7 +45,6 @@ interface Log {
fileDownloadUrl?: string;
filesize?: number;
timestamp: Date;
headers?: Headers;
}
interface UploadState {
@@ -59,48 +52,11 @@ interface UploadState {
files: File[];
}
const ClientAddress: React.FC<{ label?: string; tooltip?: string; address?: string }> = ({
label,
address,
tooltip,
}) => {
const copy = useClipboard();
if (!address) {
return <Chip label="Anonymous" icon={<VisibilityOffIcon />} />;
}
const addressShort = `${address.slice(0, 24)}...`;
return (
<Tooltip arrow title={tooltip || ''}>
<Chip
clickable
label={
label ? (
<>
<strong>{label}</strong> {addressShort}
</>
) : (
<>{addressShort}</>
)
}
onClick={() => {
if (address) {
copy.copy(address);
}
}}
icon={<ContentCopyIcon />}
/>
</Tooltip>
);
};
export const Content: React.FC = () => {
const theme = useTheme();
const { isReady, address, connect, events, sendTextMessage, sendBinaryMessage } = useMixnetContext();
const copy = useClipboard();
const [revealSenderAddress, setRevealSenderAddress] = React.useState(false);
const [sendToSelf, setSendToSelf] = React.useState(false);
const [recipient, setRecipient] = React.useState<string>();
const handleRecipientChange = (event: React.ChangeEvent<HTMLInputElement>) => {
@@ -138,8 +94,13 @@ export const Content: React.FC = () => {
React.useEffect(() => {
if (isReady) {
const validatorApiUrl = 'https://validator.nymtech.net/api';
const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
// // mixnet v1
// const validatorApiUrl = 'https://validator.nymtech.net/api';
// const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
// mixnet v2
const validatorApiUrl = 'https://qwerty-validator-api.qa.nymte.ch/api'; // "http://localhost:8081";
const preferredGatewayIdentityKey = undefined; // '36vfvEyBzo5cWEFbnP7fqgY39kFw9PQhvwzbispeNaxL';
connect({
clientId: 'Example Client',
@@ -156,7 +117,6 @@ export const Content: React.FC = () => {
kind: 'rx',
timestamp: new Date(),
message: e.args.payload,
headers: e.args.headers,
});
setLogTrigger(Date.now());
});
@@ -182,12 +142,8 @@ export const Content: React.FC = () => {
React.useEffect(() => {
if (events) {
const unsubcribe = events.subscribeToBinaryMessageReceivedEvent((e) => {
if (!e.args.headers) {
console.error('Expected headers, got undefined 😢', e.args);
return;
}
const headers = e.args.headers as BinaryMessageHeaders;
// the headers will be JSON (see the mixnet context for how they are created), so parse them
const headers = parseBinaryMessageHeaders(e.args.headers);
const blob = new Blob([new Uint8Array(e.args.payload)], { type: headers.mimeType });
log.current.push({
@@ -196,7 +152,6 @@ export const Content: React.FC = () => {
filename: headers.filename,
fileDownloadUrl: URL.createObjectURL(blob),
filesize: e.args.payload.length,
headers: e.args.headers,
});
setLogTrigger(Date.now());
});
@@ -229,8 +184,7 @@ export const Content: React.FC = () => {
message,
});
setLogTrigger(Date.now());
const senderAddress = revealSenderAddress ? address : undefined;
await sendTextMessage({ payload: message, recipient, headers: { senderAddress } });
await sendTextMessage({ payload: message, recipient });
await Promise.all(
files.map(async (f) => {
@@ -246,7 +200,7 @@ export const Content: React.FC = () => {
return await sendBinaryMessage({
payload: new Uint8Array(buffer),
recipient,
headers: { filename: f.name, mimeType: f.type, senderAddress },
headers: { filename: f.name, mimeType: f.type },
});
} catch (e) {
addErrorLog('Failed to send file', f.name);
@@ -295,7 +249,20 @@ export const Content: React.FC = () => {
) : (
<>
<Chip color="success" icon={<CheckCircleIcon />} label="Connected" variant="outlined" />
<ClientAddress address={address} tooltip="Copy your client address to the clipboard" />
{address && (
<Tooltip arrow title="Copy your client address to the clipboard">
<Chip
clickable
label={`${address.slice(0, 24)}...`}
onClick={() => {
if (address) {
copy.copy(address);
}
}}
icon={<ContentCopyIcon />}
/>
</Tooltip>
)}
</>
)}
</Stack>
@@ -380,34 +347,9 @@ export const Content: React.FC = () => {
/>
</Box>
<Stack direction="row" spacing={2}>
<Button variant="contained" sx={{ width: 100 }} onClick={handleSend}>
Send
</Button>
<FormGroup>
<FormControlLabel
control={
<Switch
color={revealSenderAddress ? 'warning' : 'default'}
onClick={() => setRevealSenderAddress((prevState) => !prevState)}
/>
}
label={
revealSenderAddress ? (
<Stack direction="row" spacing={1}>
<VisibilityIcon color="warning" />
<Typography color={theme.palette.warning.main}>Reveal your address to the recipient</Typography>
</Stack>
) : (
<Stack direction="row" spacing={1}>
<VisibilityOffIcon />
<Typography>Hide your address from the recipient</Typography>
</Stack>
)
}
/>
</FormGroup>
</Stack>
<Button variant="contained" sx={{ width: 100 }} onClick={handleSend}>
Send
</Button>
</Stack>
)}
</Box>
@@ -456,16 +398,6 @@ export const Content: React.FC = () => {
)}
</>
)}
{item.kind === 'rx' &&
(item.headers?.senderAddress ? (
<ClientAddress
label="Sender"
tooltip="Click to copy the message sender's address"
address={item.headers?.senderAddress}
/>
) : (
<ClientAddress label="Sender" />
))}
</Stack>
</Box>
))}
@@ -1,11 +1,14 @@
import * as React from 'react';
import { createNymMixnetClient, IWebWorkerEvents, NymClientConfig, NymMixnetClient, Headers } from '@nymproject/sdk';
import { createNymMixnetClient, IWebWorkerEvents, NymClientConfig, NymMixnetClient } from '@nymproject/sdk';
export interface BinaryMessageHeaders extends Headers {
export interface BinaryMessageHeaders {
filename: string;
mimeType: string;
}
export const parseBinaryMessageHeaders = (headers: string): BinaryMessageHeaders =>
JSON.parse(headers) as BinaryMessageHeaders;
interface State {
// data
isReady: boolean;
@@ -14,7 +17,7 @@ interface State {
// methods
connect: (config: NymClientConfig) => Promise<void>;
sendTextMessage: (args: { payload: string; recipient: string; headers?: Headers }) => Promise<void>;
sendTextMessage: (args: { payload: string; recipient: string }) => Promise<void>;
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers: BinaryMessageHeaders }) => Promise<void>;
}
@@ -59,7 +62,7 @@ export const MixnetContextProvider: React.FC = ({ children }) => {
await nym.current.client.start(config);
};
const sendTextMessage = async (args: { payload: string; recipient: string; headers?: Headers }) => {
const sendTextMessage = async (args: { payload: string; recipient: string }) => {
if (!nym.current?.client) {
console.error('Nym client has not initialised. Please wrap in useEffect on `isReady` prop of this context.');
return;
@@ -73,7 +76,8 @@ export const MixnetContextProvider: React.FC = ({ children }) => {
return;
}
// convert headers to JSON
await nym.current.client.sendBinaryMessage(args);
const sendArgs = { ...args, headers: JSON.stringify(args.headers) };
await nym.current.client.sendBinaryMessage(sendArgs);
};
const value = React.useMemo<State>(
@@ -27,7 +27,7 @@ export interface NymClientConfig {
* Optional. The identity key of the preferred gateway to connect to.
*/
preferredGatewayIdentityKey?: string;
/**
* Optional. The listener websocket of the preferred gateway to connect to.
*/
@@ -39,16 +39,11 @@ export interface NymClientConfig {
debug?: wasm_bindgen.Debug;
}
export interface Headers {
senderAddress?: string;
[key: string]: unknown;
}
export interface IWebWorker {
start: (config: NymClientConfig) => void;
selfAddress: () => string | undefined;
sendMessage: (args: { payload: string; recipient: string; headers?: Headers }) => void;
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers?: Headers }) => void;
sendMessage: (args: { payload: string; recipient: string }) => void;
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers?: string }) => void;
}
export enum EventKinds {
@@ -77,7 +72,6 @@ export interface StringMessageReceivedEvent {
args: {
kind: number;
payload: string;
headers?: Headers;
};
}
@@ -86,7 +80,7 @@ export interface BinaryMessageReceivedEvent {
args: {
kind: number;
payload: Uint8Array;
headers?: Headers;
headers: string;
};
}
@@ -16,7 +16,6 @@ import type {
StringMessageReceivedEvent,
BinaryMessageReceivedEvent,
NymClientConfig,
Headers,
} from './types';
import { EventKinds } from './types';
@@ -92,13 +91,12 @@ class ClientWrapper {
this.client = await this.client.start();
};
sendMessage = async ({ payload, recipient, headers }: { recipient: string; payload: string; headers?: Headers }) => {
sendMessage = async ({ payload, recipient }: { recipient: string; payload: string }) => {
if (!this.client) {
console.error('Client has not been initialised. Please call `init` first.');
return;
}
const headersAsJsonString = headers ? JSON.stringify(headers) : '';
const message = wasm_bindgen.create_binary_message_from_string(PAYLOAD_KIND_TEXT, payload, headersAsJsonString);
const message = wasm_bindgen.create_binary_message_from_string(PAYLOAD_KIND_TEXT, payload);
this.client = await this.client.send_binary_message(message, recipient);
};
@@ -109,14 +107,13 @@ class ClientWrapper {
}: {
recipient: string;
payload: Uint8Array;
headers?: Headers;
headers?: string;
}) => {
if (!this.client) {
console.error('Client has not been initialised. Please call `init` first.');
return;
}
const headersAsJsonString = headers ? JSON.stringify(headers) : '';
const message = wasm_bindgen.create_binary_message_with_headers(PAYLOAD_KIND_BINARY, payload, headersAsJsonString);
const message = wasm_bindgen.create_binary_message_with_headers(PAYLOAD_KIND_BINARY, payload, headers || '');
this.client = await this.client.send_binary_message(message, recipient);
};
}
@@ -136,10 +133,11 @@ wasm_bindgen(wasmUrl)
config.validatorApiUrl,
config.preferredGatewayIdentityKey,
);
// set a different gatewayListener in order to avoid workaround ws over https error
if (config.gatewayListener) gatewayEndpoint.gateway_listener = config.gatewayListener;
if (config.gatewayListener)
gatewayEndpoint.gateway_listener = config.gatewayListener;
// create the client, passing handlers for events
wrapper.init(
new wasm_bindgen.Config(
@@ -155,20 +153,19 @@ wasm_bindgen(wasmUrl)
async (message) => {
try {
const { kind, payload, headers } = await wasm_bindgen.parse_binary_message_with_headers(message);
const parsedHeaders = headers?.length > 0 ? JSON.parse(headers) : undefined;
switch (kind) {
case PAYLOAD_KIND_TEXT: {
const stringMessage = await wasm_bindgen.parse_string_message_with_headers(message);
postMessageWithType<StringMessageReceivedEvent>({
kind: EventKinds.StringMessageReceived,
args: { kind, payload: stringMessage.payload, headers: parsedHeaders },
args: { kind, payload: stringMessage.payload },
});
break;
}
case PAYLOAD_KIND_BINARY:
postMessageWithType<BinaryMessageReceivedEvent>({
kind: EventKinds.BinaryMessageReceived,
args: { kind, payload, headers: parsedHeaders },
args: { kind, payload, headers: headers || '' },
});
break;
default:
@@ -3,7 +3,7 @@
[package]
name = "nym-network-requester"
version = "1.1.0"
version = "1.1.1"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021"
rust-version = "1.65"
-1
View File
@@ -18,7 +18,6 @@ serde_json = "1"
tokio = { version = "1.11", features = [ "net", "rt-multi-thread", "macros", "signal"] }
bip39 = "1.0.1"
anyhow = "1"
tap = "1"
nym-cli-commands = { path = "../../common/commands" }
logging = { path = "../../common/logging"}
+3 -7
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use network_defaults::NymNetworkDetails;
use nym_cli_commands::context::{create_query_client, create_signing_client, ClientArgs};
use nym_cli_commands::context::{create_signing_client, ClientArgs};
pub(crate) async fn execute(
global_args: ClientArgs,
@@ -19,22 +19,18 @@ pub(crate) async fn execute(
.await
}
Some(nym_cli_commands::validator::vesting::VestingScheduleCommands::Query(args)) => {
let address_from_args = args.address.clone();
nym_cli_commands::validator::vesting::query_vesting_schedule::query(
args,
create_query_client(network_details)?,
address_from_args,
create_signing_client(global_args, network_details)?,
)
.await
}
Some(nym_cli_commands::validator::vesting::VestingScheduleCommands::VestedBalance(
args,
)) => {
let address_from_args = args.address.clone();
nym_cli_commands::validator::vesting::balance::balance(
args,
create_query_client(network_details)?,
address_from_args,
create_signing_client(global_args, network_details)?,
)
.await
}
+1 -1
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-validator-api"
version = "1.1.0"
version = "1.1.1"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",