Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e12549e021 | |||
| fed1136f29 | |||
| 44c437e8ac | |||
| 40c07642a4 | |||
| 6eb0742a69 | |||
| b15292e403 | |||
| 2a4b80062d | |||
| 9d856c5f7d | |||
| dc7feeabf4 | |||
| e448136ee4 | |||
| 91640f1559 | |||
| 9092a80b93 | |||
| 3e9aa02264 | |||
| bf91e8995a | |||
| 0894be7981 | |||
| 9503521ecc | |||
| 78e0ae07fb | |||
| 24c146766d | |||
| 282b18660f | |||
| 184dd7767d | |||
| 2483a545b7 | |||
| df1926071a | |||
| 3519d0c31d | |||
| a33c21d438 | |||
| 04d02b08bc | |||
| 9460276131 | |||
| 84c9394eba | |||
| 6030d3831f | |||
| 241f0cf93a | |||
| 11122635f9 | |||
| ea54a3edc2 | |||
| 985a38429d | |||
| c9f821864a | |||
| 37d55f3a06 | |||
| b2ce142c17 | |||
| 374baa5ec1 | |||
| de1df74eb5 | |||
| 766c31544e | |||
| ecca7e8479 | |||
| 84a42f6ed9 | |||
| 5925e85684 | |||
| 972c60726c | |||
| ece22b9703 | |||
| 3f718feb41 | |||
| b550c32db6 | |||
| 83090c0a25 | |||
| 97ad1a2e46 | |||
| 9fbefa34e8 | |||
| 0812296399 | |||
| 51b04081a3 | |||
| 7f2027ca6b |
@@ -1,59 +0,0 @@
|
||||
name: CI for nym-connect
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'nym-connect/**'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
- run: yarn
|
||||
continue-on-error: true
|
||||
- name: Set environment from the example
|
||||
run: cp .env.sample .env
|
||||
- run: yarn storybook:build
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "nym-connect/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Keybase - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
# - name: Keybase - Send Notification
|
||||
# env:
|
||||
# NYM_NOTIFICATION_KIND: nym-connect
|
||||
# NYM_PROJECT_NAME: "nym-connect"
|
||||
# NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
# NYM_CI_WWW_LOCATION: "nym-connect-${{ env.GITHUB_REF_SLUG }}"
|
||||
# GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
# 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 }}"
|
||||
# KEYBASE_NYM_CHANNEL: "ci-nym-connect"
|
||||
# IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
# uses: docker://keybaseio/client:stable-node
|
||||
# with:
|
||||
# args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -3,7 +3,7 @@ require('dotenv').config();
|
||||
const Bot = require('keybase-bot');
|
||||
|
||||
let context = {
|
||||
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect'],
|
||||
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly'],
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
const Handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function addToContextAndValidate(context) {
|
||||
if (!context.env.NYM_CI_WWW_LOCATION) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
|
||||
}
|
||||
if (!context.env.NYM_CI_WWW_BASE) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
|
||||
}
|
||||
}
|
||||
|
||||
async function getMessageBody(context) {
|
||||
const source = fs
|
||||
.readFileSync(
|
||||
context.env.IS_SUCCESS === 'true'
|
||||
? path.resolve(__dirname, 'templates', 'success')
|
||||
: path.resolve(__dirname, 'templates', 'failure'),
|
||||
)
|
||||
.toString();
|
||||
const template = Handlebars.compile(source);
|
||||
return template(context);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addToContextAndValidate,
|
||||
getMessageBody,
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||
> 🔴 **FAILURE** :cry:
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
|
||||
Commit message:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View storybook:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
|
||||
> ✅ **SUCCESS**
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
|
||||
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -6,15 +6,11 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
### Added
|
||||
|
||||
- nym-connect: initial proof-of-concept of a UI around the socks5 client was added.
|
||||
- all: added network compilation target to `--help` (or `--version`) commands ([#1256]).
|
||||
- explorer-api: learned how to sum the delegations by owner in a new endpoint.
|
||||
- gateway: Added gateway coconut verifications and validator-api communication for double spending protection ([#1261])
|
||||
- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
|
||||
- mixnet-contract: Replace all naked `-` with `saturating_sub`.
|
||||
- mixnet-contrat: Added staking_supply field to ContractStateParams.
|
||||
- network-explorer-ui: Upgrade to React Router 6
|
||||
- rewarding: replace circulating supply with staking supply in reward calculations ([#1324])
|
||||
- validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284])
|
||||
- validator-api: add detailed mixnode bond endpoints, and explorer-api makes use of that data to append stake saturation.
|
||||
- validator-api: add Swagger to document the REST API ([#1249]).
|
||||
@@ -28,7 +24,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- wallet: new delegation and rewards UI
|
||||
- wallet: show version in nav bar
|
||||
- wallet: contract admin route put back
|
||||
- waller: staking_supply field to StateParams
|
||||
- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328])
|
||||
|
||||
### Fixed
|
||||
@@ -42,7 +37,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- mixnode: the mixnode learned how to shutdown gracefully.
|
||||
- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275])
|
||||
- native & socks5 clients: fail early when clients try to re-init with a different gateway, which is not supported yet ([#1322])
|
||||
- validator: fixed local docker-compose setup to work on Apple M1 ([#1329])
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -66,9 +60,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
[#1302]: https://github.com/nymtech/nym/pull/1302
|
||||
[#1318]: https://github.com/nymtech/nym/pull/1318
|
||||
[#1322]: https://github.com/nymtech/nym/pull/1322
|
||||
[#1324]: https://github.com/nymtech/nym/pull/1324
|
||||
[#1328]: https://github.com/nymtech/nym/pull/1328
|
||||
[#1329]: https://github.com/nymtech/nym/pull/1329
|
||||
|
||||
## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04)
|
||||
|
||||
|
||||
@@ -2852,7 +2852,6 @@ dependencies = [
|
||||
"nymsphinx-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"task",
|
||||
"tokio",
|
||||
"tokio-util 0.7.3",
|
||||
"url",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
test: build clippy-all cargo-test wasm fmt
|
||||
no-clippy: build cargo-test wasm fmt
|
||||
happy: fmt clippy-happy test
|
||||
clippy-all: clippy-all-main clippy-all-contracts clippy-all-wallet clippy-all-connect
|
||||
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect
|
||||
cargo-test: test-main test-contracts test-wallet test-connect
|
||||
build: build-contracts build-wallet build-main build-connect
|
||||
fmt: fmt-main fmt-contracts fmt-wallet fmt-connect
|
||||
clippy-all: clippy-all-main clippy-all-contracts clippy-all-wallet
|
||||
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet
|
||||
cargo-test: test-main test-contracts test-wallet
|
||||
build: build-contracts build-wallet build-main
|
||||
fmt: fmt-main fmt-contracts fmt-wallet
|
||||
|
||||
clippy-happy-main:
|
||||
cargo clippy
|
||||
@@ -16,9 +16,6 @@ clippy-happy-contracts:
|
||||
clippy-happy-wallet:
|
||||
cargo clippy --manifest-path nym-wallet/Cargo.toml
|
||||
|
||||
clippy-happy-connect:
|
||||
cargo clippy --manifest-path nym-connect/Cargo.toml
|
||||
|
||||
clippy-all-main:
|
||||
cargo clippy --workspace --all-features -- -D warnings
|
||||
|
||||
@@ -28,9 +25,6 @@ clippy-all-contracts:
|
||||
clippy-all-wallet:
|
||||
cargo clippy --workspace --manifest-path nym-wallet/Cargo.toml --all-features -- -D warnings
|
||||
|
||||
clippy-all-connect:
|
||||
cargo clippy --workspace --manifest-path nym-connect/Cargo.toml --all-features -- -D warnings
|
||||
|
||||
test-main:
|
||||
cargo test --all-features --workspace
|
||||
|
||||
@@ -40,9 +34,6 @@ test-contracts:
|
||||
test-wallet:
|
||||
cargo test --manifest-path nym-wallet/Cargo.toml --all-features
|
||||
|
||||
test-connect:
|
||||
cargo test --manifest-path nym-connect/Cargo.toml --all-features
|
||||
|
||||
build-main:
|
||||
cargo build --workspace
|
||||
|
||||
@@ -52,9 +43,6 @@ build-contracts:
|
||||
build-wallet:
|
||||
cargo build --manifest-path nym-wallet/Cargo.toml --workspace
|
||||
|
||||
build-connect:
|
||||
cargo build --manifest-path nym-connect/Cargo.toml --workspace
|
||||
|
||||
fmt-main:
|
||||
cargo fmt --all
|
||||
|
||||
@@ -64,9 +52,6 @@ fmt-contracts:
|
||||
fmt-wallet:
|
||||
cargo fmt --manifest-path nym-wallet/Cargo.toml --all
|
||||
|
||||
fmt-connect:
|
||||
cargo fmt --manifest-path nym-connect/Cargo.toml --all
|
||||
|
||||
wasm:
|
||||
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
Update fonts by doing the following:
|
||||
|
||||
1. Go to https://fonts.google.com/specimen/Open+Sans
|
||||
2. Add all the styles you want and select `@import`
|
||||
3. Copy the url (e.g. curl https://fonts.googleapis.com/css2\?family\=Open+Sans:ital,wght@0,300\;0,400\;0,500\;0,600\;0,700\;0,800\;1,300\;1,400\;1,500\;1,600\;1,700\;1,800\&display\=swap)
|
||||
4. Run `curl curl https://fonts.googleapis.com/css2\?family\=Open+Sans:ital,wght@0,300\;0,400\;0,500\;0,600\;0,700\;0,800\;1,300\;1,400\;1,500\;1,600\;1,700\;1,800\&display\=swap`
|
||||
5. Use the response as the CSS import directives and download the font files for each font weight
|
||||
6. Remember to delete any old font files
|
||||
@@ -1,96 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk_RkaVc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkxhjaVc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk0ZjaVc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4n.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4n.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjr0C4n.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsgH1y4n.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4n.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-stretch: normal;
|
||||
font-display: swap;
|
||||
src: url(./memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgshZ1y4n.ttf) format('truetype');
|
||||
}
|
||||
@@ -345,7 +345,7 @@ pub struct Client<T> {
|
||||
nym_root_directory: PathBuf,
|
||||
|
||||
#[serde(skip)]
|
||||
super_struct: PhantomData<T>,
|
||||
super_struct: PhantomData<*const T>,
|
||||
}
|
||||
|
||||
impl<T: NymConfig> Default for Client<T> {
|
||||
|
||||
@@ -20,7 +20,6 @@ use client_core::client::topology_control::{
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use crypto::asymmetric::identity;
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use gateway_client::bandwidth::BandwidthController;
|
||||
use gateway_client::{
|
||||
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
|
||||
@@ -36,17 +35,7 @@ use crate::socks::{
|
||||
server::SphinxSocksServer,
|
||||
};
|
||||
|
||||
pub mod config;
|
||||
|
||||
// Channels used to control the main task from outside
|
||||
pub type Socks5ControlMessageSender = mpsc::UnboundedSender<Socks5ControlMessage>;
|
||||
pub type Socks5ControlMessageReceiver = mpsc::UnboundedReceiver<Socks5ControlMessage>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Socks5ControlMessage {
|
||||
/// Tell the main task to stop
|
||||
Stop,
|
||||
}
|
||||
pub(crate) mod config;
|
||||
|
||||
pub struct NymClient {
|
||||
/// Client configuration options, including, among other things, packet sending rates,
|
||||
@@ -283,20 +272,6 @@ impl NymClient {
|
||||
);
|
||||
}
|
||||
|
||||
// Variant of `run_forever` that listends for remote control messages
|
||||
pub async fn run_and_listen(&mut self, mut receiver: Socks5ControlMessageReceiver) {
|
||||
self.start().await;
|
||||
tokio::select! {
|
||||
message = receiver.next() => match message {
|
||||
Some(Socks5ControlMessage::Stop) => {
|
||||
log::info!("Received: {:?}", message);
|
||||
log::info!("Shutting down");
|
||||
}
|
||||
None => log::info!("none"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start(&mut self) {
|
||||
info!("Starting nym client");
|
||||
// channels for inter-component communication
|
||||
|
||||
@@ -88,8 +88,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
app
|
||||
}
|
||||
|
||||
// TODO: make this private again after refactoring the config setup
|
||||
pub async fn register_with_gateway(
|
||||
async fn register_with_gateway(
|
||||
gateway: &gateway::Node,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
) -> Arc<SharedKeys> {
|
||||
@@ -111,8 +110,7 @@ pub async fn register_with_gateway(
|
||||
.expect("failed to register with the gateway!")
|
||||
}
|
||||
|
||||
// TODO: make this private again after refactoring the config setup
|
||||
pub async fn gateway_details(
|
||||
async fn gateway_details(
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<&str>,
|
||||
) -> gateway::Node {
|
||||
@@ -146,8 +144,7 @@ pub async fn gateway_details(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make this private again after refactoring the config setup
|
||||
pub fn show_address(config: &Config) {
|
||||
fn show_address(config: &Config) {
|
||||
fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair {
|
||||
let identity_keypair: identity::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::client::config::Config;
|
||||
use clap::ArgMatches;
|
||||
use url::Url;
|
||||
|
||||
pub mod init;
|
||||
pub(crate) mod init;
|
||||
pub(crate) mod run;
|
||||
pub(crate) mod upgrade;
|
||||
|
||||
|
||||
@@ -2,9 +2,4 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod client;
|
||||
// This is only used as we reach into the init functions in nym-connect. We need to refactor the
|
||||
// init functions so that nym-connect can just call the same init function as the regular socks5
|
||||
// client.
|
||||
#[allow(unused)]
|
||||
pub mod commands;
|
||||
pub mod socks;
|
||||
|
||||
@@ -220,9 +220,9 @@ impl DelegatorRewardParams {
|
||||
|
||||
// change all values into their fixed representations
|
||||
let delegation_amount = U128::from_num(delegation_amount.u128());
|
||||
let staking_supply = U128::from_num(self.reward_params.staking_supply());
|
||||
let circulating_supply = U128::from_num(self.reward_params.circulating_supply());
|
||||
|
||||
let scaled_delegation_amount = delegation_amount / staking_supply;
|
||||
let scaled_delegation_amount = delegation_amount / circulating_supply;
|
||||
|
||||
// Div by zero checked above
|
||||
let delegator_reward =
|
||||
@@ -392,21 +392,22 @@ impl MixNodeBond {
|
||||
self.total_delegation.clone()
|
||||
}
|
||||
|
||||
pub fn stake_saturation(&self, staking_supply: u128, rewarded_set_size: u32) -> U128 {
|
||||
self.total_bond_to_staking_supply(staking_supply) * U128::from_num(rewarded_set_size)
|
||||
pub fn stake_saturation(&self, circulating_supply: u128, rewarded_set_size: u32) -> U128 {
|
||||
self.total_bond_to_circulating_supply(circulating_supply)
|
||||
* U128::from_num(rewarded_set_size)
|
||||
}
|
||||
|
||||
// TODO: There is an effect here when adding accumulted rewards to the total bond, ie accumulated rewards will not
|
||||
// affect lambda, but will affect sigma, in turn over time, if left unclaimed operator rewards will not compound, but
|
||||
// behave similarly to delegations.
|
||||
// The question is should this be taken into account when calculating operator rewards?
|
||||
pub fn pledge_to_staking_supply(&self, staking_supply: u128) -> U128 {
|
||||
U128::from_num(self.pledge_amount().amount.u128()) / U128::from_num(staking_supply)
|
||||
pub fn pledge_to_circulating_supply(&self, circulating_supply: u128) -> U128 {
|
||||
U128::from_num(self.pledge_amount().amount.u128()) / U128::from_num(circulating_supply)
|
||||
}
|
||||
|
||||
pub fn total_bond_to_staking_supply(&self, staking_supply: u128) -> U128 {
|
||||
pub fn total_bond_to_circulating_supply(&self, circulating_supply: u128) -> U128 {
|
||||
U128::from_num(self.pledge_amount().amount.u128() + self.total_delegation().amount.u128())
|
||||
/ U128::from_num(staking_supply)
|
||||
/ U128::from_num(circulating_supply)
|
||||
}
|
||||
|
||||
pub fn lambda_ticked(&self, params: &RewardParams) -> U128 {
|
||||
@@ -416,7 +417,7 @@ impl MixNodeBond {
|
||||
|
||||
pub fn lambda(&self, params: &RewardParams) -> U128 {
|
||||
// Ratio of a bond to the token circulating supply
|
||||
self.pledge_to_staking_supply(params.staking_supply())
|
||||
self.pledge_to_circulating_supply(params.circulating_supply())
|
||||
}
|
||||
|
||||
pub fn sigma_ticked(&self, params: &RewardParams) -> U128 {
|
||||
@@ -426,7 +427,7 @@ impl MixNodeBond {
|
||||
|
||||
pub fn sigma(&self, params: &RewardParams) -> U128 {
|
||||
// Ratio of a delegation to the the token circulating supply
|
||||
self.total_bond_to_staking_supply(params.staking_supply())
|
||||
self.total_bond_to_circulating_supply(params.circulating_supply())
|
||||
}
|
||||
|
||||
pub fn estimate_reward(
|
||||
@@ -514,8 +515,9 @@ impl MixNodeBond {
|
||||
}
|
||||
|
||||
pub fn sigma_ratio(&self, params: &RewardParams) -> U128 {
|
||||
if self.total_bond_to_staking_supply(params.staking_supply()) < params.one_over_k() {
|
||||
self.total_bond_to_staking_supply(params.staking_supply())
|
||||
if self.total_bond_to_circulating_supply(params.circulating_supply()) < params.one_over_k()
|
||||
{
|
||||
self.total_bond_to_circulating_supply(params.circulating_supply())
|
||||
} else {
|
||||
params.one_over_k()
|
||||
}
|
||||
|
||||
@@ -78,9 +78,9 @@ impl NodeEpochRewards {
|
||||
) -> Result<Uint128, MixnetContractError> {
|
||||
// change all values into their fixed representations
|
||||
let delegation_amount = U128::from_num(delegation_amount.u128());
|
||||
let staking_supply = U128::from_num(epoch_reward_params.staking_supply());
|
||||
let circulating_supply = U128::from_num(epoch_reward_params.circulating_supply());
|
||||
|
||||
let scaled_delegation_amount = delegation_amount / staking_supply;
|
||||
let scaled_delegation_amount = delegation_amount / circulating_supply;
|
||||
|
||||
let check_div_by_zero =
|
||||
if let Some(value) = scaled_delegation_amount.checked_div(self.sigma()) {
|
||||
@@ -105,8 +105,7 @@ pub struct EpochRewardParams {
|
||||
epoch_reward_pool: Uint128,
|
||||
rewarded_set_size: Uint128,
|
||||
active_set_size: Uint128,
|
||||
#[serde(alias = "circulating_supply")]
|
||||
staking_supply: Uint128,
|
||||
circulating_supply: Uint128,
|
||||
sybil_resistance_percent: u8,
|
||||
active_set_work_factor: u8,
|
||||
}
|
||||
@@ -116,7 +115,7 @@ impl EpochRewardParams {
|
||||
epoch_reward_pool: u128,
|
||||
rewarded_set_size: u128,
|
||||
active_set_size: u128,
|
||||
staking_supply: u128,
|
||||
circulating_supply: u128,
|
||||
sybil_resistance_percent: u8,
|
||||
active_set_work_factor: u8,
|
||||
) -> EpochRewardParams {
|
||||
@@ -124,7 +123,7 @@ impl EpochRewardParams {
|
||||
epoch_reward_pool: Uint128::new(epoch_reward_pool),
|
||||
rewarded_set_size: Uint128::new(rewarded_set_size),
|
||||
active_set_size: Uint128::new(active_set_size),
|
||||
staking_supply: Uint128::new(staking_supply),
|
||||
circulating_supply: Uint128::new(circulating_supply),
|
||||
sybil_resistance_percent,
|
||||
active_set_work_factor,
|
||||
}
|
||||
@@ -137,7 +136,7 @@ impl EpochRewardParams {
|
||||
pub fn new_empty() -> Self {
|
||||
EpochRewardParams {
|
||||
epoch_reward_pool: Uint128::new(0),
|
||||
staking_supply: Uint128::new(0),
|
||||
circulating_supply: Uint128::new(0),
|
||||
sybil_resistance_percent: 0,
|
||||
rewarded_set_size: Uint128::new(0),
|
||||
active_set_size: Uint128::new(0),
|
||||
@@ -153,8 +152,8 @@ impl EpochRewardParams {
|
||||
self.active_set_size.u128()
|
||||
}
|
||||
|
||||
pub fn staking_supply(&self) -> u128 {
|
||||
self.staking_supply.u128()
|
||||
pub fn circulating_supply(&self) -> u128 {
|
||||
self.circulating_supply.u128()
|
||||
}
|
||||
|
||||
pub fn epoch_reward_pool(&self) -> u128 {
|
||||
@@ -253,8 +252,8 @@ impl RewardParams {
|
||||
self.epoch.rewarded_set_size.u128()
|
||||
}
|
||||
|
||||
pub fn staking_supply(&self) -> u128 {
|
||||
self.epoch.staking_supply.u128()
|
||||
pub fn circulating_supply(&self) -> u128 {
|
||||
self.epoch.circulating_supply.u128()
|
||||
}
|
||||
|
||||
pub fn reward_blockstamp(&self) -> u64 {
|
||||
|
||||
@@ -43,7 +43,6 @@ pub struct ContractStateParams {
|
||||
// subset of rewarded mixnodes that are actively receiving mix traffic
|
||||
// used to handle shorter-term (e.g. hourly) fluctuations of demand
|
||||
pub mixnode_active_set_size: u32,
|
||||
pub staking_supply: Uint128,
|
||||
}
|
||||
|
||||
impl Display for ContractStateParams {
|
||||
|
||||
@@ -26,6 +26,5 @@ nymsphinx-forwarding = { path = "../nymsphinx/forwarding" }
|
||||
nymsphinx-framing = { path = "../nymsphinx/framing" }
|
||||
nymsphinx-params = { path = "../nymsphinx/params" }
|
||||
nymsphinx-types = { path = "../nymsphinx/types" }
|
||||
task = { path = "../task" }
|
||||
validator-client = { path = "../client-libs/validator-client" }
|
||||
version-checker = { path = "../version-checker" }
|
||||
|
||||
@@ -24,8 +24,6 @@ pub enum RttError {
|
||||
ConnectionWriteTimeout(String),
|
||||
|
||||
UnexpectedReplySequence,
|
||||
|
||||
ShutdownReceived,
|
||||
}
|
||||
|
||||
impl Display for RttError {
|
||||
@@ -71,9 +69,6 @@ impl Display for RttError {
|
||||
f,
|
||||
"The received reply packet had an unexpected sequence number"
|
||||
),
|
||||
RttError::ShutdownReceived => {
|
||||
write!(f, "Shutdown signal received")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ use std::fmt::{Display, Formatter};
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, io, process};
|
||||
use task::ShutdownListener;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||
@@ -19,19 +18,13 @@ use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||
pub(crate) struct PacketListener {
|
||||
address: SocketAddr,
|
||||
connection_handler: Arc<ConnectionHandler>,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl PacketListener {
|
||||
pub(crate) fn new(
|
||||
address: SocketAddr,
|
||||
identity: Arc<identity::KeyPair>,
|
||||
shutdown: ShutdownListener,
|
||||
) -> Self {
|
||||
pub(crate) fn new(address: SocketAddr, identity: Arc<identity::KeyPair>) -> Self {
|
||||
PacketListener {
|
||||
address,
|
||||
connection_handler: Arc::new(ConnectionHandler { identity }),
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,37 +34,24 @@ impl PacketListener {
|
||||
let listener = match TcpListener::bind(self.address).await {
|
||||
Ok(listener) => listener,
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to bind to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?",
|
||||
self.address, err
|
||||
);
|
||||
error!("Failed to bind to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address, err);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
info!("Started listening for echo packets on {}", self.address);
|
||||
|
||||
let mut shutdown_listener = self.shutdown.clone();
|
||||
|
||||
while !shutdown_listener.is_shutdown() {
|
||||
loop {
|
||||
// cloning the arc as each accepted socket is handled in separate task
|
||||
let connection_handler = Arc::clone(&self.connection_handler);
|
||||
let handler_shutdown_listener = self.shutdown.clone();
|
||||
|
||||
tokio::select! {
|
||||
socket = listener.accept() => {
|
||||
match socket {
|
||||
Ok((socket, remote_addr)) => {
|
||||
debug!("New verloc connection from {}", remote_addr);
|
||||
match listener.accept().await {
|
||||
Ok((socket, remote_addr)) => {
|
||||
debug!("New verloc connection from {}", remote_addr);
|
||||
|
||||
tokio::spawn(connection_handler.handle_connection(socket, remote_addr, handler_shutdown_listener));
|
||||
}
|
||||
Err(err) => warn!("Failed to accept incoming connection - {:?}", err),
|
||||
}
|
||||
},
|
||||
_ = shutdown_listener.recv() => {
|
||||
log::trace!("PacketListener: Received shutdown");
|
||||
tokio::spawn(connection_handler.handle_connection(socket, remote_addr));
|
||||
}
|
||||
Err(err) => warn!("Failed to accept incoming connection - {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,46 +67,34 @@ impl ConnectionHandler {
|
||||
packet.construct_reply(self.identity.private_key())
|
||||
}
|
||||
|
||||
pub(crate) async fn handle_connection(
|
||||
self: Arc<Self>,
|
||||
conn: TcpStream,
|
||||
remote: SocketAddr,
|
||||
mut shutdown_listener: ShutdownListener,
|
||||
) {
|
||||
pub(crate) async fn handle_connection(self: Arc<Self>, conn: TcpStream, remote: SocketAddr) {
|
||||
debug!("Starting connection handler for {:?}", remote);
|
||||
|
||||
let mut framed_conn = Framed::new(conn, EchoPacketCodec);
|
||||
while !shutdown_listener.is_shutdown() {
|
||||
tokio::select! {
|
||||
Some(echo_packet) = framed_conn.next() => {
|
||||
// handle echo packet
|
||||
let reply_packet = match echo_packet {
|
||||
Ok(echo_packet) => self.handle_echo_packet(echo_packet),
|
||||
Err(err) => {
|
||||
error!(
|
||||
"The socket connection got corrupted with error: {}. Closing the socket",
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// write back the reply (note the lack of framing)
|
||||
if let Err(err) = framed_conn
|
||||
.get_mut()
|
||||
.write_all(reply_packet.to_bytes().as_ref())
|
||||
.await
|
||||
{
|
||||
error!(
|
||||
"Failed to write reply packet back to the sender - {}. Closing the socket on our end",
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ = shutdown_listener.recv() => {
|
||||
trace!("ConnectionHandler: Shutdown received");
|
||||
while let Some(echo_packet) = framed_conn.next().await {
|
||||
// handle echo packet
|
||||
let reply_packet = match echo_packet {
|
||||
Ok(echo_packet) => self.handle_echo_packet(echo_packet),
|
||||
Err(err) => {
|
||||
error!(
|
||||
"The socket connection got corrupted with error: {}. Closing the socket",
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// write back the reply (note the lack of framing)
|
||||
if let Err(err) = framed_conn
|
||||
.get_mut()
|
||||
.write_all(reply_packet.to_bytes().as_ref())
|
||||
.await
|
||||
{
|
||||
error!(
|
||||
"Failed to write reply packet back to the sender - {}. Closing the socket on our end",
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::verloc::listener::PacketListener;
|
||||
pub use crate::verloc::measurement::{AtomicVerlocResult, Verloc, VerlocResult};
|
||||
use crate::verloc::sender::{PacketSender, TestedNode};
|
||||
use crypto::asymmetric::identity;
|
||||
use futures::stream::FuturesUnordered;
|
||||
@@ -12,14 +13,11 @@ use rand::thread_rng;
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use task::ShutdownListener;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio::time::sleep;
|
||||
use url::Url;
|
||||
use version_checker::parse_version;
|
||||
|
||||
pub use crate::verloc::measurement::{AtomicVerlocResult, Verloc, VerlocResult};
|
||||
|
||||
pub mod error;
|
||||
pub(crate) mod listener;
|
||||
pub(crate) mod measurement;
|
||||
@@ -139,10 +137,9 @@ impl ConfigBuilder {
|
||||
|
||||
pub fn build(self) -> Config {
|
||||
// panics here are fine as those are only ever constructed at the initial setup
|
||||
assert!(
|
||||
!self.0.validator_api_urls.is_empty(),
|
||||
"at least one validator endpoint must be provided",
|
||||
);
|
||||
if self.0.validator_api_urls.is_empty() {
|
||||
panic!("at least one validator endpoint must be provided")
|
||||
}
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@@ -168,7 +165,6 @@ pub struct VerlocMeasurer {
|
||||
config: Config,
|
||||
packet_sender: Arc<PacketSender>,
|
||||
packet_listener: Arc<PacketListener>,
|
||||
shutdown_listener: ShutdownListener,
|
||||
|
||||
currently_used_api: usize,
|
||||
|
||||
@@ -181,11 +177,7 @@ pub struct VerlocMeasurer {
|
||||
}
|
||||
|
||||
impl VerlocMeasurer {
|
||||
pub fn new(
|
||||
mut config: Config,
|
||||
identity: Arc<identity::KeyPair>,
|
||||
shutdown_listener: ShutdownListener,
|
||||
) -> Self {
|
||||
pub fn new(mut config: Config, identity: Arc<identity::KeyPair>) -> Self {
|
||||
config.validator_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
VerlocMeasurer {
|
||||
@@ -195,14 +187,11 @@ impl VerlocMeasurer {
|
||||
config.packet_timeout,
|
||||
config.connection_timeout,
|
||||
config.delay_between_packets,
|
||||
shutdown_listener.clone(),
|
||||
)),
|
||||
packet_listener: Arc::new(PacketListener::new(
|
||||
config.listening_address,
|
||||
Arc::clone(&identity),
|
||||
shutdown_listener.clone(),
|
||||
)),
|
||||
shutdown_listener,
|
||||
currently_used_api: 0,
|
||||
validator_client: validator_client::ApiClient::new(
|
||||
config.validator_api_urls[0].clone(),
|
||||
@@ -233,11 +222,7 @@ impl VerlocMeasurer {
|
||||
tokio::spawn(packet_listener.run())
|
||||
}
|
||||
|
||||
async fn perform_measurement(&self, nodes_to_test: Vec<TestedNode>) -> MeasurementOutcome {
|
||||
log::trace!("Performing measurements");
|
||||
|
||||
let mut shutdown_listener = self.shutdown_listener.clone();
|
||||
|
||||
async fn perform_measurement(&self, nodes_to_test: Vec<TestedNode>) {
|
||||
for chunk in nodes_to_test.chunks(self.config.tested_nodes_batch_size) {
|
||||
let mut chunk_results = Vec::with_capacity(chunk.len());
|
||||
|
||||
@@ -261,44 +246,33 @@ impl VerlocMeasurer {
|
||||
.collect::<FuturesUnordered<_>>();
|
||||
|
||||
// exhaust the results
|
||||
while !shutdown_listener.is_shutdown() {
|
||||
tokio::select! {
|
||||
Some(result) = measurement_chunk.next() => {
|
||||
// if we receive JoinError it means the task failed to get executed, so either there's a bigger issue with tokio
|
||||
// or there was a panic inside the task itself. In either case, we should just terminate ourselves.
|
||||
let execution_result = result.expect("the measurement task panicked!");
|
||||
let measurement_result = match execution_result.0 {
|
||||
Err(err) => {
|
||||
debug!(
|
||||
"Failed to perform measurement for {} - {}",
|
||||
execution_result.1.to_base58_string(),
|
||||
err
|
||||
);
|
||||
None
|
||||
}
|
||||
Ok(result) => Some(result),
|
||||
};
|
||||
chunk_results.push(Verloc::new(execution_result.1, measurement_result));
|
||||
},
|
||||
_ = shutdown_listener.recv() => {
|
||||
trace!("Shutdown received while measuring");
|
||||
return MeasurementOutcome::Shutdown;
|
||||
while let Some(result) = measurement_chunk.next().await {
|
||||
// if we receive JoinError it means the task failed to get executed, so either there's a bigger issue with tokio
|
||||
// or there was a panic inside the task itself. In either case, we should just terminate ourselves.
|
||||
let execution_result = result.expect("the measurement task panicked!");
|
||||
let measurement_result = match execution_result.0 {
|
||||
Err(err) => {
|
||||
debug!(
|
||||
"Failed to perform measurement for {} - {}",
|
||||
execution_result.1.to_base58_string(),
|
||||
err
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
Ok(result) => Some(result),
|
||||
};
|
||||
chunk_results.push(Verloc::new(execution_result.1, measurement_result));
|
||||
}
|
||||
|
||||
// update the results vector with chunks as they become available (by default every 50 nodes)
|
||||
self.results.append_results(chunk_results).await;
|
||||
}
|
||||
|
||||
MeasurementOutcome::Done
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
self.start_listening();
|
||||
|
||||
while !self.shutdown_listener.is_shutdown() {
|
||||
info!("Starting verloc measurements");
|
||||
loop {
|
||||
info!(target: "verloc", "Starting verloc measurements");
|
||||
// TODO: should we also measure gateways?
|
||||
|
||||
let all_mixes = match self.validator_client.get_cached_mixnodes().await {
|
||||
@@ -348,32 +322,13 @@ impl VerlocMeasurer {
|
||||
// on start of each run remove old results
|
||||
self.results.reset_results(tested_nodes.len()).await;
|
||||
|
||||
if let MeasurementOutcome::Shutdown = self.perform_measurement(tested_nodes).await {
|
||||
log::trace!("Shutting down after aborting measurements");
|
||||
break;
|
||||
}
|
||||
self.perform_measurement(tested_nodes).await;
|
||||
|
||||
// write current time to "run finished" field
|
||||
self.results.finish_measurements().await;
|
||||
|
||||
info!(
|
||||
"Finished performing verloc measurements. The next one will happen in {:?}",
|
||||
self.config.testing_interval
|
||||
);
|
||||
|
||||
tokio::select! {
|
||||
_ = sleep(self.config.testing_interval) => {},
|
||||
_ = self.shutdown_listener.recv() => {
|
||||
log::trace!("Shutdown received while sleeping");
|
||||
}
|
||||
}
|
||||
info!(target: "verloc", "Finished performing verloc measurements. The next one will happen in {:?}", self.config.testing_interval);
|
||||
sleep(self.config.testing_interval).await
|
||||
}
|
||||
|
||||
log::trace!("Verloc: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
enum MeasurementOutcome {
|
||||
Done,
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
@@ -7,11 +7,10 @@ use crate::verloc::packet::{EchoPacket, ReplyPacket};
|
||||
use crypto::asymmetric::identity;
|
||||
use log::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::{fmt, io};
|
||||
use task::ShutdownListener;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::sleep;
|
||||
@@ -28,16 +27,6 @@ impl TestedNode {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TestedNode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"TestedNode(id: {}, address: {})",
|
||||
self.identity, self.address
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PacketSender {
|
||||
identity: Arc<identity::KeyPair>,
|
||||
// timeout for receiving before sending new one
|
||||
@@ -45,7 +34,6 @@ pub(crate) struct PacketSender {
|
||||
packet_timeout: Duration,
|
||||
connection_timeout: Duration,
|
||||
delay_between_packets: Duration,
|
||||
shutdown_listener: ShutdownListener,
|
||||
}
|
||||
|
||||
impl PacketSender {
|
||||
@@ -55,7 +43,6 @@ impl PacketSender {
|
||||
packet_timeout: Duration,
|
||||
connection_timeout: Duration,
|
||||
delay_between_packets: Duration,
|
||||
shutdown_listener: ShutdownListener,
|
||||
) -> Self {
|
||||
PacketSender {
|
||||
identity,
|
||||
@@ -63,7 +50,6 @@ impl PacketSender {
|
||||
packet_timeout,
|
||||
connection_timeout,
|
||||
delay_between_packets,
|
||||
shutdown_listener,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +69,6 @@ impl PacketSender {
|
||||
self: Arc<Self>,
|
||||
tested_node: TestedNode,
|
||||
) -> Result<Measurement, RttError> {
|
||||
let mut shutdown_listener = self.shutdown_listener.clone();
|
||||
|
||||
let mut conn = match tokio::time::timeout(
|
||||
self.connection_timeout,
|
||||
TcpStream::connect(tested_node.address),
|
||||
@@ -114,40 +98,35 @@ impl PacketSender {
|
||||
let start = tokio::time::Instant::now();
|
||||
// TODO: should we get the start time after or before actually sending the data?
|
||||
// there's going to definitely some scheduler and network stack bias here
|
||||
let packet_bytes = packet.to_bytes();
|
||||
|
||||
tokio::select! {
|
||||
write = tokio::time::timeout(self.packet_timeout, conn.write_all(packet_bytes.as_ref())) => {
|
||||
match write {
|
||||
Err(_timeout) => {
|
||||
let identity_string = tested_node.identity.to_base58_string();
|
||||
debug!(
|
||||
"failed to write echo packet to {} within {:?}. Stopping the test.",
|
||||
identity_string, self.packet_timeout
|
||||
);
|
||||
return Err(RttError::UnexpectedConnectionFailureWrite(
|
||||
identity_string,
|
||||
io::ErrorKind::TimedOut.into(),
|
||||
));
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
let identity_string = tested_node.identity.to_base58_string();
|
||||
debug!(
|
||||
"failed to write echo packet to {} - {}. Stopping the test.",
|
||||
identity_string, err
|
||||
);
|
||||
return Err(RttError::UnexpectedConnectionFailureWrite(
|
||||
identity_string,
|
||||
err,
|
||||
));
|
||||
}
|
||||
Ok(Ok(_)) => {}
|
||||
}
|
||||
},
|
||||
_ = shutdown_listener.recv() => {
|
||||
log::trace!("PacketSender: Received shutdown while sending");
|
||||
return Err(RttError::ShutdownReceived);
|
||||
},
|
||||
match tokio::time::timeout(
|
||||
self.packet_timeout,
|
||||
conn.write_all(packet.to_bytes().as_ref()),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(_timeout) => {
|
||||
let identity_string = tested_node.identity.to_base58_string();
|
||||
debug!(
|
||||
"failed to write echo packet to {} within {:?}. Stopping the test.",
|
||||
identity_string, self.packet_timeout
|
||||
);
|
||||
return Err(RttError::UnexpectedConnectionFailureWrite(
|
||||
identity_string,
|
||||
io::ErrorKind::TimedOut.into(),
|
||||
));
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
let identity_string = tested_node.identity.to_base58_string();
|
||||
debug!(
|
||||
"failed to write echo packet to {} - {}. Stopping the test.",
|
||||
identity_string, err
|
||||
);
|
||||
return Err(RttError::UnexpectedConnectionFailureWrite(
|
||||
identity_string,
|
||||
err,
|
||||
));
|
||||
}
|
||||
Ok(Ok(_)) => {}
|
||||
}
|
||||
|
||||
// there's absolutely no need to put a codec on ReplyPackets as we know exactly
|
||||
@@ -168,28 +147,21 @@ impl PacketSender {
|
||||
ReplyPacket::try_from_bytes(&buf, &tested_node.identity)
|
||||
};
|
||||
|
||||
let reply_packet = tokio::select! {
|
||||
reply = tokio::time::timeout(self.packet_timeout, reply_packet_future) => {
|
||||
match reply {
|
||||
Ok(reply_packet) => reply_packet,
|
||||
Err(_timeout) => {
|
||||
// TODO: should we continue regardless (with the rest of the packets, or abandon the whole thing?)
|
||||
// Note: if we decide to continue, it would increase the complexity of the whole thing
|
||||
debug!(
|
||||
"failed to receive reply to our echo packet within {:?}. Stopping the test",
|
||||
self.packet_timeout
|
||||
);
|
||||
return Err(RttError::ConnectionReadTimeout(
|
||||
tested_node.identity.to_base58_string(),
|
||||
));
|
||||
}
|
||||
let reply_packet =
|
||||
match tokio::time::timeout(self.packet_timeout, reply_packet_future).await {
|
||||
Ok(reply_packet) => reply_packet,
|
||||
Err(_timeout) => {
|
||||
// TODO: should we continue regardless (with the rest of the packets, or abandon the whole thing?)
|
||||
// Note: if we decide to continue, it would increase the complexity of the whole thing
|
||||
debug!(
|
||||
"failed to receive reply to our echo packet within {:?}. Stopping the test",
|
||||
self.packet_timeout
|
||||
);
|
||||
return Err(RttError::ConnectionReadTimeout(
|
||||
tested_node.identity.to_base58_string(),
|
||||
));
|
||||
}
|
||||
},
|
||||
_ = shutdown_listener.recv() => {
|
||||
log::trace!("PacketSender: Received shutdown while waiting for reply");
|
||||
return Err(RttError::ShutdownReceived);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let reply_packet = reply_packet?;
|
||||
// make sure it's actually the expected packet...
|
||||
|
||||
@@ -317,6 +317,7 @@ mod test {
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use cosmwasm_std::Decimal as CosmWasmDecimal;
|
||||
use serde_json::json;
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
|
||||
@@ -423,7 +424,9 @@ mod test {
|
||||
};
|
||||
println!(
|
||||
"from_atomics = {}",
|
||||
CosmWasmDecimal::from_atomics(coin.amount, 6).unwrap()
|
||||
CosmWasmDecimal::from_atomics(coin.amount.clone(), 6)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
);
|
||||
let c: MajorCurrencyAmount = coin.into();
|
||||
assert_eq!(c, MajorCurrencyAmount::new("0.000001", CurrencyDenom::Nym));
|
||||
@@ -437,7 +440,7 @@ mod test {
|
||||
};
|
||||
println!(
|
||||
"from_atomics = {:?}",
|
||||
CosmWasmDecimal::from_atomics(coin.amount, 6)
|
||||
CosmWasmDecimal::from_atomics(coin.amount.clone(), 6)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
);
|
||||
@@ -486,4 +489,27 @@ mod test {
|
||||
let denom = c.denom.to_string();
|
||||
assert_eq!(denom, "NYM".to_string());
|
||||
}
|
||||
|
||||
fn amounts() -> Vec<&'static str> {
|
||||
vec![
|
||||
"1",
|
||||
"10",
|
||||
"100",
|
||||
"1000",
|
||||
"10000",
|
||||
"100000",
|
||||
"10000000",
|
||||
"100000000",
|
||||
"1000000000",
|
||||
"10000000000",
|
||||
"100000000000",
|
||||
"1000000000000",
|
||||
"10000000000000",
|
||||
"100000000000000",
|
||||
"1000000000000000",
|
||||
"10000000000000000",
|
||||
"100000000000000000",
|
||||
"1000000000000000000",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,6 @@ pub const INITIAL_ACTIVE_SET_WORK_FACTOR: u8 = 10;
|
||||
pub const DEFAULT_FIRST_INTERVAL_START: OffsetDateTime =
|
||||
time::macros::datetime!(2022-01-01 12:00 UTC);
|
||||
|
||||
pub const INITIAL_STAKING_SUPPLY: Uint128 = Uint128::new(100_000_000_000_000);
|
||||
|
||||
pub fn debug_with_visibility<S: Into<String>>(api: &dyn Api, msg: S) {
|
||||
api.debug(&*format!("\n\n\n=========================================\n{}\n=========================================\n\n\n", msg.into()));
|
||||
}
|
||||
@@ -72,7 +70,6 @@ fn default_initial_state(owner: Addr, rewarding_validator_address: Addr) -> Cont
|
||||
minimum_gateway_pledge: INITIAL_GATEWAY_PLEDGE,
|
||||
mixnode_rewarded_set_size: INITIAL_MIXNODE_REWARDED_SET_SIZE,
|
||||
mixnode_active_set_size: INITIAL_MIXNODE_ACTIVE_SET_SIZE,
|
||||
staking_supply: INITIAL_STAKING_SUPPLY,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -435,52 +432,7 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result<QueryResponse, C
|
||||
Ok(query_res?)
|
||||
}
|
||||
|
||||
fn migrate_contract_state_params(deps: DepsMut<'_>) -> Result<(), ContractError> {
|
||||
use crate::mixnet_contract_settings::storage::CONTRACT_STATE;
|
||||
use cw_storage_plus::Item;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct OldContractState {
|
||||
pub owner: Addr,
|
||||
pub rewarding_validator_address: Addr,
|
||||
pub params: OldContractStateParams,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct OldContractStateParams {
|
||||
pub minimum_mixnode_pledge: Uint128,
|
||||
pub minimum_gateway_pledge: Uint128,
|
||||
pub mixnode_rewarded_set_size: u32,
|
||||
pub mixnode_active_set_size: u32,
|
||||
}
|
||||
|
||||
const OLD_CONTRACT_STATE: Item<'_, OldContractState> = Item::new("config");
|
||||
|
||||
let old_contract_state = OLD_CONTRACT_STATE.load(deps.storage)?;
|
||||
|
||||
let old_params = old_contract_state.params;
|
||||
|
||||
let new_params = ContractStateParams {
|
||||
minimum_mixnode_pledge: old_params.minimum_mixnode_pledge,
|
||||
minimum_gateway_pledge: old_params.minimum_gateway_pledge,
|
||||
mixnode_rewarded_set_size: old_params.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: old_params.mixnode_active_set_size,
|
||||
staking_supply: INITIAL_STAKING_SUPPLY,
|
||||
};
|
||||
|
||||
let new_contract_state = ContractState {
|
||||
owner: old_contract_state.owner,
|
||||
rewarding_validator_address: old_contract_state.rewarding_validator_address,
|
||||
params: new_params,
|
||||
};
|
||||
|
||||
CONTRACT_STATE.save(deps.storage, &new_contract_state)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn _deal_with_zero_delegations(deps: DepsMut<'_>) -> Result<(), ContractError> {
|
||||
fn deal_with_zero_delegations(deps: DepsMut<'_>) -> Result<(), ContractError> {
|
||||
// if there exists any delegation of 0 value, remove it
|
||||
let zero_delegations = delegations()
|
||||
.range(deps.storage, None, None, cosmwasm_std::Order::Ascending)
|
||||
@@ -514,7 +466,7 @@ fn _deal_with_zero_delegations(deps: DepsMut<'_>) -> Result<(), ContractError> {
|
||||
|
||||
#[entry_point]
|
||||
pub fn migrate(deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
migrate_contract_state_params(deps)?;
|
||||
deal_with_zero_delegations(deps)?;
|
||||
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::storage;
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use mixnet_contract_common::{ContractStateParams, MixnetContractVersion};
|
||||
|
||||
pub fn query_contract_settings_params(deps: Deps<'_>) -> StdResult<ContractStateParams> {
|
||||
pub(crate) fn query_contract_settings_params(deps: Deps<'_>) -> StdResult<ContractStateParams> {
|
||||
storage::CONTRACT_STATE
|
||||
.load(deps.storage)
|
||||
.map(|settings| settings.params)
|
||||
@@ -51,7 +51,6 @@ pub(crate) mod tests {
|
||||
minimum_gateway_pledge: 456u128.into(),
|
||||
mixnode_rewarded_set_size: 1000,
|
||||
mixnode_active_set_size: 500,
|
||||
staking_supply: 1000000u128.into(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ pub(crate) fn try_update_contract_settings(
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::contract::{INITIAL_GATEWAY_PLEDGE, INITIAL_MIXNODE_PLEDGE, INITIAL_STAKING_SUPPLY};
|
||||
use crate::contract::{INITIAL_GATEWAY_PLEDGE, INITIAL_MIXNODE_PLEDGE};
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnet_contract_settings::queries::query_rewarding_validator_address;
|
||||
use crate::mixnet_contract_settings::transactions::try_update_contract_settings;
|
||||
@@ -114,7 +114,6 @@ pub mod tests {
|
||||
minimum_gateway_pledge: INITIAL_GATEWAY_PLEDGE,
|
||||
mixnode_rewarded_set_size: 100,
|
||||
mixnode_active_set_size: 50,
|
||||
staking_supply: INITIAL_STAKING_SUPPLY,
|
||||
};
|
||||
|
||||
let initial_params = storage::CONTRACT_STATE
|
||||
|
||||
@@ -42,21 +42,10 @@ pub fn incr_reward_pool(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn reward_accounting(storage: &mut dyn Storage, amount: Uint128) -> Result<(), ContractError> {
|
||||
decr_reward_pool(storage, amount)?;
|
||||
incr_staking_supply(storage, amount)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn incr_staking_supply(storage: &mut dyn Storage, amount: Uint128) -> Result<(), ContractError> {
|
||||
let mut contract_state =
|
||||
crate::mixnet_contract_settings::storage::CONTRACT_STATE.load(storage)?;
|
||||
contract_state.params.staking_supply += amount;
|
||||
crate::mixnet_contract_settings::storage::CONTRACT_STATE.save(storage, &contract_state)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn decr_reward_pool(storage: &mut dyn Storage, amount: Uint128) -> Result<Uint128, ContractError> {
|
||||
pub fn decr_reward_pool(
|
||||
storage: &mut dyn Storage,
|
||||
amount: Uint128,
|
||||
) -> Result<Uint128, ContractError> {
|
||||
REWARD_POOL.update(storage, |current_pool| {
|
||||
let stake = current_pool
|
||||
.checked_sub(amount)
|
||||
|
||||
@@ -678,7 +678,7 @@ pub(crate) fn try_reward_mixnode(
|
||||
)?;
|
||||
|
||||
// Take rewards out of the rewarding pool
|
||||
storage::reward_accounting(deps.storage, stored_node_result.reward())?;
|
||||
storage::decr_reward_pool(deps.storage, stored_node_result.reward())?;
|
||||
|
||||
let rewarding_result = RewardingResult {
|
||||
node_reward: stored_node_result.reward(),
|
||||
|
||||
@@ -4,7 +4,8 @@ x-network: &NETWORK
|
||||
BECH32_PREFIX: nymt
|
||||
DENOM: nymt
|
||||
STAKE_DENOM: nyxt
|
||||
WASMD_VERSION: v0.27.0
|
||||
WASMD_VERSION: v0.26.0
|
||||
WASMD_COMMIT_HASH: dc5ef6fe84f0a5e3b0894692a18cc48fb5b00adf
|
||||
|
||||
services:
|
||||
genesis_validator:
|
||||
|
||||
@@ -7,6 +7,6 @@ RUN ./setup.sh
|
||||
|
||||
FROM ubuntu:20.04
|
||||
COPY --from=go_builder /go/wasmd/build/nymd /root/nymd
|
||||
COPY --from=go_builder /go/wasmd/build/libwasmvm*.so /root
|
||||
COPY --from=go_builder /go/wasmd/build/libwasmvm.so /root/libwasmvm.so
|
||||
COPY init_and_start.sh .
|
||||
ENTRYPOINT ["./init_and_start.sh"]
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ue
|
||||
|
||||
git clone https://github.com/CosmWasm/wasmd.git
|
||||
cd wasmd
|
||||
git checkout "${WASMD_VERSION}"
|
||||
WASMD_COMMIT_HASH=$(git rev-parse HEAD)
|
||||
mkdir build
|
||||
go build \
|
||||
-o build/nymd -mod=readonly -tags "netgo,ledger" \
|
||||
@@ -17,4 +14,5 @@ go build \
|
||||
-X github.com/CosmWasm/wasmd/app.Bech32Prefix=${BECH32_PREFIX} \
|
||||
-X 'github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger'" \
|
||||
-trimpath ./cmd/wasmd
|
||||
find .. -type f -name 'libwasm*.so' -exec cp {} build \;
|
||||
WASMVM_SO=$(ldd build/nymd | grep libwasmvm.so | awk '{ print $3 }')
|
||||
cp "${WASMVM_SO}" build/
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"react-error-boundary": "^3.1.4",
|
||||
"react-google-charts": "^3.0.15",
|
||||
"react-identicons": "^1.2.5",
|
||||
"react-router-dom": "6",
|
||||
"react-router": "^5.2.1",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-simple-maps": "^2.3.0",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"use-clipboard-copy": "^0.2.0"
|
||||
@@ -32,11 +33,11 @@
|
||||
"@babel/core": "^7.15.0",
|
||||
"@nymproject/eslint-config-react-typescript": "^1.0.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
|
||||
"@storybook/addon-actions": "^6.5.8",
|
||||
"@storybook/addon-essentials": "^6.5.8",
|
||||
"@storybook/addon-interactions": "^6.5.8",
|
||||
"@storybook/addon-links": "^6.5.8",
|
||||
"@storybook/react": "^6.5.8",
|
||||
"@storybook/addon-actions": "^6.4.19",
|
||||
"@storybook/addon-essentials": "^6.4.19",
|
||||
"@storybook/addon-interactions": "^6.4.19",
|
||||
"@storybook/addon-links": "^6.4.19",
|
||||
"@storybook/react": "^6.4.19",
|
||||
"@storybook/testing-library": "^0.0.9",
|
||||
"@svgr/webpack": "^6.1.1",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
@@ -49,6 +50,8 @@
|
||||
"@types/node": "^16.7.13",
|
||||
"@types/react": "^17.0.34",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"@types/react-router": "^5.1.18",
|
||||
"@types/react-router-dom": "^5.1.8",
|
||||
"@types/react-simple-maps": "^1.0.6",
|
||||
"@types/react-tooltip": "^4.2.4",
|
||||
"@types/topojson-client": "^3.1.0",
|
||||
@@ -71,7 +74,7 @@
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-react": "^7.29.2",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"eslint-plugin-storybook": "^0.5.12",
|
||||
"eslint-plugin-storybook": "^0.5.7",
|
||||
"favicons-webpack-plugin": "^5.0.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"fork-ts-checker-webpack-plugin": "^7.2.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
|
||||
import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard';
|
||||
import { CopyToClipboard } from '@nymproject/react';
|
||||
import { Box } from '@mui/system';
|
||||
import { cellStyles } from './Universal-DataGrid';
|
||||
import { currencyToString } from '../utils/currency';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { Menu } from '@mui/icons-material';
|
||||
import { NymLogo } from '@nymproject/react/logo/NymLogo';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
import { useMainContext } from '../context/main';
|
||||
import { MobileDrawerClose } from '../icons/MobileDrawerClose';
|
||||
import { Footer } from './Footer';
|
||||
|
||||
@@ -14,7 +14,7 @@ import IconButton from '@mui/material/IconButton';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import { NymLogo } from '@nymproject/react/logo/NymLogo';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
import { BIG_DIPPER, NYM_WEBSITE } from '../api/constants';
|
||||
import { useMainContext } from '../context/main';
|
||||
import { MobileDrawerClose } from '../icons/MobileDrawerClose';
|
||||
@@ -84,7 +84,7 @@ export const originalNavOptions: NavOptionType[] = [
|
||||
{
|
||||
id: 0,
|
||||
isActive: false,
|
||||
url: '/',
|
||||
url: '/overview',
|
||||
title: 'Overview',
|
||||
Icon: <OverviewSVG />,
|
||||
},
|
||||
@@ -343,7 +343,7 @@ export const Nav: React.FC = ({ children }) => {
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
<MuiLink component={Link} to="/" underline="none" color="inherit">
|
||||
<MuiLink component={Link} to="/overview" underline="none" color="inherit">
|
||||
Network Explorer
|
||||
</MuiLink>
|
||||
</Typography>
|
||||
|
||||
@@ -44,7 +44,7 @@ export const StatsCard: React.FC<StatsCardProps> = ({ icon, title, count, onClic
|
||||
</Box>
|
||||
{errorMsg && (
|
||||
<Typography variant="body2" sx={{ color: 'danger', padding: 2 }}>
|
||||
{typeof errorMsg === 'string' ? errorMsg : errorMsg.message || 'Oh no! An error occurred'}
|
||||
{errorMsg}
|
||||
</Typography>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
@@ -18,7 +18,7 @@ export const originalNavOptions: NavOptionType[] = [
|
||||
{
|
||||
id: 0,
|
||||
isActive: false,
|
||||
url: '/',
|
||||
url: '/overview',
|
||||
title: 'Overview',
|
||||
Icon: <OverviewSVG />,
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { FallbackProps } from 'react-error-boundary';
|
||||
import { Alert, AlertTitle, Container } from '@mui/material';
|
||||
import { NymThemeProvider } from '@nymproject/mui-theme';
|
||||
import { NymLogo } from '@nymproject/react/logo/NymLogo';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
|
||||
export const ErrorBoundaryContent: React.FC<FallbackProps> = ({ error }) => (
|
||||
<NymThemeProvider mode="dark">
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#121726;}
|
||||
.st1{fill:url(#SVGID_1_);}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st0" cx="250" cy="250.1" r="239.8"/>
|
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="4.980469e-02" y1="5613.9395" x2="500.0498" y2="5613.9395" gradientTransform="matrix(1 0 0 -1 0 5863.9897)">
|
||||
<stop offset="0" style="stop-color:#E1864B"/>
|
||||
<stop offset="1" style="stop-color:#DA465B"/>
|
||||
</linearGradient>
|
||||
<path class="st1" d="M250,500.1c-17,0-33.9-1.7-50.4-5.1c-16.1-3.3-31.8-8.2-46.9-14.6c-14.8-6.3-29.1-14-42.5-23.1
|
||||
c-13.2-8.9-25.7-19.2-37-30.5c-11.3-11.3-21.6-23.8-30.5-37c-9-13.4-16.8-27.6-23.1-42.5c-6.4-15.1-11.3-30.9-14.6-46.9
|
||||
C1.8,284,0,267,0,250.1s1.7-33.9,5.1-50.4c3.3-16.1,8.2-31.8,14.6-46.9c6.3-14.8,14-29.1,23.1-42.5C51.7,97,62,84.6,73.3,73.3
|
||||
s23.8-21.6,37-30.5c13.4-9,27.7-16.8,42.5-23.1c15.1-6.4,30.9-11.3,46.9-14.6c16.5-3.4,33.4-5.1,50.4-5.1c17,0,33.9,1.7,50.4,5.1
|
||||
c16.1,3.3,31.8,8.2,46.9,14.6c14.8,6.3,29.1,14,42.5,23.1c13.2,8.9,25.7,19.2,37,30.5c11.3,11.3,21.6,23.8,30.5,37
|
||||
c9,13.4,16.8,27.7,23.1,42.5c6.4,15.1,11.3,30.9,14.6,46.9c3.4,16.5,5.1,33.4,5.1,50.4s-1.7,33.9-5.1,50.4
|
||||
c-3.3,16.1-8.2,31.8-14.6,46.9c-6.3,14.8-14,29.1-23.1,42.5c-8.9,13.2-19.2,25.7-30.5,37c-11.3,11.3-23.8,21.6-37,30.5
|
||||
c-13.4,9-27.7,16.8-42.5,23.1c-15.1,6.4-30.9,11.3-46.9,14.6C284,498.3,267,500.1,250,500.1z M250,20.5c-15.6,0-31.2,1.6-46.3,4.7
|
||||
c-14.7,3-29.2,7.5-43.1,13.4c-13.6,5.8-26.7,12.9-39,21.2c-12.2,8.2-23.6,17.7-34,28c-10.4,10.4-19.8,21.8-28,34
|
||||
c-8.3,12.3-15.4,25.4-21.2,39c-5.9,13.8-10.4,28.3-13.4,43.1c-3.1,15.1-4.7,30.7-4.7,46.3s1.6,31.2,4.7,46.3
|
||||
c3,14.7,7.5,29.2,13.4,43.1c5.8,13.6,12.9,26.7,21.2,39c8.2,12.2,17.7,23.6,28,34c10.4,10.4,21.8,19.8,34,28
|
||||
c12.3,8.3,25.4,15.4,39,21.2c13.8,5.9,28.3,10.4,43.1,13.4c15.1,3.1,30.7,4.7,46.3,4.7c15.6,0,31.2-1.6,46.3-4.7
|
||||
c14.7-3,29.2-7.5,43.1-13.4c13.6-5.8,26.7-12.9,39-21.2c12.2-8.2,23.6-17.7,34-28c10.4-10.4,19.8-21.8,28-34
|
||||
c8.3-12.3,15.4-25.4,21.2-39c5.9-13.8,10.4-28.3,13.4-43.1c3.1-15.1,4.7-30.7,4.7-46.3s-1.6-31.2-4.7-46.3
|
||||
c-3-14.7-7.5-29.2-13.4-43.1c-5.8-13.6-12.9-26.7-21.2-39c-8.2-12.2-17.7-23.6-28-34c-10.4-10.4-21.8-19.8-34-28
|
||||
c-12.3-8.3-25.4-15.4-39-21.2c-13.8-5.9-28.3-10.4-43.1-13.4C281.2,22,265.6,20.5,250,20.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st2" d="M369.8,341.2h-52.8l-144-142v142h-42.8V158.9h54.1l144,141.9V158.9h41.5V341.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
@@ -1,12 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Button, Grid, Paper, Typography } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { NymLogo } from '@nymproject/react/logo/NymLogo';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
import { useMainContext } from '../../context/main';
|
||||
|
||||
export const Page404: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const history = useHistory();
|
||||
const { mode } = useMainContext();
|
||||
const theme = useTheme();
|
||||
return (
|
||||
@@ -37,7 +37,7 @@ export const Page404: React.FC = () => {
|
||||
bgcolor: theme.palette.primary.main,
|
||||
color: theme.palette.secondary.main,
|
||||
}}
|
||||
onClick={() => navigate('/')}
|
||||
onClick={() => history.push('/overview')}
|
||||
>
|
||||
Overview
|
||||
</Button>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid';
|
||||
import { Button, Card, Grid, Link as MuiLink } from '@mui/material';
|
||||
import { Link as RRDLink, useParams, useNavigate } from 'react-router-dom';
|
||||
import { Link as RRDLink, useParams } from 'react-router-dom';
|
||||
import { SelectChangeEvent } from '@mui/material/Select';
|
||||
import { SxProps } from '@mui/system';
|
||||
import { Theme, useTheme } from '@mui/material/styles';
|
||||
import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard';
|
||||
import { useHistory } from 'react-router';
|
||||
import { CopyToClipboard } from '@nymproject/react';
|
||||
import { useMainContext } from '../../context/main';
|
||||
import { MixnodeRowType, mixnodeToGridRow } from '../../components/MixNodes';
|
||||
import { TableToolbar } from '../../components/TableToolbar';
|
||||
@@ -41,7 +42,7 @@ export const PageMixnodes: React.FC = () => {
|
||||
const [searchTerm, setSearchTerm] = React.useState<string>('');
|
||||
const theme = useTheme();
|
||||
const { status } = useParams<{ status: MixnodeStatusWithAll | undefined }>();
|
||||
const navigate = useNavigate();
|
||||
const history = useHistory();
|
||||
|
||||
const handleSearch = (str: string) => {
|
||||
setSearchTerm(str.toLowerCase());
|
||||
@@ -73,7 +74,7 @@ export const PageMixnodes: React.FC = () => {
|
||||
}, [status]);
|
||||
|
||||
const handleMixnodeStatusChanged = (newStatus?: MixnodeStatusWithAll) => {
|
||||
navigate(
|
||||
history.push(
|
||||
newStatus && newStatus !== MixnodeStatusWithAll.all
|
||||
? `/network-components/mixnodes/${newStatus}`
|
||||
: '/network-components/mixnodes',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Grid, Link, Typography } from '@mui/material';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { WorldMap } from '../../components/WorldMap';
|
||||
import { useMainContext } from '../../context/main';
|
||||
import { formatNumber } from '../../utils';
|
||||
@@ -17,7 +17,7 @@ import { Icons } from '../../components/Icons';
|
||||
|
||||
export const PageOverview: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const history = useHistory();
|
||||
const { summaryOverview, gateways, validators, block, countryData } = useMainContext();
|
||||
return (
|
||||
<Box component="main" sx={{ flexGrow: 1 }}>
|
||||
@@ -31,7 +31,7 @@ export const PageOverview: React.FC = () => {
|
||||
<>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() => navigate('/network-components/mixnodes')}
|
||||
onClick={() => history.push('/network-components/mixnodes')}
|
||||
title="Mixnodes"
|
||||
icon={<MixnodesSVG />}
|
||||
count={summaryOverview.data?.mixnodes.count || ''}
|
||||
@@ -40,7 +40,7 @@ export const PageOverview: React.FC = () => {
|
||||
</Grid>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() => navigate('/network-components/mixnodes/active')}
|
||||
onClick={() => history.push('/network-components/mixnodes/active')}
|
||||
title="Active nodes"
|
||||
icon={<Icons.Mixnodes.Status.Active />}
|
||||
color={theme.palette.nym.networkExplorer.mixnodes.status.active}
|
||||
@@ -50,7 +50,7 @@ export const PageOverview: React.FC = () => {
|
||||
</Grid>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() => navigate('/network-components/mixnodes/standby')}
|
||||
onClick={() => history.push('/network-components/mixnodes/standby')}
|
||||
title="Standby nodes"
|
||||
color={theme.palette.nym.networkExplorer.mixnodes.status.standby}
|
||||
icon={<Icons.Mixnodes.Status.Standby />}
|
||||
@@ -63,7 +63,7 @@ export const PageOverview: React.FC = () => {
|
||||
{gateways && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<StatsCard
|
||||
onClick={() => navigate('/network-components/gateways')}
|
||||
onClick={() => history.push('/network-components/gateways')}
|
||||
title="Gateways"
|
||||
count={gateways?.data?.length || ''}
|
||||
errorMsg={gateways?.error}
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import { Routes as ReactRouterRoutes, Route } from 'react-router-dom';
|
||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||
import { PageOverview } from '../pages/Overview';
|
||||
import { PageMixnodesMap } from '../pages/MixnodesMap';
|
||||
import { Page404 } from '../pages/404';
|
||||
import { NetworkComponentsRoutes } from './network-components';
|
||||
|
||||
export const Routes: React.FC = () => (
|
||||
<ReactRouterRoutes>
|
||||
<Route path="/" element={<PageOverview />} />
|
||||
<Route path="/network-components/*" element={<NetworkComponentsRoutes />} />
|
||||
<Route path="/nodemap" element={<PageMixnodesMap />} />
|
||||
<Route path="*" element={Page404} />
|
||||
</ReactRouterRoutes>
|
||||
<Switch>
|
||||
<Route exact path="/">
|
||||
<Redirect to="/overview" />
|
||||
</Route>
|
||||
<Route exact path="/overview">
|
||||
<PageOverview />
|
||||
</Route>
|
||||
<Route path="/network-components">
|
||||
<NetworkComponentsRoutes />
|
||||
</Route>
|
||||
<Route path="/nodemap">
|
||||
<PageMixnodesMap />
|
||||
</Route>
|
||||
<Route component={Page404} />
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
import * as React from 'react';
|
||||
import { Routes as ReactRouterRoutes, Route, useNavigate } from 'react-router-dom';
|
||||
import { Switch, Route, RouteComponentProps } from 'react-router-dom';
|
||||
import { BIG_DIPPER } from '../api/constants';
|
||||
import { PageGateways } from '../pages/Gateways';
|
||||
import { PageMixnodeDetail } from '../pages/MixnodeDetail';
|
||||
import { PageMixnodes } from '../pages/Mixnodes';
|
||||
|
||||
const ValidatorRoute: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
window.open(`${BIG_DIPPER}/validators`);
|
||||
navigate(-1);
|
||||
return null;
|
||||
};
|
||||
|
||||
export const NetworkComponentsRoutes: React.FC = () => (
|
||||
<ReactRouterRoutes>
|
||||
<Route path="mixnodes/:status" element={<PageMixnodes />} />
|
||||
<Route path="mixnodes" element={<PageMixnodes />} />
|
||||
<Route path="mixnode/:id" element={<PageMixnodeDetail />} />
|
||||
<Route path="gateways" element={<PageGateways />} />
|
||||
<Route path="validators" element={<ValidatorRoute />} />
|
||||
<Route path="gateways/:id" element={<h1> Specific Gateways ID</h1>} />
|
||||
</ReactRouterRoutes>
|
||||
<Switch>
|
||||
<Route exact path="/network-components/mixnodes/:status">
|
||||
<PageMixnodes />
|
||||
</Route>
|
||||
<Route exact path="/network-components/mixnodes">
|
||||
<PageMixnodes />
|
||||
</Route>
|
||||
<Route path="/network-components/mixnode/:id">
|
||||
<PageMixnodeDetail />
|
||||
</Route>
|
||||
<Route path="/network-components/gateways">
|
||||
<PageGateways />
|
||||
</Route>
|
||||
<Route
|
||||
path="/network-components/validators"
|
||||
component={(props: RouteComponentProps) => {
|
||||
window.open(`${BIG_DIPPER}/validators`);
|
||||
props.history.goBack();
|
||||
return null;
|
||||
}}
|
||||
/>
|
||||
<Route path="/network-components/gateways/:id">
|
||||
<h1> Specific Gateways ID</h1>
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@@ -213,7 +213,7 @@ impl MixNode {
|
||||
packet_sender
|
||||
}
|
||||
|
||||
fn start_verloc_measurements(&self, shutdown: ShutdownListener) -> AtomicVerlocResult {
|
||||
fn start_verloc_measurements(&self) -> AtomicVerlocResult {
|
||||
info!("Starting the round-trip-time measurer...");
|
||||
|
||||
// this is a sanity check to make sure we didn't mess up with the minimum version at some point
|
||||
@@ -246,8 +246,7 @@ impl MixNode {
|
||||
.validator_api_urls(self.config.get_validator_api_endpoints())
|
||||
.build();
|
||||
|
||||
let mut verloc_measurer =
|
||||
VerlocMeasurer::new(config, Arc::clone(&self.identity_keypair), shutdown);
|
||||
let mut verloc_measurer = VerlocMeasurer::new(config, Arc::clone(&self.identity_keypair));
|
||||
let atomic_verloc_results = verloc_measurer.get_verloc_results_pointer();
|
||||
tokio::spawn(async move { verloc_measurer.run().await });
|
||||
atomic_verloc_results
|
||||
@@ -332,11 +331,9 @@ impl MixNode {
|
||||
delay_forwarding_channel,
|
||||
shutdown.subscribe(),
|
||||
);
|
||||
let atomic_verloc_results = self.start_verloc_measurements(shutdown.subscribe());
|
||||
|
||||
// Rocket handles shutdown on it's own, but its shutdown handling should be incorporated
|
||||
// with that of the rest of the tasks.
|
||||
// Currently it's runtime is forcefully terminated once the mixnode exits.
|
||||
// TODO: these two also needs to be shutdown
|
||||
let atomic_verloc_results = self.start_verloc_measurements();
|
||||
self.start_http_api(atomic_verloc_results, node_stats_pointer);
|
||||
|
||||
info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!");
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"esmodules": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": ["@babel/plugin-transform-async-to-generator"]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
ADMIN_ADDRESS=
|
||||
@@ -1,112 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"ecmaVersion": 2019,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"plugins": ["react", "react-hooks", "jsx-a11y", "prettier", "jest"],
|
||||
"extends": [
|
||||
"plugin:react/recommended",
|
||||
"airbnb",
|
||||
"prettier",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:jest/style"
|
||||
],
|
||||
"rules": {
|
||||
"jest/prefer-strict-equal": "error",
|
||||
"jest/prefer-to-have-length": "warn",
|
||||
"prettier/prettier": "error",
|
||||
"import/prefer-default-export": "off",
|
||||
"react/prop-types": "off",
|
||||
"react/require-default-props": "off",
|
||||
"react/jsx-filename-extension": "off",
|
||||
"react/jsx-props-no-spreading": "off",
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": [
|
||||
"**/*.test.[jt]s",
|
||||
"**/*.spec.[jt]s",
|
||||
"**/*.test.[jt]sx",
|
||||
"**/*.spec.[jt]sx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"import/extensions": [
|
||||
"error",
|
||||
"ignorePackages",
|
||||
{
|
||||
"ts": "never",
|
||||
"tsx": "never",
|
||||
"js": "never",
|
||||
"jsx": "never"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": "**/*.+(ts|tsx)",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"plugins": ["@typescript-eslint/eslint-plugin"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-use-before-define": [0],
|
||||
"@typescript-eslint/no-use-before-define": [1],
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": [
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.stories.*",
|
||||
"**/.storybook/**/*.*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"quotes": "off",
|
||||
"@typescript-eslint/quotes": [
|
||||
2,
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": [2, { "argsIgnorePattern": "^_" }]
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"root-import": {
|
||||
"rootPathPrefix": "@",
|
||||
"rootPathSuffix": "src",
|
||||
"extensions": [".js", ".ts", ".tsx", ".jsx", ".mdx"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
14
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"trailingComma": "all",
|
||||
"singleQuote": true,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"semi": true
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
module.exports = {
|
||||
stories: [
|
||||
"../src/**/*.stories.mdx",
|
||||
"../src/**/*.stories.@(js|jsx|ts|tsx)"
|
||||
],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials"
|
||||
],
|
||||
framework: "@storybook/react",
|
||||
features: {
|
||||
emotionAlias: false,
|
||||
},
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import '../src/fonts/fonts.css';
|
||||
|
||||
export const Fonts = ({ children }) => <>{children}</>;
|
||||
@@ -1,26 +0,0 @@
|
||||
import { NymMixnetTheme } from '../src/theme';
|
||||
import { ClientContextProvider } from '../src/context/main';
|
||||
import { Fonts } from './preview-fonts';
|
||||
|
||||
const withThemeProvider= (Story, context) =>{
|
||||
return (
|
||||
<Fonts>
|
||||
<ClientContextProvider>
|
||||
<NymMixnetTheme>
|
||||
<Story {...context} />
|
||||
</NymMixnetTheme>
|
||||
</ClientContextProvider>
|
||||
</Fonts>
|
||||
)
|
||||
}
|
||||
export const decorators = [withThemeProvider];
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
[workspace]
|
||||
members = ["src-tauri"]
|
||||
@@ -1,95 +0,0 @@
|
||||
<!--
|
||||
Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
# Nym Connect
|
||||
|
||||
Nym is an open-source, decentralized and permissionless privacy system. It provides full-stack privacy, allowing other applications, services or blockchains to provide their users with strong metadata protection, at both the network level (mixnet), and the application level (anonymous credentials) without the need to build privacy from scratch.
|
||||
|
||||
Nym Connects sets up a SOCKS5 proxy for local applications to use.
|
||||
|
||||
## Installation prerequisites - Linux / Mac
|
||||
|
||||
- `Yarn`
|
||||
- `NodeJS >= v16.8.0`
|
||||
- `Rust & cargo >= v1.56`
|
||||
|
||||
## Installation prerequisites - Windows
|
||||
|
||||
- When running on Windows you will need to install c++ build tools
|
||||
- An easy guide to get rust up and running [Installation]("http://kennykerr.ca/2019/11/18/rust-getting-started/")
|
||||
- When installing NodeJS please use the `current features` version
|
||||
- Using a package manager like [Chocolatey]("chocolatey.org") is recommended
|
||||
- Nym connect requires you to have `Webview2` installed, please head to the [Installer](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section), this will ensure a smooth app launch
|
||||
|
||||
## Installation
|
||||
|
||||
Inside the `nym-connect` directory, run the following command:
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
## Development mode
|
||||
|
||||
You can compile nym-connectin development mode by running the following command inside the `nym-connect` directory:
|
||||
|
||||
```
|
||||
yarn dev
|
||||
```
|
||||
This will produce a binary in - `nym-connect/target/debug/` named `nym-connect`
|
||||
|
||||
To launch, navigate to the directory and run the following command: `./nym-connect`
|
||||
|
||||
## Production mode
|
||||
|
||||
Run the following command from the `nym-connect` folder
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
The output will compile different types of binaries dependent on your hardware / OS system. Once the binaries are built, they can be located as follows:
|
||||
|
||||
### Binary output directory structure
|
||||
```
|
||||
**macos**
|
||||
|
|
||||
└─── target/release
|
||||
| |─ nym-connect
|
||||
└───target/release/bundle/dmg
|
||||
│ │─ bundle_dmg.sh
|
||||
│ │─ nym-connect.*.dmg
|
||||
└───target/release/bundle/macos/MacOs
|
||||
│ │─ nym-connect
|
||||
|
|
||||
**Linux**
|
||||
└─── target/release
|
||||
| │─ nym-connect
|
||||
└───target/release/bundle/appimage
|
||||
│ │─ nym-connect_*_.AppImage
|
||||
│ │─ build_appimage.sh
|
||||
└───target/release/bundle/deb
|
||||
│ │─ nym-connect_*_.deb
|
||||
|
|
||||
**Windows**
|
||||
└─── target/release
|
||||
| │─ nym-connect.exe
|
||||
└───target/release/bundle/msi
|
||||
│ │─ nym-connect_*_.msi
|
||||
```
|
||||
|
||||
For instructions on how to release nym-connect, please see [RELEASE.md](./docs/release/RELEASE.md).
|
||||
|
||||
# Storybook
|
||||
|
||||
Run storybook with:
|
||||
|
||||
```
|
||||
yarn storybook
|
||||
```
|
||||
|
||||
And build storybook static site with:
|
||||
|
||||
```
|
||||
yarn storybook:build
|
||||
```
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export const config = {
|
||||
DOCS_BASE_URL: 'https://nymtech.net/docs',
|
||||
};
|
||||
@@ -1,91 +0,0 @@
|
||||
{
|
||||
"name": "@nym/nym-connect",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"webpack:dev": "yarn webpack serve --config webpack.dev.js",
|
||||
"webpack:prod": "yarn webpack --progress --config webpack.prod.js",
|
||||
"tauri:dev": "RUST_DEBUG=1 yarn tauri dev",
|
||||
"tauri:build": "yarn tauri build",
|
||||
"dev": "run-p webpack:dev tauri:dev",
|
||||
"build": "run-s webpack:prod tauri:build",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"storybook:build": "build-storybook",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@emotion/react": "^11.7.0",
|
||||
"@emotion/styled": "^11.6.0",
|
||||
"@hookform/resolvers": "^2.8.0",
|
||||
"@mui/icons-material": "^5.2.0",
|
||||
"@mui/material": "^5.2.2",
|
||||
"@mui/styles": "^5.2.2",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"bs58": "^4.0.1",
|
||||
"clsx": "^1.1.1",
|
||||
"luxon": "^2.3.0",
|
||||
"pretty-bytes": "^6.0.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"react-hook-form": "^7.14.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"semver": "^6.3.0",
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.14.5",
|
||||
"@babel/preset-env": "^7.15.0",
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@storybook/addon-actions": "^6.4.18",
|
||||
"@storybook/addon-essentials": "^6.4.18",
|
||||
"@storybook/addon-links": "^6.4.18",
|
||||
"@storybook/react": "^6.4.18",
|
||||
"@svgr/webpack": "^6.1.1",
|
||||
"@tauri-apps/api": "^1.0.0-rc.4",
|
||||
"@tauri-apps/cli": "^1.0.0-rc.9",
|
||||
"@types/bs58": "^4.0.1",
|
||||
"@types/luxon": "^2.0.9",
|
||||
"@types/qrcode.react": "^1.0.2",
|
||||
"@types/react-router-dom": "^5.1.8",
|
||||
"@types/semver": "^7.3.8",
|
||||
"@typescript-eslint/eslint-plugin": "4.31.0",
|
||||
"@typescript-eslint/parser": "4.31.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-root-import": "^6.6.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-airbnb": "18.2.1",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-import-resolver-root-import": "1.0.4",
|
||||
"eslint-plugin-import": "2.24.2",
|
||||
"eslint-plugin-jest": "^24.4.0",
|
||||
"eslint-plugin-jsx-a11y": "6.4.1",
|
||||
"eslint-plugin-prettier": "4.0.0",
|
||||
"eslint-plugin-react": "7.25.1",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
"favicons": "^6.2.2",
|
||||
"favicons-webpack-plugin": "^5.0.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"jest": "^27.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "2.3.2",
|
||||
"style-loader": "^3.2.1",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^4.4.2",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.64.3",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"webpack-dev-server": "^4.5.0",
|
||||
"webpack-merge": "^5.8.0"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>nym-connect</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
WixTools
|
||||
@@ -1,50 +0,0 @@
|
||||
[package]
|
||||
name = "nym-connect"
|
||||
version = "1.0.0"
|
||||
description = "nym-connect"
|
||||
authors = ["Nym Technologies SA"]
|
||||
license = ""
|
||||
repository = ""
|
||||
default-run = "nym-connect"
|
||||
edition = "2021"
|
||||
build = "src/build.rs"
|
||||
rust-version = "1.58"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "=1.0.0-rc.7", features = [] }
|
||||
|
||||
tauri-codegen = "=1.0.0-rc.5"
|
||||
tauri-macros = "=1.0.0-rc.5"
|
||||
|
||||
[dependencies]
|
||||
|
||||
bip39 = "1.0"
|
||||
dirs = "4.0"
|
||||
eyre = "0.6.5"
|
||||
futures = "0.3"
|
||||
once_cell = "1.12"
|
||||
rand = "0.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tauri = { version = "=1.0.0-rc.8", features = ["ayatana-tray", "shell-open", "system-tray"] }
|
||||
tendermint-rpc = "0.23.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.19.1", features = ["sync"] }
|
||||
url = "2.2"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.4.0"
|
||||
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs", branch = "release"}
|
||||
|
||||
client-core = { path = "../../clients/client-core" }
|
||||
nym-socks5-client = { path = "../../clients/socks5" }
|
||||
config = { path = "../../common/config" }
|
||||
|
||||
[dev-dependencies]
|
||||
ts-rs = "6.1.2"
|
||||
tempfile = "3.3.0"
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 56 KiB |
@@ -1,3 +0,0 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
use log::info;
|
||||
use once_cell::sync::Lazy;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::Rng;
|
||||
|
||||
use client_core::client::key_manager::KeyManager;
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use config::NymConfig;
|
||||
|
||||
// Generate a random id used for the config, since we need to init a new configuration each time
|
||||
// due to not being able to reuse gateway registration. This is probably something we should
|
||||
// improve.
|
||||
pub static SOCKS5_CONFIG_ID: Lazy<String> = Lazy::new(|| {
|
||||
let mut rng = rand::thread_rng();
|
||||
format!("{}{:08}", "nym-connect-", rng.gen::<u64>())
|
||||
});
|
||||
|
||||
// TODO: make this configurable from the UI
|
||||
pub static PROVIDER_ADDRESS: &str = "EWa8DgePKfuWSjqPo6NEdavBK6gpnK4TKb2npi2HWuC2.6PGVT9y83UMGbFrPKDnCvTP2jJjpXYpD87ZpiRsLo1YR@CgQrYP8etksSBf4nALNqp93SHPpgFwEUyTsjBNNLj5WM";
|
||||
|
||||
const DEFAULT_ETH_ENDPOINT: &str = "https://rinkeby.infura.io/v3/00000000000000000000000000000000";
|
||||
const DEFAULT_ETH_PRIVATE_KEY: &str =
|
||||
"0000000000000000000000000000000000000000000000000000000000000001";
|
||||
|
||||
pub struct Config {}
|
||||
|
||||
impl Config {
|
||||
pub async fn init() {
|
||||
info!("Initialising...");
|
||||
init_socks5(PROVIDER_ADDRESS, None).await;
|
||||
info!("Configuration saved 🚀");
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_socks5(provider_address: &str, chosen_gateway_id: Option<&str>) {
|
||||
let id: &str = &SOCKS5_CONFIG_ID;
|
||||
log::trace!("Creating config for id: {}", id);
|
||||
let mut config = nym_socks5::client::config::Config::new(id, provider_address);
|
||||
|
||||
// create identity, encryption and ack keys.
|
||||
let mut rng = OsRng;
|
||||
let mut key_manager = KeyManager::new(&mut rng);
|
||||
|
||||
info!("Getting gateway details");
|
||||
let gateway_details = nym_socks5::commands::init::gateway_details(
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
info!("Registering with gateway");
|
||||
let shared_keys = nym_socks5::commands::init::register_with_gateway(
|
||||
&gateway_details,
|
||||
key_manager.identity_keypair(),
|
||||
)
|
||||
.await;
|
||||
|
||||
info!("Setting gateway endpoint");
|
||||
config.get_base_mut().with_gateway_endpoint(
|
||||
gateway_details.identity_key.to_base58_string(),
|
||||
gateway_details.owner.clone(),
|
||||
gateway_details.clients_address(),
|
||||
);
|
||||
|
||||
info!("Insert gateway shared key");
|
||||
key_manager.insert_gateway_shared_key(shared_keys);
|
||||
|
||||
info!("Creating client key path finder");
|
||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||
key_manager
|
||||
.store_keys(&pathfinder)
|
||||
.expect("Failed to generated keys");
|
||||
info!("Saved all generated keys");
|
||||
|
||||
// As far as I'm aware, these two are not used, they are only set because the socks5 init code
|
||||
// requires them for initialising the bandwidth controller.
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_eth_endpoint(DEFAULT_ETH_ENDPOINT);
|
||||
config
|
||||
.get_base_mut()
|
||||
.with_eth_private_key(DEFAULT_ETH_PRIVATE_KEY);
|
||||
|
||||
let config_save_location = config.get_config_file_save_location();
|
||||
config
|
||||
.save_to_file(None)
|
||||
.expect("Failed to save the config file");
|
||||
info!("Saved configuration file to {:?}", config_save_location);
|
||||
info!("Using gateway: {}", config.get_base().get_gateway_id(),);
|
||||
info!("Client configuration completed.\n\n\n");
|
||||
|
||||
nym_socks5::commands::init::show_address(&config);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
use serde::{Serialize, Serializer};
|
||||
use thiserror::Error;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BackendError {
|
||||
#[error("State error")]
|
||||
StateError,
|
||||
#[error("Could not connect")]
|
||||
CouldNotConnect,
|
||||
#[error("Could not disconnect")]
|
||||
CouldNotDisconnect,
|
||||
}
|
||||
|
||||
impl Serialize for BackendError {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.collect_str(self)
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
#![cfg_attr(
|
||||
all(not(debug_assertions), target_os = "windows"),
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use tauri::Menu;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::menu::AddDefaultSubmenus;
|
||||
use crate::menu::{create_tray_menu, tray_menu_event_handler};
|
||||
use crate::state::State;
|
||||
use crate::window::window_toggle;
|
||||
|
||||
mod config;
|
||||
mod error;
|
||||
mod menu;
|
||||
mod models;
|
||||
mod operations;
|
||||
mod state;
|
||||
mod window;
|
||||
|
||||
fn main() {
|
||||
setup_logging();
|
||||
println!("Starting up...");
|
||||
|
||||
// As per breaking change description here
|
||||
// https://github.com/tauri-apps/tauri/blob/feac1d193c6d618e49916ad0707201f43d5cdd36/tooling/bundler/CHANGELOG.md
|
||||
if let Err(error) = fix_path_env::fix() {
|
||||
log::warn!("Failed to fix PATH: {error}");
|
||||
}
|
||||
|
||||
tauri::Builder::default()
|
||||
.manage(Arc::new(RwLock::new(State::new())))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
crate::operations::connection::connect::start_connecting,
|
||||
crate::operations::connection::disconnect::start_disconnecting,
|
||||
crate::operations::window::hide_window,
|
||||
])
|
||||
.menu(Menu::new().add_default_app_submenu_if_macos())
|
||||
.system_tray(create_tray_menu())
|
||||
.on_system_tray_event(tray_menu_event_handler)
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
fn setup_logging() {
|
||||
let mut log_builder = pretty_env_logger::formatted_timed_builder();
|
||||
if let Ok(s) = ::std::env::var("RUST_LOG") {
|
||||
log_builder.parse_filters(&s);
|
||||
} else {
|
||||
// default to 'Info'
|
||||
log_builder.filter(None, log::LevelFilter::Info);
|
||||
}
|
||||
|
||||
log_builder
|
||||
.filter_module("handlebars", log::LevelFilter::Warn)
|
||||
.init();
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
use crate::window_toggle;
|
||||
use tauri::{
|
||||
AppHandle, CustomMenuItem, Menu,
|
||||
SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, Wry,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::{CustomMenuItem, MenuItem, Submenu, SystemTray, SystemTrayMenu, SystemTrayMenuItem};
|
||||
|
||||
pub trait AddDefaultSubmenus {
|
||||
fn add_default_app_submenu_if_macos(self) -> Self;
|
||||
}
|
||||
|
||||
impl AddDefaultSubmenus for Menu {
|
||||
fn add_default_app_submenu_if_macos(self) -> Menu {
|
||||
#[cfg(target_os = "macos")]
|
||||
return self
|
||||
.add_submenu(Submenu::new(
|
||||
"File",
|
||||
Menu::new().add_native_item(MenuItem::Quit),
|
||||
))
|
||||
.add_submenu(Submenu::new(
|
||||
"Edit",
|
||||
Menu::new()
|
||||
.add_native_item(MenuItem::Copy)
|
||||
.add_native_item(MenuItem::Cut)
|
||||
.add_native_item(MenuItem::Paste)
|
||||
.add_native_item(MenuItem::SelectAll),
|
||||
))
|
||||
.add_submenu(Submenu::new(
|
||||
"Window",
|
||||
Menu::new()
|
||||
.add_native_item(MenuItem::Hide)
|
||||
.add_native_item(MenuItem::HideOthers)
|
||||
.add_native_item(MenuItem::ShowAll),
|
||||
));
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
pub const TRAY_MENU_QUIT: &str = "quit";
|
||||
pub const TRAY_MENU_SHOW_HIDE: &str = "show-hide";
|
||||
pub const TRAY_MENU_CONNECTION: &str = "connection";
|
||||
|
||||
pub(crate) fn create_tray_menu() -> SystemTray {
|
||||
let quit = CustomMenuItem::new(TRAY_MENU_QUIT, "Quit");
|
||||
let hide = CustomMenuItem::new(TRAY_MENU_SHOW_HIDE, "Hide");
|
||||
let connection = CustomMenuItem::new(TRAY_MENU_CONNECTION, "Connect");
|
||||
let tray_menu = SystemTrayMenu::new()
|
||||
.add_item(hide)
|
||||
.add_item(connection)
|
||||
.add_native_item(SystemTrayMenuItem::Separator)
|
||||
.add_item(quit);
|
||||
|
||||
SystemTray::new().with_menu(tray_menu)
|
||||
}
|
||||
|
||||
pub(crate) fn tray_menu_event_handler(app: &AppHandle<Wry>, event: SystemTrayEvent) {
|
||||
match event {
|
||||
SystemTrayEvent::LeftClick { position, size, .. } => {
|
||||
println!("Event {:?} {:?}", position, size);
|
||||
}
|
||||
SystemTrayEvent::MenuItemClick { id, .. } => {
|
||||
println!("Event {}", id);
|
||||
match id.as_str() {
|
||||
TRAY_MENU_SHOW_HIDE => {
|
||||
window_toggle(app);
|
||||
}
|
||||
TRAY_MENU_QUIT => {
|
||||
// TODO: add disconnecting first
|
||||
app.exit(0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct ConnectResult {
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct DisconnectResult {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(rename_all = "lowercase"))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ConnectionStatusKind {
|
||||
Disconnected,
|
||||
Disconnecting,
|
||||
Connected,
|
||||
Connecting,
|
||||
}
|
||||
|
||||
pub const APP_EVENT_CONNECTION_STATUS_CHANGED: &str = "app:connection-status-changed";
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
pub struct AppEventConnectionStatusChangedPayload {
|
||||
pub status: ConnectionStatusKind,
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
use crate::error::BackendError;
|
||||
use crate::models::ConnectResult;
|
||||
use crate::State;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn start_connecting(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
window: tauri::Window<tauri::Wry>,
|
||||
) -> Result<ConnectResult, BackendError> {
|
||||
let mut guard = state.write().await;
|
||||
|
||||
guard.start_connecting(&window).await;
|
||||
|
||||
Ok(ConnectResult {
|
||||
// WIP(JON): fixme
|
||||
address: "Test".to_string(),
|
||||
})
|
||||
}
|
||||