Compare commits

..

51 Commits

Author SHA1 Message Date
Mark Sinclair e12549e021 Update change log 2022-06-09 17:03:27 +01:00
Mark Sinclair fed1136f29 Merge branch 'develop' into feature/wallet-delegation-ui-squashed
# Conflicts:
#	nym-wallet/src-tauri/src/coin.rs
2022-06-09 17:00:07 +01:00
Mark Sinclair 44c437e8ac Show admin page when account matches account id from .env file ADMIN_ADDRESS map. Value is fetch from GH Actions secrets at build time. 2022-06-09 16:43:38 +01:00
Mark Sinclair 40c07642a4 Show app version at bottom of nav 2022-06-09 15:39:56 +01:00
fmtabbara 6eb0742a69 tommy fixes 2022-06-09 15:35:11 +01:00
fmtabbara b15292e403 fix up coin validation 2022-06-09 12:15:29 +01:00
fmtabbara 2a4b80062d display est fee until new simulations are used 2022-06-08 12:57:51 +01:00
fmtabbara 9d856c5f7d add compound success case 2022-06-08 12:07:05 +01:00
fmtabbara dc7feeabf4 update validation for hostname (prevent leading spaces) 2022-06-08 11:16:38 +01:00
Jędrzej Stuczyński e448136ee4 Merge with develop 2022-06-08 10:33:42 +01:00
fmtabbara 91640f1559 remove old delegations pages + remove settings modal + update network explorer url 2022-06-07 17:49:32 +01:00
fmtabbara 9092a80b93 refresh locked tokens on page load 2022-06-06 16:48:01 +01:00
fmtabbara 3e9aa02264 set up compound rewards 2022-06-06 16:06:29 +01:00
fmtabbara bf91e8995a handle reedem and vesting redeem requests 2022-06-06 15:21:35 +01:00
fmtabbara 0894be7981 handle page overflow 2022-06-06 15:21:06 +01:00
fmtabbara 9503521ecc fix lint errors 2022-06-06 12:08:47 +01:00
fmtabbara 78e0ae07fb allow sorting of pending events 2022-06-06 12:08:47 +01:00
Jędrzej Stuczyński 24c146766d Merge with wallet-claim-rewards 2022-06-06 12:04:15 +01:00
durch 282b18660f PR comments 2022-06-06 12:38:33 +02:00
durch 184dd7767d Sort CHANGELOG lines 2022-06-06 11:28:36 +02:00
durch 2483a545b7 CHANGELOG 2022-06-06 11:27:09 +02:00
durch df1926071a Add claim and compound wallet endpoints, proc_macro to generate execute and simulate 2022-06-06 11:21:35 +02:00
fmtabbara 3519d0c31d Merge branch 'develop' into feature/wallet-delegation-ui-squashed 2022-06-01 16:32:34 +01:00
fmtabbara a33c21d438 Merge branch 'develop' into feature/wallet-delegation-ui-squashed 2022-06-01 11:23:05 +01:00
Jędrzej Stuczyński 04d02b08bc Merged with develop 2022-06-01 11:15:41 +01:00
Jędrzej Stuczyński 9460276131 Bunch of temporary workaround to have wallet working-ish 2022-06-01 10:59:41 +01:00
Jędrzej Stuczyński 84c9394eba Broken, but compilable first stage of post-merging 2022-06-01 09:57:40 +01:00
fmtabbara 6030d3831f refresh on network or client details change 2022-05-31 15:54:31 +01:00
Jędrzej Stuczyński 241f0cf93a changelog 2022-05-31 11:48:29 +01:00
Jędrzej Stuczyński 11122635f9 Refactored missed coin-generic API methods 2022-05-31 11:43:04 +01:00
Jędrzej Stuczyński ea54a3edc2 Merge with develop 2022-05-31 10:50:02 +01:00
Jędrzej Stuczyński 985a38429d Fixed up tests and clippy 2022-05-31 10:43:17 +01:00
fmtabbara c9f821864a only return events table if there are events 2022-05-31 10:06:29 +01:00
fmtabbara 37d55f3a06 handle undelegation of locked tokens 2022-05-30 22:07:05 +01:00
fmtabbara b2ce142c17 integrate modal divider with modal component 2022-05-30 22:06:23 +01:00
Jędrzej Stuczyński 374baa5ec1 Fixed validator api 2022-05-30 16:13:48 +01:00
Jędrzej Stuczyński de1df74eb5 Simplified the API by removing the generics in favour of explicit Coin type 2022-05-30 16:09:37 +01:00
Jędrzej Stuczyński 766c31544e Made wallet compilable with the recent changes 2022-05-30 15:58:31 +01:00
Jędrzej Stuczyński ecca7e8479 CoinConverter trait 2022-05-30 14:51:12 +01:00
Jędrzej Stuczyński 84a42f6ed9 Changed client API to use the new coin type 2022-05-30 14:46:05 +01:00
Jędrzej Stuczyński 5925e85684 try_add 2022-05-30 11:37:18 +01:00
Jędrzej Stuczyński 972c60726c Additional From implementations plus a constructor 2022-05-30 11:31:58 +01:00
fmtabbara ece22b9703 spell delegations correctly! 2022-05-30 11:29:02 +01:00
Jędrzej Stuczyński 3f718feb41 Created nymd internal coin 2022-05-30 11:22:44 +01:00
fmtabbara b550c32db6 update wording 2022-05-30 11:20:11 +01:00
fmtabbara 83090c0a25 use token pool selector 2022-05-30 11:16:52 +01:00
fmtabbara 97ad1a2e46 fix duplicate key 2022-05-30 11:16:19 +01:00
fmtabbara 9fbefa34e8 get wallet balance after transactions 2022-05-30 09:06:16 +01:00
Mark Sinclair 0812296399 Integrate fees changes:
- make operations available as requests (typed with any for now, needs changing)
- move `FeeDetails` to `common/types`
- mock `getGasFee()`
2022-05-27 18:33:02 +01:00
Mark Sinclair 51b04081a3 Fix rebase errors 2022-05-27 17:44:52 +01:00
tommy 7f2027ca6b Delegation UI:
Update QA vars

fmt

re-map coin type for qa

add correct bech32 address as the network-explorer-api was complaining

clean up

fmt

Delegation components

Show delegation story on paper

Remove actions header from delegations list

Add copy to clipboard for delegation list node ids

Move tooltip

Modals

Extract modal styles

Fix exports

Rewards summary and redeem modal

Factor out simple modal

Delegations actions modals: delegate, delegate more, undelegate

Coin mark and move logo stories

Rust types

React components handle currency

Form field to enter and display an Identity Key

Fix up build order

Update README

Flat buttons

End adornment

Currency form field

Add more props

Export components

Add currency and mixnode fields

Group stories into folders and add flow

Change exports from shared packages to stop webpack bundling issues

Fix logo import

Add mock for tauri api in storybook that shows a console error for operations that are not mocked

Delegations views and routes for wallet

Delegations list show pending delegations and undelegations

wip - delegations page status

Add typescript type checking to storybook webpack config and more mocks for tauri

Add more interstitial states and confirmation modals

Copy change

Move config to inside source tree

Fix up `Console` typings

Add wrapper around Tauri `invoke` that logs operations in development mode

wip

wip

wip

ts-rs: remove old files

ts-rs: update paths to `ts-packages/types`

ts-rs: remove old files

ts-rs: export new types to `ts-packages/types`

Add `MajorCurrencyAmount` to convert to and from TS types for various backend currency types

New crate `nym-types` to provide types for frontend apps (wallet, explorer, etc)

wip

update type imports and fix some lint errors

update packages

update type imports

update type imports

update type imports

update type imports

start pulling out use of  minorMajor and majorMinor

update type imports

update import

Add missing types generated by ts-rs

fix types

Adding denom to account

type updates

Handle micro currency denoms

Fix type conversion mistake

Add clean target

eslint: formatting

Update React currency components to use `MajorCurrencyAmount`

Add separators and extra props to currency components

replace currency mapper with denom returning from service

Adjust type while generation is broken

start integrating new CurrencyFormField component

update balance and vesting on client change (not only client address)

Fix up conversion from cosmwasm coin to major currency for minor denoms

Fix up typings and validations to remove more `Coin` usage

fix conflict

fix delegations form

start fixing validation

type update

remove console log

tidy up

remove more unused types

remove more unused types

Fix `Coin` denom to be `minor`

Fix up to minor_cosmos_coin

Fix up send

Remove `Coin` type

Fix up exported types

start delegation UI

more UI work

close actions modal on action select

update label

fix old delegateion form

minor updates

undo change to currency in stringD

Fix up types

Add feature flag for generating typescript
Generate types behind feature flag

Use custom cli tool to export `ts-rs` types

`ts-rs-cli` moves files into place and fix up `Makefile`

Update generations target

Add missing types for generation

Generate typescript types

reorder imports

use make generate-typescript for new types + type import updates

update types

Add delegate with everything

Add get block to nymd client

More conversions

Get a big list of delegations with lots of stuff

Add `avg_uptime_percent`

component api updates

ui updates and fixes

Add delegation history and pending events

Fix up addition

Fix up pending delegation event types

Filter pending delegation events

add history and pending events

set total delegations

rebase

fix breaking type change on delegate page

Fix mixnode mapping

Add back refresh and set periodic refresh

upgrade to react router 6

Add logging
Export new types for gas and transactions

increase container size!

add sendtx type

update onOK to return MAjorCurrencyAmount

align table items

display dash if amount not availble

work on delegate and undelegate

Make serializable

More types

Fix up errors

align item icon

type updates

Add operation to get all pending delegation/undelegation events

Fix up logging

Add more logging

Fix undelegate error

get pending delegation events

remove unused import
2022-05-27 16:50:16 +01:00
243 changed files with 2676 additions and 30800 deletions
-59
View File
@@ -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 }}
```
-12
View File
@@ -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,8 +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
- wallet: staking_supply field to StateParams
- wallet: show transaction hash for redeeming or compounding rewards
- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328])
### Fixed
@@ -43,15 +37,12 @@ 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])
- wallet: overwritten the `32x32.png` icon with a higher resolution variant to temporarily fix icon issues on Linux (#[1354])
### Changed
- validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]]
- all: updated all `cosmwasm`-related dependencies to `1.0.0` and `cw-storage-plus` to `0.13.4` [[#1318]]
- network-requester: allow to voluntarily store and send statistical data about the number of bytes the proxied server serves ([#1328])
- wallet: updated backend to `tauri v1.0.0-rc.14` (#[1354])
[#1249]: https://github.com/nymtech/nym/pull/1249
[#1256]: https://github.com/nymtech/nym/pull/1256
@@ -69,10 +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
[#1354]: https://github.com/nymtech/nym/pull/1354
## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04)
Generated
-1
View File
@@ -2852,7 +2852,6 @@ dependencies = [
"nymsphinx-types",
"rand 0.8.5",
"serde",
"task",
"tokio",
"tokio-util 0.7.3",
"url",
+5 -20
View File
@@ -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
-8
View File
@@ -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
-96
View File
@@ -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');
}
+1 -1
View File
@@ -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> {
+1 -26
View File
@@ -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
+3 -6
View File
@@ -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(
+1 -1
View File
@@ -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;
-5
View File
@@ -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 {
-1
View File
@@ -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")
}
}
}
}
+32 -64
View File
@@ -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;
}
}
}
+26 -71
View File
@@ -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,
}
+44 -72
View File
@@ -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...
+28 -2
View File
@@ -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",
]
}
}
+2 -50
View File
@@ -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
+4 -15
View File
@@ -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)
+1 -1
View File
@@ -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(),
+2 -1
View File
@@ -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:
+1 -1
View File
@@ -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"]
+2 -4
View File
@@ -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/
+10 -7
View File
@@ -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 -1
View File
@@ -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';
@@ -149,6 +149,14 @@ export const BondBreakdownTable: React.FC = () => {
>
Delegations&nbsp;&nbsp;
</Typography>
<Typography
sx={{
fontSize: 12,
fontWeight: 400,
}}
>
{`(${uniqDelegations?.data?.length} delegators)`}
</Typography>
</Box>
<Table stickyHeader>
<TableHead>
+1 -1
View File
@@ -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';
+3 -3
View File
@@ -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>
+7 -4
View File
@@ -10,7 +10,7 @@ import { DiscordIcon } from '../icons/socials/DiscordIcon';
export const TELEGRAM_LINK = 'https://t.me/nymchan';
export const TWITTER_LINK = 'https://twitter.com/nymproject';
export const GITHUB_LINK = 'https://github.com/nymtech';
export const DISCORD_LINK = 'https://discord.gg/nym';
export const DISCORD_LINK = 'https://discord.gg/ggxrUpbNnn';
export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => {
const theme = useTheme();
@@ -22,9 +22,12 @@ export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => {
<IconButton component="a" href={TELEGRAM_LINK} target="_blank" data-testid="telegram">
<TelegramIcon color={color} size={24} />
</IconButton>
<IconButton component="a" href={DISCORD_LINK} target="_blank" data-testid="discord">
<DiscordIcon color={color} size={24} />
</IconButton>
{false && (
<IconButton component="a" href={DISCORD_LINK} target="_blank" data-testid="discord">
<DiscordIcon color={color} size={24} />
</IconButton>
)}
<IconButton component="a" href={TWITTER_LINK} target="_blank" data-testid="twitter">
<TwitterIcon color={color} size={24} />
</IconButton>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -18,7 +18,7 @@ export const originalNavOptions: NavOptionType[] = [
{
id: 0,
isActive: false,
url: '/',
url: '/overview',
title: 'Overview',
Icon: <OverviewSVG />,
},
+1 -1
View File
@@ -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">
+37
View File
@@ -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

+4 -4
View File
@@ -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>
+2 -2
View File
@@ -63,7 +63,7 @@ const columns: ColumnsType[] = [
* Shows mix node details
*/
const PageMixnodeDetailWithState: React.FC = () => {
const { mixNode, mixNodeRow, description, stats, status, uptimeStory, uniqDelegations } = useMixnodeContext();
const { mixNode, mixNodeRow, description, stats, status, uptimeStory } = useMixnodeContext();
return (
<Box component="main">
@@ -95,7 +95,7 @@ const PageMixnodeDetailWithState: React.FC = () => {
<Grid container spacing={2} mt={0}>
<Grid item xs={12}>
<ContentCard title={`Stake Breakdown (${uniqDelegations?.data?.length} delegators)`}>
<ContentCard title="Stake Breakdown">
<BondBreakdownTable />
</ContentCard>
</Grid>
+13 -11
View File
@@ -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';
@@ -19,8 +20,8 @@ import { splice } from '../../utils';
import { getMixNodeStatusColor } from '../../components/MixNodes/Status';
import { MixNodeStatusDropdown } from '../../components/MixNodes/StatusDropdown';
const getCellFontStyle = (theme: Theme, row: MixnodeRowType, textColor?: string) => {
const color = textColor || getMixNodeStatusColor(theme, row.status);
const getCellFontStyle = (theme: Theme, row: MixnodeRowType) => {
const color = getMixNodeStatusColor(theme, row.status);
return {
fontWeight: 400,
fontSize: 12,
@@ -28,10 +29,10 @@ const getCellFontStyle = (theme: Theme, row: MixnodeRowType, textColor?: string)
};
};
const getCellStyles = (theme: Theme, row: MixnodeRowType, textColor?: string): SxProps => ({
const getCellStyles = (theme: Theme, row: MixnodeRowType): SxProps => ({
...cellStyles,
// TODO: should these be here, or change in `cellStyles`??
...getCellFontStyle(theme, row, textColor),
...getCellFontStyle(theme, row),
});
export const PageMixnodes: React.FC = () => {
@@ -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',
@@ -189,7 +190,8 @@ export const PageMixnodes: React.FC = () => {
<MuiLink
sx={{
textAlign: 'left',
...getCellStyles(theme, params.row, params.value > 100 ? 'theme.palette.warning.main' : undefined),
color: params.value > 100 ? theme.palette.warning.main : 'inherit',
...getCellStyles(theme, params.row),
}}
component={RRDLink}
to={`/network-components/mixnode/${params.row.identity_key}`}
@@ -235,8 +237,8 @@ export const PageMixnodes: React.FC = () => {
},
{
field: 'avg_uptime',
headerName: 'Avg. Uptime',
renderHeader: () => <CustomColumnHeading headingTitle="Avg. Uptime" />,
headerName: 'Average Uptime',
renderHeader: () => <CustomColumnHeading headingTitle="Average Uptime" />,
headerClassName: 'MuiDataGrid-header-override',
width: 160,
headerAlign: 'left',
+6 -6
View File
@@ -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}
+16 -7
View File
@@ -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>
);
+26 -16
View File
@@ -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>
);
+4 -7
View File
@@ -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!");
-15
View File
@@ -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
View File
@@ -1 +0,0 @@
ADMIN_ADDRESS=
-112
View File
@@ -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
View File
@@ -1 +0,0 @@
14
-7
View File
@@ -1,7 +0,0 @@
{
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 2,
"semi": true
}
-14
View File
@@ -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,
},
}
-3
View File
@@ -1,3 +0,0 @@
import '../src/fonts/fonts.css';
export const Fonts = ({ children }) => <>{children}</>;
-26
View File
@@ -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$/,
},
},
}
-7060
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -1,2 +0,0 @@
[workspace]
members = ["src-tauri"]
-95
View File
@@ -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
```
-3
View File
@@ -1,3 +0,0 @@
export const config = {
DOCS_BASE_URL: 'https://nymtech.net/docs',
};
-91
View File
@@ -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.6",
"@tauri-apps/cli": "^1.0.0-rc.12",
"@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"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

-11
View File
@@ -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>
-4
View File
@@ -1,4 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/
WixTools
-47
View File
@@ -1,47 +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.12", features = [] }
[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.14", 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"]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

-3
View File
@@ -1,3 +0,0 @@
fn main() {
tauri_build::build()
}
-93
View File
@@ -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);
}
-22
View File
@@ -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)
}
}
-60
View File
@@ -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();
}

Some files were not shown because too many files have changed in this diff Show More