Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a94272ffd6 | |||
| 773f9e5ead | |||
| 79f695f138 | |||
| 3aabbcf876 | |||
| d96b7408db | |||
| 728b0f4549 | |||
| 0a37c81709 | |||
| 957cbb45b0 | |||
| 8ec074cb1f | |||
| ab5740087f | |||
| 6af59c303e | |||
| 27b384e034 | |||
| 7f5ce3ffeb | |||
| 89b6667c75 | |||
| a94a9aeaf5 | |||
| 6bc8b88a20 | |||
| 21f3991714 | |||
| cd8eba988a | |||
| d2b3841bbd | |||
| de877fb337 | |||
| d4c2b9060f | |||
| 41ac866729 | |||
| a7afd2a1c7 | |||
| df03daf2cc | |||
| b3f5a4f496 | |||
| d080d661f7 | |||
| 6deb481e5d | |||
| 5b98e18a4e | |||
| 506a0da89c | |||
| c7fdcf0a79 | |||
| f7d38a7ec6 | |||
| 8edc762df9 | |||
| 4459aca933 | |||
| 5b84c58985 | |||
| 4301d91f6c | |||
| 03d28c115e | |||
| 7b15f350cd | |||
| 2b4917b8b1 | |||
| de78ca8d9b | |||
| 58d09e382a | |||
| 0cef12d05b | |||
| 30e73ee795 | |||
| d918b69664 | |||
| 921e558660 | |||
| b3b8d2ab46 | |||
| d62638b8e2 | |||
| 67130a1289 | |||
| 0dabff72bd | |||
| e8e2f195e6 | |||
| fa354016e0 | |||
| 935ee765e9 | |||
| 4c8e59e6fc | |||
| 067f3e6f1a | |||
| 6f09d46dce | |||
| bdef48331b | |||
| 51a6936e51 | |||
| fd456d2952 | |||
| eee1abe593 | |||
| fffad43937 | |||
| 3a79f43a8d | |||
| 2e495f87ab | |||
| 57a9f18f5a | |||
| 02da10e222 | |||
| 0c6a0a9cae | |||
| c80d8d354a | |||
| 3f544dbc69 | |||
| d1e1f15db0 | |||
| 651c314182 | |||
| b957b939cf | |||
| a57545521d | |||
| da60606921 | |||
| 14f9bf7234 | |||
| c1fa92869a | |||
| c8533e3ec8 | |||
| 06c4dd601d | |||
| 4ff80bbab2 | |||
| d7220b1fec | |||
| d92df9ada3 | |||
| 9c19ae322d | |||
| 07893828d8 | |||
| 1167f50543 | |||
| ba1818a903 | |||
| e631219a73 | |||
| 207c6cf2c7 | |||
| c5ece97872 | |||
| 2637924e9c | |||
| 8a2c95d044 | |||
| ba5e3d4efa | |||
| c81623a61a | |||
| 8bb42c2b1b | |||
| bbaa06417d | |||
| 33e161bd59 | |||
| 0233499036 | |||
| a059a29173 | |||
| 83c3398570 | |||
| 93f931459a | |||
| 5a7b19aeb6 | |||
| b901655591 | |||
| a9fdbccb82 | |||
| edcaf72714 | |||
| 80ad7c1798 |
@@ -0,0 +1,36 @@
|
||||
name: Daily security audit
|
||||
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
security_audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/audit-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
notification:
|
||||
if: ${{ failure() }}
|
||||
needs: security_audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Keybase - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Keybase - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nightly
|
||||
NYM_PROJECT_NAME: "Nym daily audit"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
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_NYMBTECH_TEAM }}"
|
||||
KEYBASE_NYM_CHANNEL: "test"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -1,6 +1,7 @@
|
||||
name: CI for Network Explorer
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'explorer/**'
|
||||
@@ -75,3 +76,14 @@ jobs:
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
- name: Deploy
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CD_PROD_NE_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/dist/"
|
||||
REMOTE_HOST: ${{ secrets.CD_PROD_NE_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CD_PROD_NE_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CD_PROD_NE_REMOTE_TARGET }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
@@ -166,8 +166,8 @@ jobs:
|
||||
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-nightly"
|
||||
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMTECH_TEAM }}"
|
||||
KEYBASE_NYM_CHANNEL: "test"
|
||||
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
|
||||
@@ -45,3 +45,4 @@ jobs:
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-validator-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-network-statistics
|
||||
@@ -51,12 +51,12 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
working-directory: nym-wallet/webdriver
|
||||
working-directory: nym-wallet/wallet-ui-tests
|
||||
|
||||
- name: Remove existing user datafile
|
||||
uses: JesseTG/rm@v1.0.2
|
||||
with:
|
||||
path: nym-wallet/webdriver/common/data/user-data.json
|
||||
path: nym-wallet/wallet-ui-tests/common/user-data.json
|
||||
|
||||
- name: Create user data json file
|
||||
id: create-json
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
name: "user-data.json"
|
||||
json: ${{ secrets.WALLET_USERDATA }}
|
||||
dir: "nym-wallet/webdriver/common/data/"
|
||||
dir: "nym-wallet/wallet-ui-tests/common/"
|
||||
|
||||
- name: Install tauri-driver
|
||||
uses: actions-rs/cargo@v1
|
||||
@@ -73,5 +73,5 @@ jobs:
|
||||
args: tauri-driver
|
||||
|
||||
- name: Launch tests
|
||||
run: xvfb-run yarn test:runall
|
||||
working-directory: nym-wallet/webdriver
|
||||
run: xvfb-run yarn test
|
||||
working-directory: nym-wallet/wallet-ui-tests
|
||||
|
||||
+22
-245
@@ -2,16 +2,20 @@
|
||||
|
||||
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## [Unreleased]
|
||||
### Changed
|
||||
|
||||
- validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541])
|
||||
|
||||
[#1541]: https://github.com/nymtech/nym/pull/1541
|
||||
|
||||
|
||||
## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2)
|
||||
|
||||
### Added
|
||||
|
||||
- socks5 client/websocket client: add `--force-register-gateway` flag, useful when rerunning init ([#1353])
|
||||
- nym-connect: initial proof-of-concept of a UI around the socks5 client was added
|
||||
- nym-connect: add ability to select network requester and gateway ([#1427])
|
||||
- nym-connect: add ability to export gateway keys as JSON
|
||||
- nym-connect: add auto updater
|
||||
- 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.
|
||||
- explorer-api: add apy values to `mix_nodes` endpoint
|
||||
@@ -29,6 +33,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- validator-client: add `denom` argument and add simple test for querying an account balance
|
||||
- gateway, validator-api: Checks for coconut credential double spending attempts, taking the coconut bandwidth contract as source of truth ([#1457])
|
||||
- coconut-bandwidth-contract: Record the state of a coconut credential; create specific proposal for releasing funds ([#1457])
|
||||
- inclusion-probability: add simulator for active set inclusion probability
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -39,10 +44,12 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- native & socks5 clients: rerun init will now reuse previous gateway configuration instead of failing ([#1353])
|
||||
- native & socks5 clients: deduplicate big chunks of init logic
|
||||
- validator: fixed local docker-compose setup to work on Apple M1 ([#1329])
|
||||
- explorer-api: listen out for SIGTERM and SIGQUIT too, making it play nicely as a system service ([#1482]).
|
||||
- network-requester: fix filter for suffix-only domains ([#1487])
|
||||
- validator-api: listen out for SIGTERM and SIGQUIT too, making it play nicely as a system service ([#1496]).
|
||||
|
||||
### Changed
|
||||
|
||||
- nym-connect: reuse config id instead of creating a new id on each connection
|
||||
- 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]]
|
||||
- all: updated `rocket` to `0.5.0-rc.2`.
|
||||
@@ -53,6 +60,9 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- validator-api: fee payment for multisig operations comes from the gateway account instead of the validator APIs' accounts ([#1419])
|
||||
- multisig-contract: Limit the proposal creating functionality to one address (coconut-bandwidth-contract address) ([#1457])
|
||||
- All binaries and cosmwasm blobs are configured at runtime now; binaries are configured using environment variables or .env files and contracts keep the configuration parameters in storage ([#1463])
|
||||
- gateway, network-statistics: include gateway id in the sent statistical data ([#1478])
|
||||
- network explorer: tweak how active set probability is shown ([#1503])
|
||||
- validator-api: rewarder set update fails without panicking on possible nymd queries ([#1520])
|
||||
|
||||
|
||||
[#1249]: https://github.com/nymtech/nym/pull/1249
|
||||
@@ -74,78 +84,14 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
[#1393]: https://github.com/nymtech/nym/pull/1393
|
||||
[#1404]: https://github.com/nymtech/nym/pull/1404
|
||||
[#1419]: https://github.com/nymtech/nym/pull/1419
|
||||
[#1427]: https://github.com/nymtech/nym/pull/1427
|
||||
[#1457]: https://github.com/nymtech/nym/pull/1457
|
||||
[#1463]: https://github.com/nymtech/nym/pull/1463
|
||||
|
||||
## [nym-wallet-v1.0.7](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.7) (2022-07-11)
|
||||
|
||||
- wallet: dark mode
|
||||
- wallet: when simulating gas costs, an automatic adjustment is being used ([#1388]).
|
||||
|
||||
[#1388]: https://github.com/nymtech/nym/pull/1388
|
||||
|
||||
## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22)
|
||||
|
||||
### Added
|
||||
|
||||
- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
|
||||
- mixnet-contract: Replace all naked `-` with `saturating_sub`.
|
||||
- mixnet-contract: Added staking_supply field to ContractStateParams.
|
||||
- mixnet-contract: Added a query to get MixnodeBond by identity key ([#1369]).
|
||||
- mixnet-contract: Added a query to get GatewayBond by identity key ([#1369]).
|
||||
- vesting-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
|
||||
- vesting-contract: Added limit to the amount of tokens one can pledge ([#1331])
|
||||
|
||||
### Fixed
|
||||
|
||||
- mixnet-contract: `estimated_delegator_reward` calculation ([#1284])
|
||||
- mixnet-contract: delegator and operator rewards use lambda and sigma instead of lambda_ticked and sigma_ticked ([#1284])
|
||||
- mixnet-contract: removed `expect` in `query_delegator_reward` and queries containing invalid proxy address should now return a more human-readable error ([#1257])
|
||||
- mixnet-contract: replaced integer division with fixed for performance calculations ([#1284])
|
||||
- mixnet-contract: Under certain circumstances nodes could not be unbonded ([#1255](https://github.com/nymtech/nym/issues/1255)) ([#1258])
|
||||
- mixnet-contract: Using correct staking supply when distributing rewards. ([#1373])
|
||||
- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275])
|
||||
|
||||
|
||||
[#1255]: https://github.com/nymtech/nym/pull/1255
|
||||
[#1257]: https://github.com/nymtech/nym/pull/1257
|
||||
[#1258]: https://github.com/nymtech/nym/pull/1258
|
||||
[#1275]: https://github.com/nymtech/nym/pull/1275
|
||||
[#1284]: https://github.com/nymtech/nym/pull/1284
|
||||
[#1292]: https://github.com/nymtech/nym/pull/1292
|
||||
[#1331]: https://github.com/nymtech/nym/pull/1331
|
||||
[#1369]: https://github.com/nymtech/nym/pull/1369
|
||||
[#1373]: https://github.com/nymtech/nym/pull/1373
|
||||
|
||||
## [nym-wallet-v1.0.6](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.6) (2022-06-21)
|
||||
|
||||
- wallet: undelegating now uses either the mixnet or vesting contract, or both, depending on how delegations were made
|
||||
- wallet: redeeming and compounding now uses both the mixnet and vesting contract
|
||||
- wallet: the wallet backend learned how to archive wallet files
|
||||
- wallet: add ENABLE_QA_MODE environment variable to enable QA mode on built wallet
|
||||
|
||||
## [nym-wallet-v1.0.5](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.5) (2022-06-14)
|
||||
|
||||
- wallet: add simple CLI tool for decrypting and recovering the wallet file.
|
||||
- wallet: added support for multiple accounts ([#1265])
|
||||
- wallet: compound and claim reward endpoints for operators and delegators ([#1302])
|
||||
- wallet: require password to switch accounts
|
||||
- wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint.
|
||||
- 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
|
||||
|
||||
[#1265]: https://github.com/nymtech/nym/pull/1265
|
||||
[#1302]: https://github.com/nymtech/nym/pull/1302
|
||||
|
||||
## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04)
|
||||
|
||||
### Changed
|
||||
|
||||
- all: the default behaviour of validator client is changed to use `broadcast_sync` and poll for transaction inclusion instead of using `broadcast_commit` to deal with timeouts ([#1246])
|
||||
[#1478]: https://github.com/nymtech/nym/pull/1478
|
||||
[#1482]: https://github.com/nymtech/nym/pull/1482
|
||||
[#1487]: https://github.com/nymtech/nym/pull/1487
|
||||
[#1496]: https://github.com/nymtech/nym/pull/1496
|
||||
[#1503]: https://github.com/nymtech/nym/pull/1503
|
||||
[#1520]: https://github.com/nymtech/nym/pull/1520
|
||||
|
||||
## [v1.0.1](https://github.com/nymtech/nym/tree/v1.0.1) (2022-05-04)
|
||||
|
||||
@@ -178,77 +124,10 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-wallet-v1.0.3...nym-binaries-1.0.0)
|
||||
|
||||
## [nym-wallet-v1.0.3](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.3) (2022-04-25)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-binaries-1.0.0-rc.2...nym-wallet-v1.0.3)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \[Issue\] Wallet 1.0.2 cannot send NYM tokens from a DelayedVestingAccount [\#1215](https://github.com/nymtech/nym/issues/1215)
|
||||
- Main README not showing properly with GitHub dark mode [\#1211](https://github.com/nymtech/nym/issues/1211)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Bugfix - wallet undelegation for vesting accounts [\#1220](https://github.com/nymtech/nym/pull/1220) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Bugfix/delegation reconcile [\#1219](https://github.com/nymtech/nym/pull/1219) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bugfix/query proxied pending delegations [\#1218](https://github.com/nymtech/nym/pull/1218) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Using custom gas multiplier in the wallet [\#1217](https://github.com/nymtech/nym/pull/1217) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/vesting accounts support [\#1216](https://github.com/nymtech/nym/pull/1216) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Release/1.0.0 rc.2 [\#1214](https://github.com/nymtech/nym/pull/1214) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- chore: fix dark mode rendering [\#1212](https://github.com/nymtech/nym/pull/1212) ([pwnfoo](https://github.com/pwnfoo))
|
||||
- Feature/spend coconut [\#1210](https://github.com/nymtech/nym/pull/1210) ([neacsu](https://github.com/neacsu))
|
||||
- Bugfix/unique sphinx key [\#1207](https://github.com/nymtech/nym/pull/1207) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Add cache read and write timeouts [\#1206](https://github.com/nymtech/nym/pull/1206) ([durch](https://github.com/durch))
|
||||
- Additional, more informative routes [\#1204](https://github.com/nymtech/nym/pull/1204) ([durch](https://github.com/durch))
|
||||
- Feature/aggregated econ dynamics explorer endpoint [\#1203](https://github.com/nymtech/nym/pull/1203) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Debugging validator [\#1198](https://github.com/nymtech/nym/pull/1198) ([durch](https://github.com/durch))
|
||||
- wallet: expose additional validator configuration functionality to the frontend [\#1195](https://github.com/nymtech/nym/pull/1195) ([octol](https://github.com/octol))
|
||||
- Update rewarding validator address [\#1193](https://github.com/nymtech/nym/pull/1193) ([durch](https://github.com/durch))
|
||||
- Crypto part of the Groth's NIDKG [\#1182](https://github.com/nymtech/nym/pull/1182) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- fix unbond page [\#1180](https://github.com/nymtech/nym/pull/1180) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Type safe bounds [\#1179](https://github.com/nymtech/nym/pull/1179) ([durch](https://github.com/durch))
|
||||
- Fix delegation paging [\#1174](https://github.com/nymtech/nym/pull/1174) ([durch](https://github.com/durch))
|
||||
- Update binaries to rc version [\#1172](https://github.com/nymtech/nym/pull/1172) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Bump ansi-regex from 4.1.0 to 4.1.1 in /docker/typescript\_client/upload\_contract [\#1171](https://github.com/nymtech/nym/pull/1171) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
|
||||
## [nym-binaries-1.0.0-rc.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.0-rc.2) (2022-04-15)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-wallet-v1.0.2...nym-binaries-1.0.0-rc.2)
|
||||
|
||||
## [nym-wallet-v1.0.2](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.2) (2022-04-05)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-wallet-v1.0.1...nym-wallet-v1.0.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Wallet 1.0.2 visual tweaks [\#1197](https://github.com/nymtech/nym/pull/1197) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Password for wallet with routes [\#1196](https://github.com/nymtech/nym/pull/1196) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Add auto-updater to Nym Wallet [\#1194](https://github.com/nymtech/nym/pull/1194) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Fix clippy warnings for beta toolchain [\#1191](https://github.com/nymtech/nym/pull/1191) ([octol](https://github.com/octol))
|
||||
- wallet: expose validator urls to the frontend [\#1190](https://github.com/nymtech/nym/pull/1190) ([octol](https://github.com/octol))
|
||||
- wallet: add test for decrypting stored wallet file [\#1189](https://github.com/nymtech/nym/pull/1189) ([octol](https://github.com/octol))
|
||||
- Fix clippy warnings [\#1188](https://github.com/nymtech/nym/pull/1188) ([octol](https://github.com/octol))
|
||||
- Password for wallet with routes [\#1187](https://github.com/nymtech/nym/pull/1187) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- wallet: add validate\_mnemonic [\#1186](https://github.com/nymtech/nym/pull/1186) ([octol](https://github.com/octol))
|
||||
- wallet: support removing accounts from the wallet file [\#1185](https://github.com/nymtech/nym/pull/1185) ([octol](https://github.com/octol))
|
||||
- Feature/adding discord [\#1184](https://github.com/nymtech/nym/pull/1184) ([gala1234](https://github.com/gala1234))
|
||||
- wallet: config backend for validator selection [\#1183](https://github.com/nymtech/nym/pull/1183) ([octol](https://github.com/octol))
|
||||
- Add storybook to wallet [\#1178](https://github.com/nymtech/nym/pull/1178) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- wallet: connection test nymd and api urls independently [\#1170](https://github.com/nymtech/nym/pull/1170) ([octol](https://github.com/octol))
|
||||
- wallet: wire up account storage [\#1153](https://github.com/nymtech/nym/pull/1153) ([octol](https://github.com/octol))
|
||||
- Feature/signature on deposit [\#1151](https://github.com/nymtech/nym/pull/1151) ([neacsu](https://github.com/neacsu))
|
||||
|
||||
## [nym-wallet-v1.0.1](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.1) (2022-04-05)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-binaries-1.0.0-rc.1...nym-wallet-v1.0.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Check enabling bbbc simultaneously with open access. Estimate what it would take to make this the default compilation target. [\#1175](https://github.com/nymtech/nym/issues/1175)
|
||||
- Get coconut credential for deposited tokens [\#1138](https://github.com/nymtech/nym/issues/1138)
|
||||
- Make payments lazy [\#1135](https://github.com/nymtech/nym/issues/1135)
|
||||
- Uptime on node selection for sets [\#1049](https://github.com/nymtech/nym/issues/1049)
|
||||
|
||||
## [nym-binaries-1.0.0-rc.1](https://github.com/nymtech/nym/tree/nym-binaries-1.0.0-rc.1) (2022-03-28)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-wallet-v1.0.0...nym-binaries-1.0.0-rc.1)
|
||||
@@ -327,108 +206,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- feature/pedersen-commitments [\#1048](https://github.com/nymtech/nym/pull/1048) ([danielementary](https://github.com/danielementary))
|
||||
- Feature/reuse init owner [\#970](https://github.com/nymtech/nym/pull/970) ([neacsu](https://github.com/neacsu))
|
||||
|
||||
## [nym-wallet-v1.0.0](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.0) (2022-02-03)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.12.1...nym-wallet-v1.0.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- \[Feature Request\] Please enable registration without need for Telegram account [\#1016](https://github.com/nymtech/nym/issues/1016)
|
||||
- Fast mixnode launch with a pre-built ISO + VM software [\#1001](https://github.com/nymtech/nym/issues/1001)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \[Issue\] [\#1000](https://github.com/nymtech/nym/issues/1000)
|
||||
- \[Issue\] `nym-client` requires multiple attempts to run a server [\#869](https://github.com/nymtech/nym/issues/869)
|
||||
- De-'float'-ing `Interval` \(`Display` impl + `serde`\) [\#1065](https://github.com/nymtech/nym/pull/1065) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- display client address on wallet creation [\#1058](https://github.com/nymtech/nym/pull/1058) ([fmtabbara](https://github.com/fmtabbara))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Rewarded set inclusion probability API endpoint [\#1037](https://github.com/nymtech/nym/issues/1037)
|
||||
- Update cw-storage-plus to 0.11 [\#1032](https://github.com/nymtech/nym/issues/1032)
|
||||
- Change `u128` fields in `RewardEstimationResponse` to `u64` [\#1029](https://github.com/nymtech/nym/issues/1029)
|
||||
- Test out the mainnet Gravity Bridge [\#1006](https://github.com/nymtech/nym/issues/1006)
|
||||
- Add vesting contract interface to nym-wallet [\#959](https://github.com/nymtech/nym/issues/959)
|
||||
- Mixnode crash [\#486](https://github.com/nymtech/nym/issues/486)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- create custom urls for mainnet [\#1095](https://github.com/nymtech/nym/pull/1095) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Wallet signing on MacOS [\#1093](https://github.com/nymtech/nym/pull/1093) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Fix rust 2018 idioms warnings [\#1092](https://github.com/nymtech/nym/pull/1092) ([octol](https://github.com/octol))
|
||||
- Prevent contract overwriting [\#1090](https://github.com/nymtech/nym/pull/1090) ([durch](https://github.com/durch))
|
||||
- Logout operation [\#1087](https://github.com/nymtech/nym/pull/1087) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Update to rust edition 2021 everywhere [\#1086](https://github.com/nymtech/nym/pull/1086) ([octol](https://github.com/octol))
|
||||
- Tag contract errors, and print out lines for easier QA [\#1084](https://github.com/nymtech/nym/pull/1084) ([durch](https://github.com/durch))
|
||||
- Feature/flexible vesting + utility queries [\#1083](https://github.com/nymtech/nym/pull/1083) ([durch](https://github.com/durch))
|
||||
- Bump @openzeppelin/contracts from 4.3.1 to 4.4.2 in /contracts/basic-bandwidth-generation [\#1082](https://github.com/nymtech/nym/pull/1082) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump nth-check from 2.0.0 to 2.0.1 in /clients/native/examples/js-examples/websocket [\#1081](https://github.com/nymtech/nym/pull/1081) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump url-parse from 1.5.1 to 1.5.4 in /clients/native/examples/js-examples/websocket [\#1080](https://github.com/nymtech/nym/pull/1080) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump follow-redirects from 1.14.1 to 1.14.7 in /clients/native/examples/js-examples/websocket [\#1079](https://github.com/nymtech/nym/pull/1079) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump nanoid from 3.1.23 to 3.2.0 in /clients/native/examples/js-examples/websocket [\#1078](https://github.com/nymtech/nym/pull/1078) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Setup basic test for mixnode stats reporting [\#1077](https://github.com/nymtech/nym/pull/1077) ([octol](https://github.com/octol))
|
||||
- Make wallet\_address mandatory for mixnode init [\#1076](https://github.com/nymtech/nym/pull/1076) ([octol](https://github.com/octol))
|
||||
- Tidy nym-mixnode module visibility [\#1075](https://github.com/nymtech/nym/pull/1075) ([octol](https://github.com/octol))
|
||||
- Feature/wallet login with password [\#1074](https://github.com/nymtech/nym/pull/1074) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Add trait to mock client dependency in DelayForwarder [\#1073](https://github.com/nymtech/nym/pull/1073) ([octol](https://github.com/octol))
|
||||
- Bump rust-version to latest stable for nym-mixnode [\#1072](https://github.com/nymtech/nym/pull/1072) ([octol](https://github.com/octol))
|
||||
- Fixes CI for our wasm build [\#1069](https://github.com/nymtech/nym/pull/1069) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Add @octol as codeowner [\#1068](https://github.com/nymtech/nym/pull/1068) ([octol](https://github.com/octol))
|
||||
- set-up inclusion probability [\#1067](https://github.com/nymtech/nym/pull/1067) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Feature/wasm client [\#1066](https://github.com/nymtech/nym/pull/1066) ([neacsu](https://github.com/neacsu))
|
||||
- Changed bech32\_prefix from punk to nymt [\#1064](https://github.com/nymtech/nym/pull/1064) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump nanoid from 3.1.30 to 3.2.0 in /testnet-faucet [\#1063](https://github.com/nymtech/nym/pull/1063) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump nanoid from 3.1.30 to 3.2.0 in /nym-wallet [\#1062](https://github.com/nymtech/nym/pull/1062) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Rework vesting contract storage [\#1061](https://github.com/nymtech/nym/pull/1061) ([durch](https://github.com/durch))
|
||||
- Mixnet Contract constants extraction [\#1060](https://github.com/nymtech/nym/pull/1060) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- fix: make explorer footer year dynamic [\#1059](https://github.com/nymtech/nym/pull/1059) ([martinyung](https://github.com/martinyung))
|
||||
- Add mnemonic just on creation, to display it [\#1057](https://github.com/nymtech/nym/pull/1057) ([neacsu](https://github.com/neacsu))
|
||||
- Network Explorer: updates to API and UI to show the active set [\#1056](https://github.com/nymtech/nym/pull/1056) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Made contract addresses for query NymdClient construction optional [\#1055](https://github.com/nymtech/nym/pull/1055) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Introduced RPC query for total token supply [\#1053](https://github.com/nymtech/nym/pull/1053) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/tokio console [\#1052](https://github.com/nymtech/nym/pull/1052) ([durch](https://github.com/durch))
|
||||
- Implemented beta clippy lint recommendations [\#1051](https://github.com/nymtech/nym/pull/1051) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- add new function to update profit percentage [\#1050](https://github.com/nymtech/nym/pull/1050) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Upgrade Clap and use declarative argument parsing for nym-mixnode [\#1047](https://github.com/nymtech/nym/pull/1047) ([octol](https://github.com/octol))
|
||||
- Feature/additional bond validation [\#1046](https://github.com/nymtech/nym/pull/1046) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Fix clippy on relevant lints [\#1044](https://github.com/nymtech/nym/pull/1044) ([neacsu](https://github.com/neacsu))
|
||||
- Bump shelljs from 0.8.4 to 0.8.5 in /contracts/basic-bandwidth-generation [\#1043](https://github.com/nymtech/nym/pull/1043) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Endpoint for rewarded set inclusion probabilities [\#1042](https://github.com/nymtech/nym/pull/1042) ([durch](https://github.com/durch))
|
||||
- Bump follow-redirects from 1.14.4 to 1.14.7 in /contracts/basic-bandwidth-generation [\#1041](https://github.com/nymtech/nym/pull/1041) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump follow-redirects from 1.14.5 to 1.14.7 in /testnet-faucet [\#1040](https://github.com/nymtech/nym/pull/1040) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/node settings update [\#1036](https://github.com/nymtech/nym/pull/1036) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Migrate to cw-storage-plus 0.11.1 [\#1035](https://github.com/nymtech/nym/pull/1035) ([durch](https://github.com/durch))
|
||||
- Bump @openzeppelin/contracts from 4.4.1 to 4.4.2 in /contracts/basic-bandwidth-generation [\#1034](https://github.com/nymtech/nym/pull/1034) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/configurable wallet [\#1033](https://github.com/nymtech/nym/pull/1033) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/downcast reward estimation [\#1031](https://github.com/nymtech/nym/pull/1031) ([durch](https://github.com/durch))
|
||||
- Wallet UI updates [\#1028](https://github.com/nymtech/nym/pull/1028) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Remove migration code [\#1027](https://github.com/nymtech/nym/pull/1027) ([neacsu](https://github.com/neacsu))
|
||||
- Chore/stricter dependency requirements [\#1025](https://github.com/nymtech/nym/pull/1025) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator api client endpoints [\#1024](https://github.com/nymtech/nym/pull/1024) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Updated cosmrs to 0.4.1 [\#1023](https://github.com/nymtech/nym/pull/1023) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/testnet deploy scripts [\#1022](https://github.com/nymtech/nym/pull/1022) ([mfahampshire](https://github.com/mfahampshire))
|
||||
- Changed wallet's client to a full validator client [\#1021](https://github.com/nymtech/nym/pull/1021) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fix 404 link [\#1020](https://github.com/nymtech/nym/pull/1020) ([RiccardoMasutti](https://github.com/RiccardoMasutti))
|
||||
- Feature/additional mixnode endpoints [\#1019](https://github.com/nymtech/nym/pull/1019) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Introduced denom check when trying to withdraw vested coins [\#1018](https://github.com/nymtech/nym/pull/1018) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Add network defaults for qa [\#1017](https://github.com/nymtech/nym/pull/1017) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/expanded events [\#1015](https://github.com/nymtech/nym/pull/1015) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- update frontend to use new profit update api [\#1014](https://github.com/nymtech/nym/pull/1014) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Feature/node state endpoint [\#1013](https://github.com/nymtech/nym/pull/1013) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/hourly set updates [\#1012](https://github.com/nymtech/nym/pull/1012) ([durch](https://github.com/durch))
|
||||
- Feature/remove unused profit margin [\#1011](https://github.com/nymtech/nym/pull/1011) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/explorer node status [\#1010](https://github.com/nymtech/nym/pull/1010) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Use serial integer instead of random [\#1009](https://github.com/nymtech/nym/pull/1009) ([durch](https://github.com/durch))
|
||||
- Feature/configure profit [\#1008](https://github.com/nymtech/nym/pull/1008) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/fix gateway sign [\#1004](https://github.com/nymtech/nym/pull/1004) ([neacsu](https://github.com/neacsu))
|
||||
- Fix clippy [\#1003](https://github.com/nymtech/nym/pull/1003) ([neacsu](https://github.com/neacsu))
|
||||
- Update wallet version [\#998](https://github.com/nymtech/nym/pull/998) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Fix wallet build instructions [\#997](https://github.com/nymtech/nym/pull/997) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Make the separation between testnet-mode and erc20 bandwidth mode clearer [\#994](https://github.com/nymtech/nym/pull/994) ([neacsu](https://github.com/neacsu))
|
||||
- Bump @openzeppelin/contracts from 3.4.0 to 4.4.1 in /contracts/basic-bandwidth-generation [\#983](https://github.com/nymtech/nym/pull/983) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/implicit runtime [\#973](https://github.com/nymtech/nym/pull/973) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Differentiate staking and ownership [\#961](https://github.com/nymtech/nym/pull/961) ([durch](https://github.com/durch))
|
||||
|
||||
## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23)
|
||||
|
||||
|
||||
Generated
+533
-477
File diff suppressed because it is too large
Load Diff
+9
-7
@@ -22,22 +22,23 @@ members = [
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"common/bandwidth-claim-contract",
|
||||
"common/client-libs/gateway-client",
|
||||
"common/client-libs/mixnet-client",
|
||||
"common/client-libs/validator-client",
|
||||
"common/credential-storage",
|
||||
"common/coconut-interface",
|
||||
"common/config",
|
||||
"common/credentials",
|
||||
"common/crypto",
|
||||
"common/crypto/dkg",
|
||||
"common/execute",
|
||||
"common/bandwidth-claim-contract",
|
||||
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
|
||||
"common/cosmwasm-smart-contracts/contracts-common",
|
||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||
"common/cosmwasm-smart-contracts/multisig-contract",
|
||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||
"common/credential-storage",
|
||||
"common/credentials",
|
||||
"common/crypto",
|
||||
"common/crypto/dkg",
|
||||
"common/execute",
|
||||
"common/inclusion-probability",
|
||||
"common/mixnode-common",
|
||||
"common/network-defaults",
|
||||
"common/nonexhaustive-delayqueue",
|
||||
@@ -53,9 +54,9 @@ members = [
|
||||
"common/nymsphinx/params",
|
||||
"common/nymsphinx/types",
|
||||
"common/pemstore",
|
||||
"common/statistics",
|
||||
"common/socks5/proxy-helpers",
|
||||
"common/socks5/requests",
|
||||
"common/statistics",
|
||||
"common/task",
|
||||
"common/topology",
|
||||
"common/types",
|
||||
@@ -76,6 +77,7 @@ default-members = [
|
||||
"clients/socks5",
|
||||
"gateway",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"mixnode",
|
||||
"validator-api",
|
||||
"explorer-api",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
test: clippy-all cargo-test wasm fmt
|
||||
test-all: test cargo-test-expensive
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use crate::client::config::{Config, SocketType};
|
||||
use clap::{Parser, Subcommand};
|
||||
use url::Url;
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
pub(crate) const DEFAULT_ETH_ENDPOINT: &str =
|
||||
@@ -97,28 +96,17 @@ pub(crate) async fn execute(args: &Cli) {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
if let Some(raw_validators) = args.validators {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(parse_validators(&raw_validators));
|
||||
.set_custom_validator_apis(config::parse_validators(&raw_validators));
|
||||
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
|
||||
let raw_validators = std::env::var(network_defaults::var_names::API_VALIDATOR)
|
||||
.expect("api validator not set");
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(parse_validators(&raw_validators));
|
||||
.set_custom_validator_apis(config::parse_validators(&raw_validators));
|
||||
}
|
||||
|
||||
if args.disable_socket {
|
||||
|
||||
@@ -82,7 +82,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
if binary_version == config_version {
|
||||
true
|
||||
} else {
|
||||
warn!("The mixnode binary has different version than what is specified in config file! {} and {}", binary_version, config_version);
|
||||
warn!("The native-client binary has different version than what is specified in config file! {} and {}", binary_version, config_version);
|
||||
if is_minor_version_compatible(binary_version, config_version) {
|
||||
info!("but they are still semver compatible. However, consider running the `upgrade` command");
|
||||
true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::client::config::Config;
|
||||
use clap::{Parser, Subcommand};
|
||||
use url::Url;
|
||||
use config::parse_validators;
|
||||
|
||||
pub mod init;
|
||||
pub(crate) mod run;
|
||||
@@ -96,17 +96,6 @@ pub(crate) async fn execute(args: &Cli) {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
if let Some(raw_validators) = args.validators {
|
||||
config
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5,7 +5,7 @@ use futures::StreamExt;
|
||||
use log::*;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender};
|
||||
use socks5_requests::Response;
|
||||
use socks5_requests::Message;
|
||||
|
||||
pub(crate) struct MixnetResponseListener {
|
||||
buffer_requester: ReceivedBufferRequestSender,
|
||||
@@ -44,12 +44,16 @@ impl MixnetResponseListener {
|
||||
warn!("this message had a surb - we didn't do anything with it");
|
||||
}
|
||||
|
||||
let response = match Response::try_from_bytes(&raw_message) {
|
||||
let response = match Message::try_from_bytes(&raw_message) {
|
||||
Err(err) => {
|
||||
warn!("failed to parse received response - {:?}", err);
|
||||
return;
|
||||
}
|
||||
Ok(data) => data,
|
||||
Ok(Message::Request(_)) => {
|
||||
warn!("unexpected request");
|
||||
return;
|
||||
}
|
||||
Ok(Message::Response(data)) => data,
|
||||
};
|
||||
|
||||
self.controller_sender
|
||||
|
||||
@@ -893,7 +893,7 @@ impl<C> NymdClient<C> {
|
||||
&self,
|
||||
contract_address: &AccountId,
|
||||
msg: &M,
|
||||
fee: Fee,
|
||||
fee: Option<Fee>,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NymdError>
|
||||
@@ -901,6 +901,7 @@ impl<C> NymdClient<C> {
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
M: ?Sized + Serialize + Sync,
|
||||
{
|
||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
|
||||
self.client
|
||||
.execute(self.address(), contract_address, msg, fee, memo, funds)
|
||||
.await
|
||||
@@ -910,7 +911,7 @@ impl<C> NymdClient<C> {
|
||||
&self,
|
||||
contract_address: &AccountId,
|
||||
msgs: I,
|
||||
fee: Fee,
|
||||
fee: Option<Fee>,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
) -> Result<ExecuteResult, NymdError>
|
||||
where
|
||||
@@ -918,6 +919,7 @@ impl<C> NymdClient<C> {
|
||||
I: IntoIterator<Item = (M, Vec<Coin>)> + Send,
|
||||
M: Serialize,
|
||||
{
|
||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
|
||||
self.client
|
||||
.execute_multiple(self.address(), contract_address, msgs, fee, memo)
|
||||
.await
|
||||
@@ -1006,6 +1008,29 @@ impl<C> NymdClient<C> {
|
||||
.await
|
||||
}
|
||||
|
||||
#[execute("mixnet")]
|
||||
fn _compound_reward(
|
||||
&self,
|
||||
operator: Option<String>,
|
||||
delegator: Option<String>,
|
||||
mix_identity: Option<IdentityKey>,
|
||||
proxy: Option<String>,
|
||||
fee: Option<Fee>,
|
||||
) -> (ExecuteMsg, Option<Fee>)
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
(
|
||||
ExecuteMsg::CompoundReward {
|
||||
operator,
|
||||
delegator,
|
||||
mix_identity,
|
||||
proxy,
|
||||
},
|
||||
fee,
|
||||
)
|
||||
}
|
||||
|
||||
#[execute("mixnet")]
|
||||
fn _compound_operator_reward(&self, fee: Option<Fee>) -> (ExecuteMsg, Option<Fee>)
|
||||
where
|
||||
|
||||
@@ -88,3 +88,14 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
||||
.map_err(|toml_err| io::Error::new(io::ErrorKind::Other, toml_err))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_validators(raw: &str) -> Vec<url::Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ impl SpendCredentialData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
|
||||
pub enum SpendCredentialStatus {
|
||||
InProgress,
|
||||
Spent,
|
||||
|
||||
@@ -33,6 +33,12 @@ pub enum ExecuteMsg {
|
||||
CompoundDelegatorReward {
|
||||
mix_identity: IdentityKey,
|
||||
},
|
||||
CompoundReward {
|
||||
operator: Option<String>,
|
||||
delegator: Option<String>,
|
||||
mix_identity: Option<IdentityKey>,
|
||||
proxy: Option<String>,
|
||||
},
|
||||
BondMixnode {
|
||||
mix_node: MixNode,
|
||||
owner_signature: String,
|
||||
@@ -116,6 +122,7 @@ pub enum ExecuteMsg {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum QueryMsg {
|
||||
GetBlacklistedNodes {},
|
||||
GetCurrentOperatorCost {},
|
||||
GetRewardingValidatorAddress {},
|
||||
GetAllDelegationKeys {},
|
||||
@@ -208,4 +215,29 @@ pub enum QueryMsg {
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct MigrateMsg {}
|
||||
pub struct MigrateMsg {
|
||||
pub mixnet_denom: String,
|
||||
nodes_to_remove: Option<Vec<NodeToRemove>>,
|
||||
}
|
||||
|
||||
impl MigrateMsg {
|
||||
pub fn nodes_to_remove(&self) -> Vec<NodeToRemove> {
|
||||
self.nodes_to_remove.clone().unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
pub struct NodeToRemove {
|
||||
owner: String,
|
||||
proxy: Option<String>,
|
||||
}
|
||||
|
||||
impl NodeToRemove {
|
||||
pub fn owner(&self) -> &str {
|
||||
&self.owner
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> Option<&String> {
|
||||
self.proxy.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ pub struct InitMsg {
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct MigrateMsg {}
|
||||
pub struct MigrateMsg {
|
||||
pub mix_denom: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)]
|
||||
pub struct VestingSpecification {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "inclusion-probability"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
thiserror = "1.0.32"
|
||||
@@ -0,0 +1,9 @@
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("The list of cumulative stake was unexpectedly empty")]
|
||||
EmptyListCumulStake,
|
||||
#[error("Sample point was unexpectedly out of bounds")]
|
||||
SamplePointOutOfBounds,
|
||||
#[error("Norm computation failed on different size arrarys")]
|
||||
NormDifferenceSizeArrays,
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
//! Active set inclusion probability simulator
|
||||
|
||||
use error::Error;
|
||||
|
||||
mod error;
|
||||
|
||||
const TOLERANCE_L2_NORM: f64 = 1e-4;
|
||||
const TOLERANCE_MAX_NORM: f64 = 1e-3;
|
||||
|
||||
pub struct SelectionProbability {
|
||||
pub active_set_probability: Vec<f64>,
|
||||
pub reserve_set_probability: Vec<f64>,
|
||||
pub samples: u32,
|
||||
pub delta_l2: f64,
|
||||
pub delta_max: f64,
|
||||
}
|
||||
|
||||
pub fn simulate_selection_probability_mixnodes(
|
||||
list_stake_for_mixnodes: &[u64],
|
||||
active_set_size: usize,
|
||||
reserve_set_size: usize,
|
||||
max_samples: u32,
|
||||
) -> Result<SelectionProbability, Error> {
|
||||
// Total number of existing (registered) nodes
|
||||
let num_mixnodes = list_stake_for_mixnodes.len();
|
||||
|
||||
// Cumulative stake ordered by node index
|
||||
let list_cumul = cumul_sum(list_stake_for_mixnodes);
|
||||
|
||||
// The computed probabilities
|
||||
let mut active_set_probability = vec![0.0; num_mixnodes];
|
||||
let mut reserve_set_probability = vec![0.0; num_mixnodes];
|
||||
|
||||
// Number sufficiently large to have a good approximation of selection probability
|
||||
let mut samples = 0;
|
||||
let mut delta_l2;
|
||||
let mut delta_max;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
loop {
|
||||
samples += 1;
|
||||
let mut sample_active_mixnodes = Vec::new();
|
||||
let mut sample_reserve_mixnodes = Vec::new();
|
||||
let mut list_cumul_temp = list_cumul.clone();
|
||||
|
||||
let active_set_probability_previous = active_set_probability.clone();
|
||||
|
||||
// Select the active nodes for the epoch (hour)
|
||||
while sample_active_mixnodes.len() < active_set_size {
|
||||
let candidate = sample_candidate(&list_cumul_temp, &mut rng)?;
|
||||
|
||||
if !sample_active_mixnodes.contains(&candidate) {
|
||||
sample_active_mixnodes.push(candidate);
|
||||
remove_mixnode_from_cumul_stake(candidate, &mut list_cumul_temp);
|
||||
}
|
||||
}
|
||||
|
||||
// Select the reserve nodes for the epoch (hour)
|
||||
while sample_reserve_mixnodes.len() < reserve_set_size {
|
||||
let candidate = sample_candidate(&list_cumul_temp, &mut rng)?;
|
||||
|
||||
if !sample_reserve_mixnodes.contains(&candidate)
|
||||
&& !sample_active_mixnodes.contains(&candidate)
|
||||
{
|
||||
sample_reserve_mixnodes.push(candidate);
|
||||
remove_mixnode_from_cumul_stake(candidate, &mut list_cumul_temp);
|
||||
}
|
||||
}
|
||||
|
||||
// Sum up nodes being in active or reserve set
|
||||
for active_mixnodes in sample_active_mixnodes {
|
||||
active_set_probability[active_mixnodes] += 1.0;
|
||||
}
|
||||
for reserve_mixnodes in sample_reserve_mixnodes {
|
||||
reserve_set_probability[reserve_mixnodes] += 1.0;
|
||||
}
|
||||
|
||||
// Convergence critera only on active set.
|
||||
// We devide by samples to get the average, that is not really part of the delta
|
||||
// computation.
|
||||
delta_l2 = l2_diff(&active_set_probability, &active_set_probability_previous)?
|
||||
/ f64::from(samples);
|
||||
delta_max = max_diff(&active_set_probability, &active_set_probability_previous)?
|
||||
/ f64::from(samples);
|
||||
if samples > 10 && delta_l2 < TOLERANCE_L2_NORM && delta_max < TOLERANCE_MAX_NORM
|
||||
|| samples >= max_samples
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
active_set_probability
|
||||
.iter_mut()
|
||||
.for_each(|x| *x /= f64::from(samples));
|
||||
reserve_set_probability
|
||||
.iter_mut()
|
||||
.for_each(|x| *x /= f64::from(samples));
|
||||
|
||||
Ok(SelectionProbability {
|
||||
active_set_probability,
|
||||
reserve_set_probability,
|
||||
samples,
|
||||
delta_l2,
|
||||
delta_max,
|
||||
})
|
||||
}
|
||||
|
||||
// Compute the cumulative sum
|
||||
fn cumul_sum<'a>(list: impl IntoIterator<Item = &'a u64>) -> Vec<u64> {
|
||||
let mut list_cumul = Vec::new();
|
||||
let mut cumul = 0;
|
||||
for entry in list {
|
||||
cumul += entry;
|
||||
list_cumul.push(cumul);
|
||||
}
|
||||
list_cumul
|
||||
}
|
||||
|
||||
fn sample_candidate(list_cumul: &[u64], rng: &mut rand::rngs::ThreadRng) -> Result<usize, Error> {
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
let uniform = Uniform::from(0..*list_cumul.last().ok_or(Error::EmptyListCumulStake)?);
|
||||
let r = uniform.sample(rng);
|
||||
|
||||
let candidate = list_cumul
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, x)| *x >= &r)
|
||||
.ok_or(Error::SamplePointOutOfBounds)?
|
||||
.0;
|
||||
|
||||
Ok(candidate)
|
||||
}
|
||||
|
||||
// Update list of cumulative stake to reflect eliminating the picked node
|
||||
fn remove_mixnode_from_cumul_stake(candidate: usize, list_cumul_stake: &mut [u64]) {
|
||||
let prob_candidate = if candidate == 0 {
|
||||
list_cumul_stake[0]
|
||||
} else {
|
||||
list_cumul_stake[candidate] - list_cumul_stake[candidate - 1]
|
||||
};
|
||||
|
||||
for cumul in list_cumul_stake.iter_mut().skip(candidate) {
|
||||
*cumul -= prob_candidate;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the difference in l2-norm
|
||||
fn l2_diff(v1: &[f64], v2: &[f64]) -> Result<f64, Error> {
|
||||
if v1.len() != v2.len() {
|
||||
return Err(Error::NormDifferenceSizeArrays);
|
||||
}
|
||||
Ok(v1
|
||||
.iter()
|
||||
.zip(v2)
|
||||
.map(|(&i1, &i2)| (i1 - i2).powi(2))
|
||||
.sum::<f64>()
|
||||
.sqrt())
|
||||
}
|
||||
|
||||
// Compute the difference in max-norm
|
||||
fn max_diff(v1: &[f64], v2: &[f64]) -> Result<f64, Error> {
|
||||
if v1.len() != v2.len() {
|
||||
return Err(Error::NormDifferenceSizeArrays);
|
||||
}
|
||||
Ok(v1
|
||||
.iter()
|
||||
.zip(v2)
|
||||
.map(|(x, y)| (x - y).abs())
|
||||
.fold(f64::NEG_INFINITY, f64::max))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn compute_cumul_sum() {
|
||||
let v = cumul_sum(&vec![1, 2, 3]);
|
||||
assert_eq!(v, &[1, 3, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_mixnode_from_cumul() {
|
||||
let mut cumul_stake = vec![1, 2, 3, 4, 5, 6];
|
||||
remove_mixnode_from_cumul_stake(3, &mut cumul_stake);
|
||||
assert_eq!(cumul_stake, &[1, 2, 3, 3, 4, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_norm() {
|
||||
let v1 = vec![1.0, 2.0, 3.0];
|
||||
let v2 = vec![2.0, 4.0, -6.0];
|
||||
assert!((max_diff(&v1, &v2).unwrap() - 9.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ls_norm() {
|
||||
let v1 = vec![1.0, 2.0, 3.0];
|
||||
let v2 = vec![2.0, 3.0, -2.0];
|
||||
assert!((l2_diff(&v1, &v2).unwrap() - 5.196_152_422_706_632).abs() < 1e2 * f64::EPSILON);
|
||||
}
|
||||
|
||||
// Replicate the results from the Python simulation code in https://github.com/nymtech/team-core/issues/114
|
||||
#[test]
|
||||
fn replicate_python_simulation() {
|
||||
let active_set_size = 4;
|
||||
let standby_set_size = 1;
|
||||
|
||||
// this has to contain the total stake per node
|
||||
let list_mix = vec![
|
||||
100, 100, 3000, 500_000, 100, 10, 10, 10, 10, 10, 30000, 500, 200, 52345,
|
||||
];
|
||||
|
||||
let max_samples = 100_000;
|
||||
|
||||
let SelectionProbability {
|
||||
active_set_probability,
|
||||
reserve_set_probability,
|
||||
samples,
|
||||
delta_l2,
|
||||
delta_max,
|
||||
} = simulate_selection_probability_mixnodes(
|
||||
&list_mix,
|
||||
active_set_size,
|
||||
standby_set_size,
|
||||
max_samples,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// These values comes from running the python simulator for a very long time
|
||||
let expected_active_set_probability = vec![
|
||||
0.025_070_8,
|
||||
0.025_073_2,
|
||||
0.744_117,
|
||||
0.999_999,
|
||||
0.025_000_2,
|
||||
0.002_524_4,
|
||||
0.002_527_8,
|
||||
0.002_528_6,
|
||||
0.002_569_6,
|
||||
0.002_513_6,
|
||||
0.994,
|
||||
0.125_482_8,
|
||||
0.050_279_8,
|
||||
0.998_313_2,
|
||||
];
|
||||
// The same check is used in the convergence criterion, and hence should be reflected in
|
||||
// `delta_max` too.
|
||||
assert!(
|
||||
max_diff(&active_set_probability, &expected_active_set_probability).unwrap() < 1e-2
|
||||
);
|
||||
|
||||
let expected_reserve_set_probability = vec![
|
||||
0.076_392_4,
|
||||
0.076_499,
|
||||
0.204_893_6,
|
||||
1e-06,
|
||||
0.076_278_8,
|
||||
0.007_720_6,
|
||||
0.007_673,
|
||||
0.007_700_2,
|
||||
0.007_669_4,
|
||||
0.007_731_2,
|
||||
0.005_789_4,
|
||||
0.368_465_6,
|
||||
0.151_537_2,
|
||||
0.001_648_6,
|
||||
];
|
||||
assert!(
|
||||
max_diff(&reserve_set_probability, &expected_reserve_set_probability).unwrap() < 1e-2
|
||||
);
|
||||
|
||||
// We converge around 20_000, add another 500 for some slack due to random values
|
||||
assert!(samples < 20_500);
|
||||
assert!(delta_l2 < TOLERANCE_L2_NORM);
|
||||
assert!(delta_max < TOLERANCE_MAX_NORM);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ pub(crate) const _ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] =
|
||||
hex_literal::hex!("0000000000000000000000000000000000000000");
|
||||
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
|
||||
|
||||
pub(crate) const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "http://127.0.0.1:8090";
|
||||
pub(crate) const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
|
||||
pub const NYMD_VALIDATOR: &str = "https://rpc.nyx.nodes.guru/";
|
||||
pub const API_VALIDATOR: &str = "https://validator.nymtech.net/api/";
|
||||
pub(crate) fn validators() -> Vec<ValidatorDetails> {
|
||||
|
||||
@@ -34,12 +34,16 @@ pub enum StatsData {
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsGatewayData {
|
||||
pub gateway_id: String,
|
||||
pub inbox_count: u32,
|
||||
}
|
||||
|
||||
impl StatsGatewayData {
|
||||
pub fn new(inbox_count: u32) -> Self {
|
||||
StatsGatewayData { inbox_count }
|
||||
pub fn new(gateway_id: String, inbox_count: u32) -> Self {
|
||||
StatsGatewayData {
|
||||
gateway_id,
|
||||
inbox_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -507,7 +507,7 @@ mod test {
|
||||
|
||||
for (expected, raw_display) in values {
|
||||
let coin = DecCoin {
|
||||
denom: Network::MAINNET.mix_denom().display.into(),
|
||||
denom: Network::MAINNET.mix_denom().display,
|
||||
amount: raw_display.parse().unwrap(),
|
||||
};
|
||||
let base = reg.attempt_convert_to_base_coin(coin).unwrap();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22)
|
||||
|
||||
### Added
|
||||
|
||||
- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
|
||||
- mixnet-contract: Replace all naked `-` with `saturating_sub`.
|
||||
- mixnet-contract: Added staking_supply field to ContractStateParams.
|
||||
- mixnet-contract: Added a query to get MixnodeBond by identity key ([#1369]).
|
||||
- mixnet-contract: Added a query to get GatewayBond by identity key ([#1369]).
|
||||
- vesting-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292])
|
||||
- vesting-contract: Added limit to the amount of tokens one can pledge ([#1331])
|
||||
|
||||
### Fixed
|
||||
|
||||
- mixnet-contract: `estimated_delegator_reward` calculation ([#1284])
|
||||
- mixnet-contract: delegator and operator rewards use lambda and sigma instead of lambda_ticked and sigma_ticked ([#1284])
|
||||
- mixnet-contract: removed `expect` in `query_delegator_reward` and queries containing invalid proxy address should now return a more human-readable error ([#1257])
|
||||
- mixnet-contract: replaced integer division with fixed for performance calculations ([#1284])
|
||||
- mixnet-contract: Under certain circumstances nodes could not be unbonded ([#1255](https://github.com/nymtech/nym/issues/1255)) ([#1258])
|
||||
- mixnet-contract: Using correct staking supply when distributing rewards. ([#1373])
|
||||
- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275])
|
||||
|
||||
|
||||
[#1255]: https://github.com/nymtech/nym/pull/1255
|
||||
[#1257]: https://github.com/nymtech/nym/pull/1257
|
||||
[#1258]: https://github.com/nymtech/nym/pull/1258
|
||||
[#1275]: https://github.com/nymtech/nym/pull/1275
|
||||
[#1284]: https://github.com/nymtech/nym/pull/1284
|
||||
[#1292]: https://github.com/nymtech/nym/pull/1292
|
||||
[#1331]: https://github.com/nymtech/nym/pull/1331
|
||||
[#1369]: https://github.com/nymtech/nym/pull/1369
|
||||
[#1373]: https://github.com/nymtech/nym/pull/1373
|
||||
Generated
+4
-4
@@ -1392,18 +1392,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
|
||||
@@ -27,16 +27,18 @@ use crate::mixnodes::bonding_queries::{
|
||||
query_checkpoints_for_mixnode, query_mixnode_at_height, query_mixnodes_paged,
|
||||
};
|
||||
use crate::mixnodes::layer_queries::query_layer_distribution;
|
||||
use crate::mixnodes::transactions::_try_remove_mixnode;
|
||||
use crate::queued_migrations::migrate_config_from_env;
|
||||
use crate::rewards::queries::{
|
||||
query_circulating_supply, query_reward_pool, query_rewarding_status, query_staking_supply,
|
||||
};
|
||||
use crate::rewards::storage as rewards_storage;
|
||||
use cosmwasm_std::{
|
||||
entry_point, to_binary, Addr, Api, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
|
||||
Uint128,
|
||||
Storage, Uint128,
|
||||
};
|
||||
use mixnet_contract_common::{
|
||||
ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg,
|
||||
ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, NodeToRemove, QueryMsg,
|
||||
};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
@@ -112,6 +114,19 @@ pub fn execute(
|
||||
msg: ExecuteMsg,
|
||||
) -> Result<Response, ContractError> {
|
||||
match msg {
|
||||
ExecuteMsg::CompoundReward {
|
||||
operator,
|
||||
delegator,
|
||||
mix_identity,
|
||||
proxy,
|
||||
} => crate::rewards::transactions::try_compound_reward(
|
||||
deps,
|
||||
env,
|
||||
operator,
|
||||
delegator,
|
||||
mix_identity,
|
||||
proxy,
|
||||
),
|
||||
ExecuteMsg::UpdateRewardingValidatorAddress { address } => {
|
||||
try_update_rewarding_validator_address(deps, info, address)
|
||||
}
|
||||
@@ -127,7 +142,7 @@ pub fn execute(
|
||||
owner_signature,
|
||||
),
|
||||
ExecuteMsg::UnbondMixnode {} => {
|
||||
crate::mixnodes::transactions::try_remove_mixnode(env, deps, info)
|
||||
crate::mixnodes::transactions::try_remove_mixnode(&env, deps.storage, deps.api, info)
|
||||
}
|
||||
ExecuteMsg::UpdateMixnodeConfig {
|
||||
profit_margin_percent,
|
||||
@@ -221,7 +236,13 @@ pub fn execute(
|
||||
owner_signature,
|
||||
),
|
||||
ExecuteMsg::UnbondMixnodeOnBehalf { owner } => {
|
||||
crate::mixnodes::transactions::try_remove_mixnode_on_behalf(env, deps, info, owner)
|
||||
crate::mixnodes::transactions::try_remove_mixnode_on_behalf(
|
||||
&env,
|
||||
deps.storage,
|
||||
deps.api,
|
||||
info,
|
||||
owner,
|
||||
)
|
||||
}
|
||||
ExecuteMsg::BondGatewayOnBehalf {
|
||||
gateway,
|
||||
@@ -280,7 +301,7 @@ pub fn execute(
|
||||
)
|
||||
}
|
||||
ExecuteMsg::ReconcileDelegations {} => {
|
||||
crate::delegations::transactions::try_reconcile_all_delegation_events(deps, info)
|
||||
crate::delegations::transactions::try_reconcile_all_delegation_events(deps)
|
||||
}
|
||||
ExecuteMsg::CheckpointMixnodes {} => {
|
||||
crate::mixnodes::transactions::try_checkpoint_mixnodes(
|
||||
@@ -321,6 +342,9 @@ pub fn execute(
|
||||
#[entry_point]
|
||||
pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result<QueryResponse, ContractError> {
|
||||
let query_res = match msg {
|
||||
QueryMsg::GetBlacklistedNodes {} => to_binary(
|
||||
&crate::mixnodes::bonding_queries::get_blacklisted_nodes(deps),
|
||||
),
|
||||
QueryMsg::GetRewardingValidatorAddress {} => {
|
||||
to_binary(&query_rewarding_validator_address(deps)?)
|
||||
}
|
||||
@@ -448,9 +472,54 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result<QueryResponse, C
|
||||
Ok(query_res?)
|
||||
}
|
||||
|
||||
fn blacklist_malicious_node(storage: &mut dyn Storage, owner: &Addr) -> Result<(), ContractError> {
|
||||
let mixnode_bond = match crate::mixnodes::storage::mixnodes()
|
||||
.idx
|
||||
.owner
|
||||
.item(storage, owner.clone())?
|
||||
{
|
||||
Some(record) => record.1,
|
||||
None => {
|
||||
return Err(ContractError::NoAssociatedMixNodeBond {
|
||||
owner: owner.to_owned(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
crate::mixnodes::storage::MIXNODES_BOND_BLACKLIST.save(storage, mixnode_bond.identity(), &0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Removes nodes we've deemed malicious, returns the pledge to the owners, but does not send any rewards
|
||||
fn remove_malicious_node(
|
||||
storage: &mut dyn Storage,
|
||||
api: &dyn Api,
|
||||
env: &Env,
|
||||
node: &NodeToRemove,
|
||||
) -> Result<Response, ContractError> {
|
||||
let proxy = node.proxy().map(|p| {
|
||||
api.addr_validate(p)
|
||||
.unwrap_or_else(|_| panic!("Invalid address: {}", p))
|
||||
});
|
||||
let owner_addr = api.addr_validate(node.owner())?;
|
||||
blacklist_malicious_node(storage, &owner_addr)?;
|
||||
_try_remove_mixnode(env, storage, api, node.owner(), proxy, false)
|
||||
}
|
||||
|
||||
#[entry_point]
|
||||
pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
Ok(Default::default())
|
||||
pub fn migrate(deps: DepsMut<'_>, env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
migrate_config_from_env(deps.storage, &msg)?;
|
||||
let mut response = Response::new();
|
||||
for node in msg.nodes_to_remove().iter() {
|
||||
let mut sub_response = remove_malicious_node(deps.storage, deps.api, &env, node)
|
||||
.unwrap_or_else(|_| panic!("Could not remove node: {:?}", node));
|
||||
response.messages.append(&mut sub_response.messages);
|
||||
response.attributes.append(&mut sub_response.attributes);
|
||||
response.events.append(&mut sub_response.events);
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -19,16 +19,7 @@ use mixnet_contract_common::{Delegation, IdentityKey};
|
||||
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
use vesting_contract_common::one_ucoin;
|
||||
|
||||
pub fn try_reconcile_all_delegation_events(
|
||||
deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
) -> Result<Response, ContractError> {
|
||||
let state = mixnet_params_storage::CONTRACT_STATE.load(deps.storage)?;
|
||||
// check if this is executed by the permitted validator, if not reject the transaction
|
||||
if info.sender != state.rewarding_validator_address {
|
||||
return Err(ContractError::Unauthorized);
|
||||
}
|
||||
|
||||
pub fn try_reconcile_all_delegation_events(deps: DepsMut<'_>) -> Result<Response, ContractError> {
|
||||
_try_reconcile_all_delegation_events(deps.storage, deps.api)
|
||||
}
|
||||
|
||||
@@ -630,7 +621,14 @@ mod tests {
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation_owner = Addr::unchecked("sender");
|
||||
try_remove_mixnode(mock_env(), deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
let api = deps.api.clone();
|
||||
try_remove_mixnode(
|
||||
&mock_env(),
|
||||
deps.as_mut().storage,
|
||||
&api,
|
||||
mock_info(mixnode_owner, &[]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Err(ContractError::MixNodeBondNotFound {
|
||||
identity: identity.clone()
|
||||
@@ -653,7 +651,14 @@ mod tests {
|
||||
tests::fixtures::good_mixnode_pledge(),
|
||||
deps.as_mut(),
|
||||
);
|
||||
try_remove_mixnode(mock_env(), deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
let api = deps.api.clone();
|
||||
try_remove_mixnode(
|
||||
&mock_env(),
|
||||
deps.as_mut().storage,
|
||||
&api,
|
||||
mock_info(mixnode_owner, &[]),
|
||||
)
|
||||
.unwrap();
|
||||
let identity = test_helpers::add_mixnode(
|
||||
mixnode_owner,
|
||||
tests::fixtures::good_mixnode_pledge(),
|
||||
@@ -917,7 +922,14 @@ mod tests {
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
try_remove_mixnode(mock_env(), deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
let api = deps.api.clone();
|
||||
try_remove_mixnode(
|
||||
&mock_env(),
|
||||
deps.as_mut().storage,
|
||||
&api,
|
||||
mock_info(mixnode_owner, &[]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Err(ContractError::MixNodeBondNotFound {
|
||||
identity: identity.clone()
|
||||
@@ -1058,8 +1070,14 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
_try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
|
||||
|
||||
try_remove_mixnode(mock_env(), deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
let api = deps.api.clone();
|
||||
try_remove_mixnode(
|
||||
&mock_env(),
|
||||
deps.as_mut().storage,
|
||||
&api,
|
||||
mock_info(mixnode_owner, &[]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let expected = Delegation::new(
|
||||
delegation_owner.clone(),
|
||||
@@ -1084,179 +1102,13 @@ mod tests {
|
||||
|
||||
#[cfg(test)]
|
||||
mod removing_mix_stake_delegation {
|
||||
use super::*;
|
||||
use crate::support::tests;
|
||||
use cosmwasm_std::coin;
|
||||
use cosmwasm_std::testing::mock_env;
|
||||
use cosmwasm_std::testing::mock_info;
|
||||
use cosmwasm_std::Addr;
|
||||
|
||||
use crate::support::tests;
|
||||
|
||||
use super::*;
|
||||
|
||||
// TODO: Probably delete due to reconciliation logic
|
||||
//#[ignore]
|
||||
//#[test]
|
||||
//fn fails_if_delegation_never_existed() {
|
||||
// let mut deps = test_helpers::init_contract();
|
||||
// let env = mock_env();
|
||||
// let mixnode_owner = "bob";
|
||||
// let identity = test_helpers::add_mixnode(
|
||||
// mixnode_owner,
|
||||
// tests::fixtures::good_mixnode_pledge(),
|
||||
// deps.as_mut(),
|
||||
// );
|
||||
// let delegation_owner = Addr::unchecked("sender");
|
||||
// assert_eq!(
|
||||
// Err(ContractError::NoMixnodeDelegationFound {
|
||||
// identity: identity.clone(),
|
||||
// address: delegation_owner.to_string(),
|
||||
// }),
|
||||
// try_remove_delegation_from_mixnode(
|
||||
// deps.as_mut(),
|
||||
// env,
|
||||
// mock_info(delegation_owner.as_str(), &[]),
|
||||
// identity,
|
||||
// )
|
||||
// );
|
||||
//}
|
||||
|
||||
// TODO: Update to work with reconciliation
|
||||
//#[ignore]
|
||||
//#[test]
|
||||
//fn succeeds_if_delegation_existed() {
|
||||
// let mut deps = test_helpers::init_contract();
|
||||
// let mixnode_owner = "bob";
|
||||
// let env = mock_env();
|
||||
// let identity = test_helpers::add_mixnode(
|
||||
// mixnode_owner,
|
||||
// tests::fixtures::good_mixnode_pledge(),
|
||||
// deps.as_mut(),
|
||||
// );
|
||||
// let delegation_owner = Addr::unchecked("sender");
|
||||
// try_delegate_to_mixnode(
|
||||
// deps.as_mut(),
|
||||
// mock_env(),
|
||||
// mock_info(delegation_owner.as_str(), &coins(100, TEST_COIN_DENOM)),
|
||||
// identity.clone(),
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
// _try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
|
||||
|
||||
// let _delegation = query_mixnode_delegation(
|
||||
// &deps.storage,
|
||||
// &deps.api,
|
||||
// identity.clone(),
|
||||
// delegation_owner.clone().into_string(),
|
||||
// None,
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
// let expected_response = Response::new()
|
||||
// .add_message(BankMsg::Send {
|
||||
// to_address: delegation_owner.clone().into(),
|
||||
// amount: coins(100, TEST_COIN_DENOM),
|
||||
// })
|
||||
// .add_event(new_undelegation_event(
|
||||
// &delegation_owner,
|
||||
// &None,
|
||||
// &identity,
|
||||
// Uint128::new(100),
|
||||
// ));
|
||||
|
||||
// assert_eq!(
|
||||
// Ok(expected_response),
|
||||
// try_remove_delegation_from_mixnode(
|
||||
// deps.as_mut(),
|
||||
// env,
|
||||
// mock_info(delegation_owner.as_str(), &[]),
|
||||
// identity.clone(),
|
||||
// )
|
||||
// );
|
||||
// assert!(storage::delegations()
|
||||
// .may_load(
|
||||
// &deps.storage,
|
||||
// (identity.clone(), delegation_owner.as_bytes().to_vec(), 0),
|
||||
// )
|
||||
// .unwrap()
|
||||
// .is_none());
|
||||
|
||||
// // and total delegation is cleared
|
||||
// assert_eq!(
|
||||
// Uint128::zero(),
|
||||
// mixnodes_storage::TOTAL_DELEGATION
|
||||
// .load(&deps.storage, &identity)
|
||||
// .unwrap()
|
||||
// )
|
||||
//}
|
||||
|
||||
// TODO: Update to work with reconciliation
|
||||
//#[ignore]
|
||||
//#[test]
|
||||
//fn succeeds_if_delegation_existed_even_if_node_unbonded() {
|
||||
// let mut deps = test_helpers::init_contract();
|
||||
// let mixnode_owner = "bob";
|
||||
// let env = mock_env();
|
||||
// let identity = test_helpers::add_mixnode(
|
||||
// mixnode_owner,
|
||||
// tests::fixtures::good_mixnode_pledge(),
|
||||
// deps.as_mut(),
|
||||
// );
|
||||
// let delegation_owner = Addr::unchecked("sender");
|
||||
// try_delegate_to_mixnode(
|
||||
// deps.as_mut(),
|
||||
// mock_env(),
|
||||
// mock_info(delegation_owner.as_str(), &coins(100, TEST_COIN_DENOM)),
|
||||
// identity.clone(),
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
// _try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
|
||||
|
||||
// let _delegation = query_mixnode_delegation(
|
||||
// &deps.storage,
|
||||
// &deps.api,
|
||||
// identity.clone(),
|
||||
// delegation_owner.clone().into_string(),
|
||||
// None,
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
// let expected_response = Response::new()
|
||||
// .add_message(BankMsg::Send {
|
||||
// to_address: delegation_owner.clone().into(),
|
||||
// amount: coins(100, TEST_COIN_DENOM),
|
||||
// })
|
||||
// .add_event(new_undelegation_event(
|
||||
// &delegation_owner,
|
||||
// &None,
|
||||
// &identity,
|
||||
// Uint128::new(100),
|
||||
// ));
|
||||
|
||||
// try_remove_mixnode(mock_env(), deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
|
||||
|
||||
// assert_eq!(
|
||||
// Ok(expected_response),
|
||||
// try_remove_delegation_from_mixnode(
|
||||
// deps.as_mut(),
|
||||
// env,
|
||||
// mock_info(delegation_owner.as_str(), &[]),
|
||||
// identity.clone(),
|
||||
// )
|
||||
// );
|
||||
|
||||
// _try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
|
||||
|
||||
// assert!(test_helpers::read_delegation(
|
||||
// &deps.storage,
|
||||
// identity,
|
||||
// delegation_owner.as_bytes(),
|
||||
// mock_env().block.height
|
||||
// )
|
||||
// .is_none());
|
||||
//}
|
||||
|
||||
#[test]
|
||||
fn total_delegation_is_preserved_if_only_some_undelegate() {
|
||||
let mut deps = test_helpers::init_contract();
|
||||
|
||||
@@ -178,4 +178,11 @@ pub enum ContractError {
|
||||
last_update_time: u64,
|
||||
current_block_time: u64,
|
||||
},
|
||||
#[error("`mix_identity` is required when `delegator` is set")]
|
||||
MissingMixIdentity,
|
||||
#[error("Compounding has been disabled temporarily")]
|
||||
CompoundDisabled,
|
||||
|
||||
#[error("Mixnode {identity} has been blacklisted on the network")]
|
||||
MixnodeBlacklisted { identity: String },
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@ mod gateways;
|
||||
mod interval;
|
||||
mod mixnet_contract_settings;
|
||||
mod mixnodes;
|
||||
mod queued_migrations;
|
||||
mod rewards;
|
||||
mod support;
|
||||
|
||||
@@ -8,6 +8,13 @@ use mixnet_contract_common::{
|
||||
IdentityKey, MixNodeBond, MixOwnershipResponse, MixnodeBondResponse, PagedMixnodeResponse,
|
||||
};
|
||||
|
||||
pub fn get_blacklisted_nodes(deps: Deps<'_>) -> Vec<IdentityKey> {
|
||||
storage::MIXNODES_BOND_BLACKLIST
|
||||
.keys(deps.storage, None, None, Order::Ascending)
|
||||
.filter_map(|i| i.ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn query_mixnode_at_height(
|
||||
deps: Deps<'_>,
|
||||
mix_identity: String,
|
||||
@@ -252,10 +259,13 @@ pub(crate) mod tests {
|
||||
let res = query_owns_mixnode(deps.as_ref(), "fred".to_string()).unwrap();
|
||||
assert!(res.mixnode.is_some());
|
||||
|
||||
let api = deps.api.clone();
|
||||
|
||||
// but after unbonding it, he doesn't own one anymore
|
||||
crate::mixnodes::transactions::try_remove_mixnode(
|
||||
env,
|
||||
deps.as_mut(),
|
||||
&env,
|
||||
deps.as_mut().storage,
|
||||
&api,
|
||||
mock_info("fred", &[]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -19,6 +19,7 @@ const MIXNODES_PK_CHECKPOINTS: &str = "mn__check";
|
||||
const MIXNODES_PK_CHANGELOG: &str = "mn__change";
|
||||
const MIXNODES_OWNER_IDX_NAMESPACE: &str = "mno";
|
||||
const MIXNODES_SPHINX_IDX_NAMESPACE: &str = "mns";
|
||||
const MIXNODES_BOND_BLACKLIST_NAMESPACE: &str = "mbb";
|
||||
|
||||
const LAST_PM_UPDATE_NAMESPACE: &str = "lpm";
|
||||
|
||||
@@ -32,6 +33,9 @@ pub(crate) const TOTAL_DELEGATION: Map<'_, IdentityKeyRef<'_>, Uint128> =
|
||||
pub(crate) const LAST_PM_UPDATE_TIME: Map<'_, IdentityKeyRef<'_>, u64> =
|
||||
Map::new(LAST_PM_UPDATE_NAMESPACE);
|
||||
|
||||
pub(crate) const MIXNODES_BOND_BLACKLIST: Map<'_, IdentityKeyRef<'_>, u8> =
|
||||
Map::new(MIXNODES_BOND_BLACKLIST_NAMESPACE);
|
||||
|
||||
pub(crate) struct MixnodeBondIndex<'a> {
|
||||
pub(crate) owner: UniqueIndex<'a, Addr, StoredMixnodeBond>,
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ use crate::mixnodes::layer_queries::query_layer_distribution;
|
||||
use crate::mixnodes::storage::StoredMixnodeBond;
|
||||
use crate::support::helpers::{ensure_no_existing_bond, validate_node_identity_signature};
|
||||
use cosmwasm_std::{
|
||||
wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Storage, Uint128,
|
||||
wasm_execute, Addr, Api, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Storage, Uint128,
|
||||
};
|
||||
use mixnet_contract_common::events::{
|
||||
new_checkpoint_mixnodes_event, new_mixnode_bonding_event, new_mixnode_unbonding_event,
|
||||
};
|
||||
use mixnet_contract_common::MixNode;
|
||||
use mixnet_contract_common::{IdentityKeyRef, MixNode};
|
||||
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
use vesting_contract_common::one_ucoin;
|
||||
|
||||
@@ -87,6 +87,15 @@ pub fn try_add_mixnode_on_behalf(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_blacklisted(
|
||||
storage: &dyn Storage,
|
||||
identity: IdentityKeyRef,
|
||||
) -> Result<bool, ContractError> {
|
||||
Ok(storage::MIXNODES_BOND_BLACKLIST
|
||||
.may_load(storage, identity)?
|
||||
.is_some())
|
||||
}
|
||||
|
||||
fn _try_add_mixnode(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
@@ -100,6 +109,12 @@ fn _try_add_mixnode(
|
||||
// if the client has an active bonded mixnode or gateway, don't allow bonding
|
||||
ensure_no_existing_bond(deps.storage, &owner)?;
|
||||
|
||||
if is_blacklisted(deps.storage, &mix_node.identity_key)? {
|
||||
return Err(ContractError::MixnodeBlacklisted {
|
||||
identity: mix_node.identity_key,
|
||||
});
|
||||
};
|
||||
|
||||
// We don't have to check lower bound as its an u8
|
||||
if mix_node.profit_margin_percent > 100 {
|
||||
return Err(ContractError::InvalidProfitMarginPercent(
|
||||
@@ -167,45 +182,47 @@ fn _try_add_mixnode(
|
||||
}
|
||||
|
||||
pub fn try_remove_mixnode_on_behalf(
|
||||
env: Env,
|
||||
deps: DepsMut<'_>,
|
||||
env: &Env,
|
||||
storage: &mut dyn Storage,
|
||||
api: &dyn Api,
|
||||
info: MessageInfo,
|
||||
owner: String,
|
||||
) -> Result<Response, ContractError> {
|
||||
let proxy = info.sender;
|
||||
_try_remove_mixnode(env, deps, &owner, Some(proxy))
|
||||
_try_remove_mixnode(env, storage, api, &owner, Some(proxy), true)
|
||||
}
|
||||
|
||||
pub fn try_remove_mixnode(
|
||||
env: Env,
|
||||
deps: DepsMut<'_>,
|
||||
env: &Env,
|
||||
storage: &mut dyn Storage,
|
||||
api: &dyn Api,
|
||||
info: MessageInfo,
|
||||
) -> Result<Response, ContractError> {
|
||||
_try_remove_mixnode(env, deps, info.sender.as_ref(), None)
|
||||
_try_remove_mixnode(env, storage, api, info.sender.as_ref(), None, true)
|
||||
}
|
||||
|
||||
pub(crate) fn _try_remove_mixnode(
|
||||
env: Env,
|
||||
deps: DepsMut<'_>,
|
||||
env: &Env,
|
||||
storage: &mut dyn Storage,
|
||||
api: &dyn Api,
|
||||
owner: &str,
|
||||
proxy: Option<Addr>,
|
||||
collect_rewards: bool,
|
||||
) -> Result<Response, ContractError> {
|
||||
let owner = deps.api.addr_validate(owner)?;
|
||||
let owner = api.addr_validate(owner)?;
|
||||
|
||||
crate::rewards::transactions::_try_compound_operator_reward(
|
||||
deps.storage,
|
||||
deps.api,
|
||||
env.block.height,
|
||||
&owner,
|
||||
None,
|
||||
)?;
|
||||
if collect_rewards {
|
||||
crate::rewards::transactions::_try_compound_operator_reward(
|
||||
storage,
|
||||
api,
|
||||
env.block.height,
|
||||
&owner,
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
|
||||
// try to find the node of the sender
|
||||
let mixnode_bond = match storage::mixnodes()
|
||||
.idx
|
||||
.owner
|
||||
.item(deps.storage, owner.clone())?
|
||||
{
|
||||
let mixnode_bond = match storage::mixnodes().idx.owner.item(storage, owner.clone())? {
|
||||
Some(record) => record.1,
|
||||
None => return Err(ContractError::NoAssociatedMixNodeBond { owner }),
|
||||
};
|
||||
@@ -225,10 +242,10 @@ pub(crate) fn _try_remove_mixnode(
|
||||
};
|
||||
|
||||
// remove the bond
|
||||
storage::mixnodes().remove(deps.storage, mixnode_bond.identity(), env.block.height)?;
|
||||
storage::mixnodes().remove(storage, mixnode_bond.identity(), env.block.height)?;
|
||||
|
||||
// decrement layer count
|
||||
mixnet_params_storage::decrement_layer_count(deps.storage, mixnode_bond.layer)?;
|
||||
mixnet_params_storage::decrement_layer_count(storage, mixnode_bond.layer)?;
|
||||
|
||||
let mut response = Response::new();
|
||||
|
||||
@@ -238,8 +255,7 @@ pub(crate) fn _try_remove_mixnode(
|
||||
amount: mixnode_bond.pledge_amount(),
|
||||
};
|
||||
|
||||
let track_unbond_message =
|
||||
wasm_execute(proxy, &msg, vec![one_ucoin(mix_denom(deps.storage)?)])?;
|
||||
let track_unbond_message = wasm_execute(proxy, &msg, vec![one_ucoin(mix_denom(storage)?)])?;
|
||||
response = response.add_message(track_unbond_message);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{Addr, Response, Storage};
|
||||
use cw_storage_plus::Item;
|
||||
use mixnet_contract_common::{ContractStateParams, MigrateMsg};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnet_contract_settings::models::ContractState;
|
||||
use crate::mixnet_contract_settings::storage::CONTRACT_STATE;
|
||||
|
||||
pub fn migrate_config_from_env(
|
||||
storage: &mut dyn Storage,
|
||||
msg: &MigrateMsg,
|
||||
) -> Result<Response, ContractError> {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
pub struct OldContractState {
|
||||
pub owner: Addr,
|
||||
pub rewarding_validator_address: Addr,
|
||||
pub params: ContractStateParams,
|
||||
}
|
||||
const OLD_CONTRACT_STATE: Item<'_, OldContractState> = Item::new("config");
|
||||
|
||||
let old_state = OLD_CONTRACT_STATE.load(storage)?;
|
||||
let new_state = ContractState {
|
||||
owner: old_state.owner,
|
||||
mix_denom: msg.mixnet_denom.clone(),
|
||||
rewarding_validator_address: old_state.rewarding_validator_address,
|
||||
params: old_state.params,
|
||||
};
|
||||
|
||||
CONTRACT_STATE.save(storage, &new_state)?;
|
||||
|
||||
Ok(Default::default())
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use crate::error::ContractError;
|
||||
use crate::mixnet_contract_settings::storage::mix_denom;
|
||||
use crate::mixnodes::storage::mixnodes;
|
||||
use crate::mixnodes::storage::{self as mixnodes_storage, StoredMixnodeBond};
|
||||
use crate::mixnodes::transactions::is_blacklisted;
|
||||
use crate::rewards::helpers;
|
||||
use crate::support::helpers::{is_authorized, operator_cost_at_epoch};
|
||||
use cosmwasm_std::{
|
||||
@@ -372,6 +373,56 @@ pub fn try_compound_delegator_reward_on_behalf(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn try_compound_reward(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
operator: Option<String>,
|
||||
delegator: Option<String>,
|
||||
mix_identity: Option<IdentityKey>,
|
||||
proxy: Option<String>,
|
||||
) -> Result<Response, ContractError> {
|
||||
let proxy = proxy.and_then(|p| deps.api.addr_validate(&p).ok());
|
||||
if let Some(operator_address) = operator {
|
||||
let operator_address = deps.api.addr_validate(&operator_address)?;
|
||||
let reward = _try_compound_operator_reward(
|
||||
deps.storage,
|
||||
deps.api,
|
||||
env.block.height,
|
||||
&operator_address,
|
||||
proxy,
|
||||
)?;
|
||||
Ok(
|
||||
Response::default().add_event(new_compound_operator_reward_event(
|
||||
&operator_address,
|
||||
reward,
|
||||
)),
|
||||
)
|
||||
} else if let Some(delegator_address) = delegator {
|
||||
if mix_identity.is_none() {
|
||||
return Err(ContractError::MissingMixIdentity);
|
||||
}
|
||||
|
||||
let delegator_address = deps.api.addr_validate(&delegator_address)?;
|
||||
let reward = _try_compound_delegator_reward(
|
||||
env.block.height,
|
||||
deps,
|
||||
delegator_address.as_str(),
|
||||
mix_identity.as_ref().unwrap(),
|
||||
proxy,
|
||||
)?;
|
||||
Ok(
|
||||
Response::default().add_event(new_compound_delegator_reward_event(
|
||||
&delegator_address,
|
||||
&None,
|
||||
reward,
|
||||
&mix_identity.unwrap(),
|
||||
)),
|
||||
)
|
||||
} else {
|
||||
Ok(Response::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_compound_delegator_reward(
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
@@ -412,7 +463,7 @@ pub fn _try_compound_delegator_reward(
|
||||
proxy.as_ref(),
|
||||
);
|
||||
let reward = calculate_delegator_reward(deps.storage, deps.api, key.clone(), mix_identity)?;
|
||||
let mut compounded_delegation = reward;
|
||||
let mut total_delegation_delegate = Uint128::zero();
|
||||
|
||||
// Might want to introduce paging here
|
||||
let delegation_heights = delegation_map
|
||||
@@ -424,7 +475,7 @@ pub fn _try_compound_delegator_reward(
|
||||
for h in delegation_heights {
|
||||
let delegation =
|
||||
delegation_map.load(deps.storage, (mix_identity.to_string(), key.clone(), h))?;
|
||||
compounded_delegation += delegation.amount.amount;
|
||||
total_delegation_delegate += delegation.amount.amount;
|
||||
delegation_map.replace(
|
||||
deps.storage,
|
||||
(mix_identity.to_string(), key.clone(), h),
|
||||
@@ -433,7 +484,22 @@ pub fn _try_compound_delegator_reward(
|
||||
)?;
|
||||
}
|
||||
|
||||
let compounded_delegation = total_delegation_delegate + reward;
|
||||
|
||||
if compounded_delegation != Uint128::zero() {
|
||||
mixnodes_storage::TOTAL_DELEGATION.update::<_, ContractError>(
|
||||
deps.storage,
|
||||
mix_identity,
|
||||
|total_delegation| {
|
||||
// since we know that the target node exists and because the total_delegation bucket
|
||||
// entry is created whenever the node itself is added, the unwrap here is fine
|
||||
// as the entry MUST exist
|
||||
Ok(total_delegation
|
||||
.unwrap()
|
||||
.saturating_sub(total_delegation_delegate))
|
||||
},
|
||||
)?;
|
||||
|
||||
_try_delegate_to_mixnode(
|
||||
deps.branch(),
|
||||
block_height,
|
||||
@@ -472,6 +538,10 @@ pub fn calculate_delegator_reward(
|
||||
key: Vec<u8>,
|
||||
mix_identity: &str,
|
||||
) -> Result<Uint128, ContractError> {
|
||||
if is_blacklisted(storage, mix_identity)? {
|
||||
return Ok(Uint128::zero());
|
||||
};
|
||||
|
||||
let last_claimed_height = storage::DELEGATOR_REWARD_CLAIMED_HEIGHT
|
||||
.load(storage, (key.clone(), mix_identity.to_string()))
|
||||
.unwrap_or(0);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::errors::ContractError;
|
||||
use crate::queued_migrations::migrate_config_from_env;
|
||||
use crate::storage::{
|
||||
account_from_address, locked_pledge_cap, update_locked_pledge_cap, ADMIN,
|
||||
MIXNET_CONTRACT_ADDRESS, MIX_DENOM,
|
||||
@@ -41,6 +42,7 @@ pub fn instantiate(
|
||||
|
||||
#[entry_point]
|
||||
pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
migrate_config_from_env(_deps, _env, _msg)?;
|
||||
Ok(Response::default())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod contract;
|
||||
mod errors;
|
||||
mod queued_migrations;
|
||||
mod storage;
|
||||
mod support;
|
||||
mod traits;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{DepsMut, Env, Response};
|
||||
use vesting_contract_common::MigrateMsg;
|
||||
|
||||
use crate::{errors::ContractError, storage::MIX_DENOM};
|
||||
|
||||
pub fn migrate_config_from_env(
|
||||
deps: DepsMut<'_>,
|
||||
_env: Env,
|
||||
msg: MigrateMsg,
|
||||
) -> Result<Response, ContractError> {
|
||||
MIX_DENOM.save(deps.storage, &msg.mix_denom)?;
|
||||
|
||||
Ok(Default::default())
|
||||
}
|
||||
@@ -101,10 +101,9 @@ impl Account {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the index of the next vesting period. Unless the current time is somehow in the past or vesting has not started yet.
|
||||
/// In case vesting is over it will always return NUM_VESTING_PERIODS.
|
||||
pub fn get_current_vesting_period(&self, block_time: Timestamp) -> Period {
|
||||
// Returns the index of the next vesting period. Unless the current time is somehow in the past or vesting has not started yet.
|
||||
// In case vesting is over it will always return NUM_VESTING_PERIODS.
|
||||
|
||||
if block_time.seconds() < self.periods.first().unwrap().start_time {
|
||||
Period::Before
|
||||
} else if self.periods.last().unwrap().end_time() < block_time {
|
||||
|
||||
+1
-1
@@ -15,6 +15,6 @@ BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
|
||||
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
|
||||
MULTISIG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
|
||||
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
|
||||
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://127.0.0.1:8090"
|
||||
STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090"
|
||||
NYMD_VALIDATOR="https://rpc.nyx.nodes.guru/"
|
||||
API_VALIDATOR="https://validator.nymtech.net/api/"
|
||||
|
||||
@@ -26,4 +26,5 @@ tokio = {version = "1.19.1", features = ["full"] }
|
||||
|
||||
mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
network-defaults = { path = "../common/network-defaults" }
|
||||
task = { path = "../common/task" }
|
||||
validator-client = { path = "../common/client-libs/validator-client", features=["nymd-client"] }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use log::info;
|
||||
use task::ShutdownListener;
|
||||
|
||||
use crate::country_statistics::country_nodes_distribution::CountryNodesDistribution;
|
||||
use crate::COUNTRY_DATA_REFRESH_INTERVAL;
|
||||
@@ -7,11 +8,12 @@ use crate::state::ExplorerApiStateContext;
|
||||
|
||||
pub(crate) struct CountryStatisticsDistributionTask {
|
||||
state: ExplorerApiStateContext,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl CountryStatisticsDistributionTask {
|
||||
pub(crate) fn new(state: ExplorerApiStateContext) -> Self {
|
||||
CountryStatisticsDistributionTask { state }
|
||||
pub(crate) fn new(state: ExplorerApiStateContext, shutdown: ShutdownListener) -> Self {
|
||||
CountryStatisticsDistributionTask { state, shutdown }
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self) {
|
||||
@@ -20,10 +22,15 @@ impl CountryStatisticsDistributionTask {
|
||||
let mut interval_timer = tokio::time::interval(std::time::Duration::from_secs(
|
||||
COUNTRY_DATA_REFRESH_INTERVAL,
|
||||
));
|
||||
loop {
|
||||
// wait for the next interval tick
|
||||
interval_timer.tick().await;
|
||||
self.calculate_nodes_per_country().await;
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = interval_timer.tick() => {
|
||||
self.calculate_nodes_per_country().await;
|
||||
}
|
||||
_ = self.shutdown.recv() => {
|
||||
trace!("Listener: Received shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,15 +5,17 @@ use crate::mix_nodes::location::{GeoLocation, Location};
|
||||
use crate::state::ExplorerApiStateContext;
|
||||
use log::{info, warn};
|
||||
use reqwest::Error as ReqwestError;
|
||||
use task::ShutdownListener;
|
||||
use thiserror::Error;
|
||||
|
||||
pub(crate) struct GeoLocateTask {
|
||||
state: ExplorerApiStateContext,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl GeoLocateTask {
|
||||
pub(crate) fn new(state: ExplorerApiStateContext) -> Self {
|
||||
GeoLocateTask { state }
|
||||
pub(crate) fn new(state: ExplorerApiStateContext, shutdown: ShutdownListener) -> Self {
|
||||
GeoLocateTask { state, shutdown }
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self) {
|
||||
@@ -27,10 +29,15 @@ impl GeoLocateTask {
|
||||
info!("Spawning mix node locator task runner...");
|
||||
tokio::spawn(async move {
|
||||
let mut interval_timer = tokio::time::interval(std::time::Duration::from_millis(50));
|
||||
loop {
|
||||
// wait for the next interval tick
|
||||
interval_timer.tick().await;
|
||||
self.locate_mix_nodes().await;
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = interval_timer.tick() => {
|
||||
self.locate_mix_nodes().await;
|
||||
}
|
||||
_ = self.shutdown.recv() => {
|
||||
trace!("Listener: Received shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+47
-12
@@ -6,6 +6,7 @@ extern crate rocket_okapi;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use network_defaults::setup_env;
|
||||
use task::ShutdownNotifier;
|
||||
|
||||
pub(crate) mod cache;
|
||||
mod client;
|
||||
@@ -50,29 +51,63 @@ impl ExplorerApi {
|
||||
let validator_api_url = self.state.inner.validator_client.api_endpoint();
|
||||
info!("Using validator API - {}", validator_api_url);
|
||||
|
||||
let shutdown = ShutdownNotifier::default();
|
||||
|
||||
// spawn concurrent tasks
|
||||
crate::tasks::ExplorerApiTasks::new(self.state.clone()).start();
|
||||
crate::tasks::ExplorerApiTasks::new(self.state.clone(), shutdown.subscribe()).start();
|
||||
country_statistics::distribution::CountryStatisticsDistributionTask::new(
|
||||
self.state.clone(),
|
||||
shutdown.subscribe(),
|
||||
)
|
||||
.start();
|
||||
country_statistics::geolocate::GeoLocateTask::new(self.state.clone()).start();
|
||||
country_statistics::geolocate::GeoLocateTask::new(self.state.clone(), shutdown.subscribe())
|
||||
.start();
|
||||
|
||||
// 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 explorer-api exits.
|
||||
http::start(self.state.clone());
|
||||
|
||||
// wait for user to press ctrl+C
|
||||
self.wait_for_interrupt().await
|
||||
self.wait_for_interrupt(shutdown).await
|
||||
}
|
||||
|
||||
async fn wait_for_interrupt(&self) {
|
||||
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||
error!(
|
||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||
e
|
||||
);
|
||||
async fn wait_for_interrupt(&self, mut shutdown: ShutdownNotifier) {
|
||||
wait_for_signal().await;
|
||||
|
||||
log::info!("Sending shutdown");
|
||||
shutdown.signal_shutdown().ok();
|
||||
log::info!("Waiting for tasks to finish... (Press ctrl-c to force)");
|
||||
shutdown.wait_for_shutdown().await;
|
||||
log::info!("Stopping explorer API");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
async fn wait_for_signal() {
|
||||
use tokio::signal::unix::{signal, SignalKind};
|
||||
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel");
|
||||
let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel");
|
||||
|
||||
tokio::select! {
|
||||
_ = tokio::signal::ctrl_c() => {
|
||||
log::info!("Received SIGINT");
|
||||
},
|
||||
_ = sigterm.recv() => {
|
||||
log::info!("Received SIGTERM");
|
||||
}
|
||||
info!(
|
||||
"Received SIGINT - the mixnode will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)."
|
||||
);
|
||||
_ = sigquit.recv() => {
|
||||
log::info!("Received SIGQUIT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
async fn wait_for_signal() {
|
||||
tokio::select! {
|
||||
_ = tokio::signal::ctrl_c() => {
|
||||
log::info!("Received SIGINT");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
-15
@@ -4,6 +4,7 @@
|
||||
use std::future::Future;
|
||||
|
||||
use mixnet_contract_common::GatewayBond;
|
||||
use task::ShutdownListener;
|
||||
use validator_client::models::MixNodeBondAnnotated;
|
||||
use validator_client::nymd::error::NymdError;
|
||||
use validator_client::nymd::{Paging, QueryNymdClient, ValidatorResponse};
|
||||
@@ -14,11 +15,12 @@ use crate::state::ExplorerApiStateContext;
|
||||
|
||||
pub(crate) struct ExplorerApiTasks {
|
||||
state: ExplorerApiStateContext,
|
||||
shutdown: ShutdownListener,
|
||||
}
|
||||
|
||||
impl ExplorerApiTasks {
|
||||
pub(crate) fn new(state: ExplorerApiStateContext) -> Self {
|
||||
ExplorerApiTasks { state }
|
||||
pub(crate) fn new(state: ExplorerApiStateContext, shutdown: ShutdownListener) -> Self {
|
||||
ExplorerApiTasks { state, shutdown }
|
||||
}
|
||||
|
||||
// a helper to remove duplicate code when grabbing active/rewarded/all mixnodes
|
||||
@@ -128,24 +130,28 @@ impl ExplorerApiTasks {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(self) {
|
||||
pub(crate) fn start(mut self) {
|
||||
info!("Spawning mix nodes task runner...");
|
||||
tokio::spawn(async move {
|
||||
let mut interval_timer = tokio::time::interval(CACHE_REFRESH_RATE);
|
||||
loop {
|
||||
// wait for the next interval tick
|
||||
interval_timer.tick().await;
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = interval_timer.tick() => {
|
||||
info!("Updating validator cache...");
|
||||
self.update_validators_cache().await;
|
||||
info!("Done");
|
||||
|
||||
info!("Updating validator cache...");
|
||||
self.update_validators_cache().await;
|
||||
info!("Done");
|
||||
info!("Updating gateway cache...");
|
||||
self.update_gateways_cache().await;
|
||||
info!("Done");
|
||||
|
||||
info!("Updating gateway cache...");
|
||||
self.update_gateways_cache().await;
|
||||
info!("Done");
|
||||
|
||||
info!("Updating mix node cache...");
|
||||
self.update_mixnode_cache().await;
|
||||
info!("Updating mix node cache...");
|
||||
self.update_mixnode_cache().await;
|
||||
}
|
||||
_ = self.shutdown.recv() => {
|
||||
trace!("Listener: Received shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,5 +1,6 @@
|
||||
EXPLORER_API_URL=https://sandbox-explorer.nymtech.net/api/v1
|
||||
VALIDATOR_API_URL=https://sandbox-validator.nymtech.net
|
||||
BIG_DIPPER_URL=https://sandbox-blocks.nymtech.net
|
||||
CURRENCY_DENOM=unymt
|
||||
CURRENCY_STAKING_DENOM=unyxt
|
||||
EXPLORER_API_URL=https://explorer.nymtech.net/api/v1
|
||||
VALIDATOR_API_URL=https://validator.nymtech.net
|
||||
VALIDATOR_URL=https://rpc.nyx.nodes.guru
|
||||
BIG_DIPPER_URL=https://blocks.nymtech.net
|
||||
CURRENCY_DENOM=unym
|
||||
CURRENCY_STAKING_DENOM=unyx
|
||||
|
||||
+4
-3
@@ -1,5 +1,6 @@
|
||||
EXPLORER_API_URL=https://qa-explorer.nymtech.net/api/v1
|
||||
VALIDATOR_API_URL=https://qa-validator.nymtech.net
|
||||
VALIDATOR_API_URL=https://qa-validator-api.nymtech.net
|
||||
VALIDATOR_URL=https://qa-validator.nymtech.net
|
||||
BIG_DIPPER_URL=https://qa-blocks.nymtech.net
|
||||
CURRENCY_DENOM=unymt
|
||||
CURRENCY_STAKING_DENOM=unyxt
|
||||
CURRENCY_DENOM=unym
|
||||
CURRENCY_STAKING_DENOM=unyx
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// master APIs
|
||||
export const API_BASE_URL = process.env.EXPLORER_API_URL;
|
||||
export const VALIDATOR_API_BASE_URL = process.env.VALIDATOR_API_URL;
|
||||
export const VALIDATOR_URL = process.env.VALIDATOR_URL;
|
||||
export const BIG_DIPPER = process.env.BIG_DIPPER_URL;
|
||||
|
||||
// specific API routes
|
||||
@@ -9,7 +10,7 @@ export const MIXNODE_PING = `${API_BASE_URL}/ping`;
|
||||
export const MIXNODES_API = `${API_BASE_URL}/mix-nodes`;
|
||||
export const MIXNODE_API = `${API_BASE_URL}/mix-node`;
|
||||
export const GATEWAYS_API = `${VALIDATOR_API_BASE_URL}/api/v1/gateways`;
|
||||
export const VALIDATORS_API = `${VALIDATOR_API_BASE_URL}/validators`;
|
||||
export const VALIDATORS_API = `${VALIDATOR_URL}/validators`;
|
||||
export const BLOCK_API = `${VALIDATOR_API_BASE_URL}/block`;
|
||||
export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`;
|
||||
export const UPTIME_STORY_API = `${VALIDATOR_API_BASE_URL}/api/v1/status/mixnode`; // add ID then '/history' to this.
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Slider,
|
||||
Typography,
|
||||
Box,
|
||||
@@ -25,7 +24,9 @@ import { useIsMobile } from '../../hooks/useIsMobile';
|
||||
const FilterItem = ({
|
||||
label,
|
||||
id,
|
||||
tooltipInfo,
|
||||
value,
|
||||
isSmooth,
|
||||
marks,
|
||||
scale,
|
||||
min,
|
||||
@@ -36,12 +37,13 @@ const FilterItem = ({
|
||||
}) => (
|
||||
<Box sx={{ p: 2 }}>
|
||||
<Typography gutterBottom>{label}</Typography>
|
||||
<Typography fontSize={12}>{tooltipInfo}</Typography>
|
||||
<Slider
|
||||
value={value}
|
||||
onChange={(e: Event, newValue: number | number[]) => onChange(id, newValue as number[])}
|
||||
valueLabelDisplay="off"
|
||||
valueLabelDisplay={isSmooth ? 'auto' : 'off'}
|
||||
marks={marks}
|
||||
step={null}
|
||||
step={isSmooth ? 1 : null}
|
||||
scale={scale}
|
||||
min={min}
|
||||
max={max}
|
||||
@@ -50,7 +52,7 @@ const FilterItem = ({
|
||||
);
|
||||
|
||||
export const Filters = () => {
|
||||
const { filterMixnodes, fetchMixnodes } = useMainContext();
|
||||
const { filterMixnodes, fetchMixnodes, mixnodes } = useMainContext();
|
||||
const { status } = useParams<{ status: MixnodeStatusWithAll | undefined }>();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
@@ -127,19 +129,26 @@ export const Filters = () => {
|
||||
<Alert
|
||||
severity="info"
|
||||
variant={isMobile ? 'standard' : 'outlined'}
|
||||
sx={{ color: (t) => t.palette.info.light }}
|
||||
action={
|
||||
<Button size="small" onClick={onClearFilters}>
|
||||
Clear
|
||||
CLEAR FILTERS
|
||||
</Button>
|
||||
}
|
||||
sx={{ width: 300 }}
|
||||
>
|
||||
Filters applied
|
||||
{mixnodes?.data?.length} mixnodes matched your criteria
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
<IconButton size="large" onClick={handleToggleShowFilters}>
|
||||
<Tune />
|
||||
</IconButton>
|
||||
<Button
|
||||
size="large"
|
||||
variant="text"
|
||||
color="inherit"
|
||||
endIcon={<Tune />}
|
||||
onClick={handleToggleShowFilters}
|
||||
sx={{ textTransform: 'none' }}
|
||||
>
|
||||
Advanced filters
|
||||
</Button>
|
||||
<Dialog open={showFilters} onClose={handleToggleShowFilters} maxWidth="md" fullWidth>
|
||||
<DialogTitle>Mixnode filters</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
|
||||
@@ -5,6 +5,7 @@ export const generateFilterSchema = (upperSaturationValue?: number) => ({
|
||||
label: 'Profit margin (%)',
|
||||
id: EnumFilterKey.profitMargin,
|
||||
value: [0, 100],
|
||||
isSmooth: true,
|
||||
marks: [
|
||||
{ label: '0', value: 0 },
|
||||
{ label: '10', value: 10 },
|
||||
@@ -18,6 +19,8 @@ export const generateFilterSchema = (upperSaturationValue?: number) => ({
|
||||
{ label: '90', value: 90 },
|
||||
{ label: '100', value: 100 },
|
||||
],
|
||||
tooltipInfo:
|
||||
'As a delegator you want to chose nodes with lower profit margin, meaning more payout for their delegators',
|
||||
},
|
||||
stakeSaturation: {
|
||||
label: 'Stake saturation (%)',
|
||||
@@ -43,65 +46,29 @@ export const generateFilterSchema = (upperSaturationValue?: number) => ({
|
||||
},
|
||||
],
|
||||
max: upperSaturationValue,
|
||||
tooltipInfo: "Select nodes with <100% saturation. Any additional stake above 100% saturation won't get rewards",
|
||||
},
|
||||
stake: {
|
||||
label: 'Stake (NYM)',
|
||||
id: EnumFilterKey.stake,
|
||||
value: [20, 90],
|
||||
min: 20,
|
||||
max: 90,
|
||||
routingScore: {
|
||||
label: 'Routing score (%)',
|
||||
id: EnumFilterKey.routingScore,
|
||||
value: [0, 100],
|
||||
marks: [
|
||||
{
|
||||
value: 0,
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
value: 10,
|
||||
label: '10',
|
||||
},
|
||||
{
|
||||
value: 20,
|
||||
label: '100',
|
||||
},
|
||||
{
|
||||
value: 30,
|
||||
label: '1k',
|
||||
},
|
||||
{
|
||||
value: 40,
|
||||
label: '10k',
|
||||
},
|
||||
{
|
||||
value: 50,
|
||||
label: '100k',
|
||||
},
|
||||
{
|
||||
value: 60,
|
||||
label: '1M',
|
||||
},
|
||||
{
|
||||
value: 70,
|
||||
label: '10M',
|
||||
},
|
||||
{
|
||||
value: 80,
|
||||
label: '100M',
|
||||
},
|
||||
{
|
||||
value: 90,
|
||||
label: '1B',
|
||||
},
|
||||
{ label: '0', value: 0 },
|
||||
{ label: '10', value: 10 },
|
||||
{ label: '20', value: 20 },
|
||||
{ label: '30', value: 30 },
|
||||
{ label: '40', value: 40 },
|
||||
{ label: '50', value: 50 },
|
||||
{ label: '60', value: 60 },
|
||||
{ label: '70', value: 70 },
|
||||
{ label: '80', value: 80 },
|
||||
{ label: '90', value: 90 },
|
||||
{ label: '100', value: 100 },
|
||||
],
|
||||
tooltipInfo: 'The higher the routing score the better the performance of the node and so its rewards',
|
||||
},
|
||||
});
|
||||
|
||||
const formatStakeValuesToMinorDenom = ([value_1, value_2]: number[]) => {
|
||||
const lowerValue = 10 ** (value_1 / 10) * 1_000_000;
|
||||
const upperValue = 10 ** (value_2 / 10) * 1_000_000;
|
||||
|
||||
return [lowerValue, upperValue];
|
||||
};
|
||||
|
||||
const formatStakeSaturationValues = ([value_1, value_2]: number[]) => {
|
||||
const lowerValue = value_1 / 100;
|
||||
const upperValue = value_2 / 100;
|
||||
@@ -110,7 +77,7 @@ const formatStakeSaturationValues = ([value_1, value_2]: number[]) => {
|
||||
};
|
||||
|
||||
export const formatOnSave = (filters: TFilters) => ({
|
||||
stake: formatStakeValuesToMinorDenom(filters.stake.value),
|
||||
routingScore: filters.routingScore.value,
|
||||
profitMargin: filters.profitMargin.value,
|
||||
stakeSaturation: formatStakeSaturationValues(filters.stakeSaturation.value),
|
||||
});
|
||||
|
||||
@@ -102,8 +102,8 @@ export const MainContextProvider: React.FC = ({ children }) => {
|
||||
m.mix_node.profit_margin_percent <= filters.profitMargin[1] &&
|
||||
m.stake_saturation >= filters.stakeSaturation[0] &&
|
||||
m.stake_saturation <= filters.stakeSaturation[1] &&
|
||||
+m.pledge_amount.amount + +m.total_delegation.amount >= filters.stake[0] &&
|
||||
+m.pledge_amount.amount + +m.total_delegation.amount <= filters.stake[1],
|
||||
m.avg_uptime >= filters.routingScore[0] &&
|
||||
m.avg_uptime <= filters.routingScore[1],
|
||||
);
|
||||
setMixnodes({ data: filtered, isLoading: false });
|
||||
};
|
||||
|
||||
@@ -4,17 +4,19 @@ import { Mark } from '@mui/base';
|
||||
export enum EnumFilterKey {
|
||||
profitMargin = 'profitMargin',
|
||||
stakeSaturation = 'stakeSaturation',
|
||||
stake = 'stake',
|
||||
routingScore = 'routingScore',
|
||||
}
|
||||
|
||||
export type TFilterItem = {
|
||||
label: string;
|
||||
id: EnumFilterKey;
|
||||
value: number[];
|
||||
isSmooth?: boolean;
|
||||
marks: Mark[];
|
||||
min?: number;
|
||||
max?: number;
|
||||
scale?: (value: number) => number;
|
||||
tooltipInfo?: string;
|
||||
};
|
||||
|
||||
export type TFilters = { [key in EnumFilterKey]: TFilterItem };
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-gateway"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Mixnet Gateway"
|
||||
edition = "2021"
|
||||
|
||||
@@ -6,11 +6,11 @@ use std::{process, str::FromStr};
|
||||
use crate::{config::Config, Cli};
|
||||
use clap::Subcommand;
|
||||
use colored::Colorize;
|
||||
use config::parse_validators;
|
||||
use crypto::bech32_address_validation;
|
||||
use network_defaults::var_names::{
|
||||
API_VALIDATOR, BECH32_PREFIX, CONFIGURED, NYMD_VALIDATOR, STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
pub(crate) mod init;
|
||||
pub(crate) mod node_details;
|
||||
@@ -69,17 +69,6 @@ pub(crate) async fn execute(args: Cli) {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
let mut was_host_overridden = false;
|
||||
if let Some(host) = args.host {
|
||||
|
||||
@@ -336,6 +336,7 @@ where
|
||||
if self.config.get_enabled_statistics() {
|
||||
let statistics_service_url = self.config.get_statistics_service_url();
|
||||
let stats_collector = GatewayStatisticsCollector::new(
|
||||
self.identity_keypair.public_key().to_base58_string(),
|
||||
active_clients_store.clone(),
|
||||
statistics_service_url,
|
||||
);
|
||||
|
||||
@@ -14,13 +14,19 @@ use statistics_common::{
|
||||
use crate::node::client_handling::active_clients::ActiveClientsStore;
|
||||
|
||||
pub(crate) struct GatewayStatisticsCollector {
|
||||
gateway_id: String,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
statistics_service_url: Url,
|
||||
}
|
||||
|
||||
impl GatewayStatisticsCollector {
|
||||
pub fn new(active_clients_store: ActiveClientsStore, statistics_service_url: Url) -> Self {
|
||||
pub fn new(
|
||||
gateway_id: String,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
statistics_service_url: Url,
|
||||
) -> Self {
|
||||
GatewayStatisticsCollector {
|
||||
gateway_id,
|
||||
active_clients_store,
|
||||
statistics_service_url,
|
||||
}
|
||||
@@ -35,7 +41,10 @@ impl StatisticsCollector for GatewayStatisticsCollector {
|
||||
timestamp: DateTime<Utc>,
|
||||
) -> StatsMessage {
|
||||
let inbox_count = self.active_clients_store.size() as u32;
|
||||
let stats_data = vec![StatsData::Gateway(StatsGatewayData { inbox_count })];
|
||||
let stats_data = vec![StatsData::Gateway(StatsGatewayData::new(
|
||||
self.gateway_id.clone(),
|
||||
inbox_count,
|
||||
))];
|
||||
StatsMessage {
|
||||
stats_data,
|
||||
interval_seconds: interval.as_secs() as u32,
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-mixnode"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
|
||||
@@ -6,9 +6,11 @@ use std::process;
|
||||
use crate::{config::Config, Cli};
|
||||
use clap::Subcommand;
|
||||
use colored::Colorize;
|
||||
use config::defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED};
|
||||
use config::{
|
||||
defaults::var_names::{API_VALIDATOR, BECH32_PREFIX, CONFIGURED},
|
||||
parse_validators,
|
||||
};
|
||||
use crypto::bech32_address_validation;
|
||||
use url::Url;
|
||||
|
||||
mod describe;
|
||||
mod init;
|
||||
@@ -61,17 +63,6 @@ pub(crate) async fn execute(args: Cli) {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
let mut was_host_overridden = false;
|
||||
if let Some(host) = args.host {
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ fn long_version_static() -> &'static str {
|
||||
#[derive(Parser)]
|
||||
#[clap(author = "Nymtech", version, about, long_version = long_version_static())]
|
||||
struct Cli {
|
||||
/// Path pointing to an env file that configures the gateway.
|
||||
/// Path pointing to an env file that configures the mixnode.
|
||||
#[clap(long)]
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
|
||||
Generated
+1983
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "chitchat-test"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
chitchat = "0.4"
|
||||
poem = "1"
|
||||
poem-openapi = {version="2", features = ["swagger-ui"] }
|
||||
structopt = "0.3"
|
||||
tokio = { version = "1.14.0", features = ["net", "sync", "rt-multi-thread", "macros", "time"] }
|
||||
serde = { version="1", features=["derive"] }
|
||||
serde_json = "1"
|
||||
anyhow = "1"
|
||||
once_cell = "1"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3"
|
||||
cool-id-generator = "1"
|
||||
env_logger = "0.9"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2"
|
||||
predicates = "2"
|
||||
reqwest = { version = "0.11", default-features=false, features = ["blocking", "json"] }
|
||||
|
||||
[workspace]
|
||||
@@ -0,0 +1,15 @@
|
||||
# Chitchat test
|
||||
|
||||
Runs simple chitchat servers, mostly copied over from https://github.com/quickwit-oss/chitchat
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# Starts 5 servers and joins them into a cluster on localhost ports 10000-10004
|
||||
# All servers print cluster state on `/` ie 127.0.0.1:10000
|
||||
# `/docs` endpoint has an open api with a key value setter, set it on one node and observe how the state propagates to the other nodes
|
||||
# NodeState is a regular BTreeMap
|
||||
./run-servers.sh
|
||||
|
||||
# run killall chitchat-test after you're done, as the servers will continue to run forever in the background
|
||||
```
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
killall chitchat-test
|
||||
|
||||
cargo build --release
|
||||
|
||||
for i in $(seq 10000 10004)
|
||||
do
|
||||
listen_addr="127.0.0.1:$i";
|
||||
echo ${listen_addr};
|
||||
cargo run --release -- --listen_addr ${listen_addr} --seed 127.0.0.1:10000 --node_id node_$i &
|
||||
done;
|
||||
|
||||
read
|
||||
kill 0
|
||||
@@ -0,0 +1,123 @@
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use chitchat::transport::UdpTransport;
|
||||
use chitchat::{spawn_chitchat, Chitchat, ChitchatConfig, FailureDetectorConfig, NodeId};
|
||||
use cool_id_generator::Size;
|
||||
use poem::listener::TcpListener;
|
||||
use poem::{Route, Server};
|
||||
use poem_openapi::param::Query;
|
||||
use poem_openapi::payload::Json;
|
||||
use poem_openapi::{OpenApi, OpenApiService};
|
||||
use structopt::StructOpt;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use chitchat::ClusterStateSnapshot;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ApiResponse {
|
||||
pub cluster_id: String,
|
||||
pub cluster_state: ClusterStateSnapshot,
|
||||
pub live_nodes: Vec<NodeId>,
|
||||
pub dead_nodes: Vec<NodeId>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SetKeyValueResponse {
|
||||
pub status: bool,
|
||||
}
|
||||
|
||||
struct Api {
|
||||
chitchat: Arc<Mutex<Chitchat>>,
|
||||
}
|
||||
|
||||
#[OpenApi]
|
||||
impl Api {
|
||||
/// Chitchat state
|
||||
#[oai(path = "/", method = "get")]
|
||||
async fn index(&self) -> Json<serde_json::Value> {
|
||||
let chitchat_guard = self.chitchat.lock().await;
|
||||
let response = ApiResponse {
|
||||
cluster_id: chitchat_guard.cluster_id().to_string(),
|
||||
cluster_state: chitchat_guard.state_snapshot(),
|
||||
live_nodes: chitchat_guard.live_nodes().cloned().collect::<Vec<_>>(),
|
||||
dead_nodes: chitchat_guard.dead_nodes().cloned().collect::<Vec<_>>(),
|
||||
};
|
||||
Json(serde_json::to_value(&response).unwrap())
|
||||
}
|
||||
|
||||
/// Set a key & value on this node (with no validation).
|
||||
#[oai(path = "/set_kv/", method = "get")]
|
||||
async fn set_kv(&self, key: Query<String>, value: Query<String>) -> Json<serde_json::Value> {
|
||||
let mut chitchat_guard = self.chitchat.lock().await;
|
||||
|
||||
let cc_state = chitchat_guard.self_node_state();
|
||||
cc_state.set(key.as_str(), value.as_str());
|
||||
|
||||
Json(serde_json::to_value(&SetKeyValueResponse { status: true }).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "chitchat", about = "Chitchat test server.")]
|
||||
struct Opt {
|
||||
/// Defines the socket addr on which we should listen to.
|
||||
#[structopt(long = "listen_addr", default_value = "127.0.0.1:10000")]
|
||||
listen_addr: SocketAddr,
|
||||
/// Defines the socket_address (host:port) other servers should use to
|
||||
/// reach this server.
|
||||
///
|
||||
/// It defaults to the listen address, but this is only valid
|
||||
/// when all server are running on the same server.
|
||||
#[structopt(long = "public_addr")]
|
||||
public_addr: Option<SocketAddr>,
|
||||
|
||||
/// Node id. Has to be unique. If None, the node_id will be generated from
|
||||
/// the public_addr and a random suffix.
|
||||
#[structopt(long = "node_id")]
|
||||
node_id: Option<String>,
|
||||
|
||||
#[structopt(long = "seed")]
|
||||
seeds: Vec<String>,
|
||||
|
||||
#[structopt(long = "interval_ms", default_value = "500")]
|
||||
interval: u64,
|
||||
}
|
||||
|
||||
fn generate_server_id(public_addr: SocketAddr) -> String {
|
||||
let cool_id = cool_id_generator::get_id(Size::Medium);
|
||||
format!("server:{}-{}", public_addr, cool_id)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt::init();
|
||||
let opt = Opt::from_args();
|
||||
println!("{:?}", opt);
|
||||
let public_addr = opt.public_addr.unwrap_or(opt.listen_addr);
|
||||
let node_id_str = opt
|
||||
.node_id
|
||||
.unwrap_or_else(|| generate_server_id(public_addr));
|
||||
let node_id = NodeId::new(node_id_str, public_addr);
|
||||
let config = ChitchatConfig {
|
||||
node_id,
|
||||
cluster_id: "testing".to_string(),
|
||||
gossip_interval: Duration::from_millis(opt.interval),
|
||||
listen_addr: opt.listen_addr,
|
||||
seed_nodes: opt.seeds.clone(),
|
||||
failure_detector_config: FailureDetectorConfig::default(),
|
||||
};
|
||||
let chitchat_handler = spawn_chitchat(config, Vec::new(), &UdpTransport).await?;
|
||||
let chitchat = chitchat_handler.chitchat();
|
||||
let api = Api { chitchat };
|
||||
let api_service = OpenApiService::new(api, "Hello World", "1.0")
|
||||
.server(&format!("http://{}/", opt.listen_addr));
|
||||
let docs = api_service.swagger_ui();
|
||||
let app = Route::new().nest("/", api_service).nest("/docs", docs);
|
||||
Server::new(TcpListener::bind(&opt.listen_addr))
|
||||
.run(app)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
## [nym-connect-v1.0.1](https://github.com/nymtech/nym/tree/nym-connect-v1.0.1) (2022-07-22)
|
||||
|
||||
### Added
|
||||
|
||||
- nym-connect: initial proof-of-concept of a UI around the socks5 client was added
|
||||
- nym-connect: add ability to select network requester and gateway ([#1427])
|
||||
- nym-connect: add ability to export gateway keys as JSON
|
||||
- nym-connect: add auto updater
|
||||
|
||||
### Changed
|
||||
|
||||
- nym-connect: reuse config id instead of creating a new id on each connection
|
||||
|
||||
[#1427]: https://github.com/nymtech/nym/pull/1427
|
||||
Generated
+2
-3
@@ -3199,7 +3199,6 @@ dependencies = [
|
||||
"cosmwasm-std",
|
||||
"fixed",
|
||||
"log",
|
||||
"network-defaults",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
@@ -3405,7 +3404,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-connect"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"client-core",
|
||||
@@ -3437,7 +3436,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"client-core",
|
||||
|
||||
@@ -32,7 +32,7 @@ yarn install
|
||||
|
||||
## Development mode
|
||||
|
||||
You can compile nym-connectin development mode by running the following command inside the `nym-connect` directory:
|
||||
You can compile nym-connect in development mode by running the following command inside the `nym-connect` directory:
|
||||
|
||||
```
|
||||
yarn dev
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-connect"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
description = "nym-connect"
|
||||
authors = ["Nym Technologies SA"]
|
||||
license = ""
|
||||
@@ -39,7 +39,7 @@ tokio = { version = "1.19.1", features = ["sync", "time"] }
|
||||
url = "2.2"
|
||||
|
||||
client-core = { path = "../../clients/client-core" }
|
||||
config = { path = "../../common/config" }
|
||||
config-common = { path = "../../common/config", package = "config" }
|
||||
nym-socks5-client = { path = "../../clients/socks5" }
|
||||
topology = { path = "../../common/topology" }
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use tap::TapFallible;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use client_core::config::Config as BaseConfig;
|
||||
use config::NymConfig;
|
||||
use config_common::NymConfig;
|
||||
use nym_socks5::client::config::Config as Socks5Config;
|
||||
|
||||
use crate::{
|
||||
@@ -135,6 +135,12 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
|
||||
.get_base_mut()
|
||||
.with_eth_private_key(DEFAULT_ETH_PRIVATE_KEY);
|
||||
|
||||
if let Ok(raw_validators) = std::env::var(config_common::defaults::var_names::API_VALIDATOR) {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(config_common::parse_validators(&raw_validators));
|
||||
}
|
||||
|
||||
let gateway = setup_gateway(
|
||||
&id,
|
||||
register_gateway,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use config_common::defaults::setup_env;
|
||||
use tauri::Menu;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
@@ -24,6 +25,7 @@ mod window;
|
||||
|
||||
fn main() {
|
||||
setup_logging();
|
||||
setup_env(None);
|
||||
println!("Starting up...");
|
||||
|
||||
// As per breaking change description here
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use ::config::NymConfig;
|
||||
use ::config_common::NymConfig;
|
||||
use futures::SinkExt;
|
||||
use tap::TapFallible;
|
||||
use tauri::Manager;
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use tap::TapFallible;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use config::NymConfig;
|
||||
use config_common::NymConfig;
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
use nym_socks5::client::NymClient as Socks5NymClient;
|
||||
use nym_socks5::client::{config::Config as Socks5Config, Socks5ControlMessageSender};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "nym-connect",
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
|
||||
@@ -22,11 +22,14 @@ export const DefaultLayout: React.FC<{
|
||||
};
|
||||
return (
|
||||
<AppWindowFrame>
|
||||
<Typography fontWeight="700" fontSize="14px" textAlign="center">
|
||||
Connect, your privacy will be 100% protected thanks to the Nym Mixnet
|
||||
<Typography fontWeight="400" fontSize="12px" textAlign="center" sx={{ opacity: 0.6 }}>
|
||||
This is experimental software. <br />
|
||||
Do not rely on it for strong anonymity (yet).
|
||||
</Typography>
|
||||
<Typography fontWeight="700" fontSize="14px" textAlign="center" color="#60D6EF" pt={2}>
|
||||
You are not protected now
|
||||
<Typography fontWeight="700" fontSize="14px" textAlign="center" pt={2}>
|
||||
Connect to the
|
||||
<br />
|
||||
Nym mixnet for privacy.
|
||||
</Typography>
|
||||
<ServiceProviderSelector services={services} onChange={handleServiceProviderChange} />
|
||||
<ConnectionButton
|
||||
|
||||
@@ -1 +1 @@
|
||||
ADMIN_ADDRESS={"MAINNET":[],"SANDBOX":[],"QA":["n1c8te4wlc25re97qw5nh8urtpek494zqx30lza2","n177krl498arsfupd2p9097kwfmuf07lkj6crmj9"]}
|
||||
ADMIN_ADDRESS={\"MAINNET\":[],\"SANDBOX\":[],\"QA\":[\"n1c8te4wlc25re97qw5nh8urtpek494zqx30lza2\",\"n177krl498arsfupd2p9097kwfmuf07lkj6crmj9\"]}
|
||||
@@ -0,0 +1,213 @@
|
||||
## [nym-wallet-v1.0.8](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.0.8) (2022-08-11)
|
||||
|
||||
- wallet: new bonding flow and screen for bonded node
|
||||
- wallet: compound and redeem functionalities for operator rewards
|
||||
- wallet: a few minor touch ups and bug fixes
|
||||
|
||||
|
||||
## [nym-wallet-v1.0.7](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.7) (2022-07-11)
|
||||
|
||||
- wallet: dark mode
|
||||
- wallet: when simulating gas costs, an automatic adjustment is being used ([#1388]).
|
||||
|
||||
[#1388]: https://github.com/nymtech/nym/pull/1388
|
||||
|
||||
|
||||
## [nym-wallet-v1.0.6](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.6) (2022-06-21)
|
||||
|
||||
- wallet: undelegating now uses either the mixnet or vesting contract, or both, depending on how delegations were made
|
||||
- wallet: redeeming and compounding now uses both the mixnet and vesting contract
|
||||
- wallet: the wallet backend learned how to archive wallet files
|
||||
- wallet: add ENABLE_QA_MODE environment variable to enable QA mode on built wallet
|
||||
|
||||
## [nym-wallet-v1.0.5](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.5) (2022-06-14)
|
||||
|
||||
- wallet: add simple CLI tool for decrypting and recovering the wallet file.
|
||||
- wallet: added support for multiple accounts ([#1265])
|
||||
- wallet: compound and claim reward endpoints for operators and delegators ([#1302])
|
||||
- wallet: require password to switch accounts
|
||||
- wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint.
|
||||
- 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
|
||||
|
||||
[#1265]: https://github.com/nymtech/nym/pull/1265
|
||||
[#1302]: https://github.com/nymtech/nym/pull/1302
|
||||
|
||||
## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04)
|
||||
|
||||
### Changed
|
||||
|
||||
- all: the default behaviour of validator client is changed to use `broadcast_sync` and poll for transaction inclusion instead of using `broadcast_commit` to deal with timeouts ([#1246])
|
||||
|
||||
## [nym-wallet-v1.0.3](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.3) (2022-04-25)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-binaries-1.0.0-rc.2...nym-wallet-v1.0.3)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \[Issue\] Wallet 1.0.2 cannot send NYM tokens from a DelayedVestingAccount [\#1215](https://github.com/nymtech/nym/issues/1215)
|
||||
- Main README not showing properly with GitHub dark mode [\#1211](https://github.com/nymtech/nym/issues/1211)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Bugfix - wallet undelegation for vesting accounts [\#1220](https://github.com/nymtech/nym/pull/1220) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Bugfix/delegation reconcile [\#1219](https://github.com/nymtech/nym/pull/1219) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bugfix/query proxied pending delegations [\#1218](https://github.com/nymtech/nym/pull/1218) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Using custom gas multiplier in the wallet [\#1217](https://github.com/nymtech/nym/pull/1217) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/vesting accounts support [\#1216](https://github.com/nymtech/nym/pull/1216) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Release/1.0.0 rc.2 [\#1214](https://github.com/nymtech/nym/pull/1214) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- chore: fix dark mode rendering [\#1212](https://github.com/nymtech/nym/pull/1212) ([pwnfoo](https://github.com/pwnfoo))
|
||||
- Feature/spend coconut [\#1210](https://github.com/nymtech/nym/pull/1210) ([neacsu](https://github.com/neacsu))
|
||||
- Bugfix/unique sphinx key [\#1207](https://github.com/nymtech/nym/pull/1207) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Add cache read and write timeouts [\#1206](https://github.com/nymtech/nym/pull/1206) ([durch](https://github.com/durch))
|
||||
- Additional, more informative routes [\#1204](https://github.com/nymtech/nym/pull/1204) ([durch](https://github.com/durch))
|
||||
- Feature/aggregated econ dynamics explorer endpoint [\#1203](https://github.com/nymtech/nym/pull/1203) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Debugging validator [\#1198](https://github.com/nymtech/nym/pull/1198) ([durch](https://github.com/durch))
|
||||
- wallet: expose additional validator configuration functionality to the frontend [\#1195](https://github.com/nymtech/nym/pull/1195) ([octol](https://github.com/octol))
|
||||
- Update rewarding validator address [\#1193](https://github.com/nymtech/nym/pull/1193) ([durch](https://github.com/durch))
|
||||
- Crypto part of the Groth's NIDKG [\#1182](https://github.com/nymtech/nym/pull/1182) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- fix unbond page [\#1180](https://github.com/nymtech/nym/pull/1180) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Type safe bounds [\#1179](https://github.com/nymtech/nym/pull/1179) ([durch](https://github.com/durch))
|
||||
- Fix delegation paging [\#1174](https://github.com/nymtech/nym/pull/1174) ([durch](https://github.com/durch))
|
||||
- Update binaries to rc version [\#1172](https://github.com/nymtech/nym/pull/1172) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Bump ansi-regex from 4.1.0 to 4.1.1 in /docker/typescript\_client/upload\_contract [\#1171](https://github.com/nymtech/nym/pull/1171) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
|
||||
## [nym-wallet-v1.0.2](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.2) (2022-04-05)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-wallet-v1.0.1...nym-wallet-v1.0.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Wallet 1.0.2 visual tweaks [\#1197](https://github.com/nymtech/nym/pull/1197) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Password for wallet with routes [\#1196](https://github.com/nymtech/nym/pull/1196) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Add auto-updater to Nym Wallet [\#1194](https://github.com/nymtech/nym/pull/1194) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Fix clippy warnings for beta toolchain [\#1191](https://github.com/nymtech/nym/pull/1191) ([octol](https://github.com/octol))
|
||||
- wallet: expose validator urls to the frontend [\#1190](https://github.com/nymtech/nym/pull/1190) ([octol](https://github.com/octol))
|
||||
- wallet: add test for decrypting stored wallet file [\#1189](https://github.com/nymtech/nym/pull/1189) ([octol](https://github.com/octol))
|
||||
- Fix clippy warnings [\#1188](https://github.com/nymtech/nym/pull/1188) ([octol](https://github.com/octol))
|
||||
- Password for wallet with routes [\#1187](https://github.com/nymtech/nym/pull/1187) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- wallet: add validate\_mnemonic [\#1186](https://github.com/nymtech/nym/pull/1186) ([octol](https://github.com/octol))
|
||||
- wallet: support removing accounts from the wallet file [\#1185](https://github.com/nymtech/nym/pull/1185) ([octol](https://github.com/octol))
|
||||
- Feature/adding discord [\#1184](https://github.com/nymtech/nym/pull/1184) ([gala1234](https://github.com/gala1234))
|
||||
- wallet: config backend for validator selection [\#1183](https://github.com/nymtech/nym/pull/1183) ([octol](https://github.com/octol))
|
||||
- Add storybook to wallet [\#1178](https://github.com/nymtech/nym/pull/1178) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- wallet: connection test nymd and api urls independently [\#1170](https://github.com/nymtech/nym/pull/1170) ([octol](https://github.com/octol))
|
||||
- wallet: wire up account storage [\#1153](https://github.com/nymtech/nym/pull/1153) ([octol](https://github.com/octol))
|
||||
- Feature/signature on deposit [\#1151](https://github.com/nymtech/nym/pull/1151) ([neacsu](https://github.com/neacsu))
|
||||
|
||||
## [nym-wallet-v1.0.1](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.1) (2022-04-05)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/nym-binaries-1.0.0-rc.1...nym-wallet-v1.0.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Check enabling bbbc simultaneously with open access. Estimate what it would take to make this the default compilation target. [\#1175](https://github.com/nymtech/nym/issues/1175)
|
||||
- Get coconut credential for deposited tokens [\#1138](https://github.com/nymtech/nym/issues/1138)
|
||||
- Make payments lazy [\#1135](https://github.com/nymtech/nym/issues/1135)
|
||||
- Uptime on node selection for sets [\#1049](https://github.com/nymtech/nym/issues/1049)
|
||||
|
||||
## [nym-wallet-v1.0.0](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.0) (2022-02-03)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.12.1...nym-wallet-v1.0.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- \[Feature Request\] Please enable registration without need for Telegram account [\#1016](https://github.com/nymtech/nym/issues/1016)
|
||||
- Fast mixnode launch with a pre-built ISO + VM software [\#1001](https://github.com/nymtech/nym/issues/1001)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \[Issue\] [\#1000](https://github.com/nymtech/nym/issues/1000)
|
||||
- \[Issue\] `nym-client` requires multiple attempts to run a server [\#869](https://github.com/nymtech/nym/issues/869)
|
||||
- De-'float'-ing `Interval` \(`Display` impl + `serde`\) [\#1065](https://github.com/nymtech/nym/pull/1065) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- display client address on wallet creation [\#1058](https://github.com/nymtech/nym/pull/1058) ([fmtabbara](https://github.com/fmtabbara))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Rewarded set inclusion probability API endpoint [\#1037](https://github.com/nymtech/nym/issues/1037)
|
||||
- Update cw-storage-plus to 0.11 [\#1032](https://github.com/nymtech/nym/issues/1032)
|
||||
- Change `u128` fields in `RewardEstimationResponse` to `u64` [\#1029](https://github.com/nymtech/nym/issues/1029)
|
||||
- Test out the mainnet Gravity Bridge [\#1006](https://github.com/nymtech/nym/issues/1006)
|
||||
- Add vesting contract interface to nym-wallet [\#959](https://github.com/nymtech/nym/issues/959)
|
||||
- Mixnode crash [\#486](https://github.com/nymtech/nym/issues/486)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- create custom urls for mainnet [\#1095](https://github.com/nymtech/nym/pull/1095) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Wallet signing on MacOS [\#1093](https://github.com/nymtech/nym/pull/1093) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Fix rust 2018 idioms warnings [\#1092](https://github.com/nymtech/nym/pull/1092) ([octol](https://github.com/octol))
|
||||
- Prevent contract overwriting [\#1090](https://github.com/nymtech/nym/pull/1090) ([durch](https://github.com/durch))
|
||||
- Logout operation [\#1087](https://github.com/nymtech/nym/pull/1087) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Update to rust edition 2021 everywhere [\#1086](https://github.com/nymtech/nym/pull/1086) ([octol](https://github.com/octol))
|
||||
- Tag contract errors, and print out lines for easier QA [\#1084](https://github.com/nymtech/nym/pull/1084) ([durch](https://github.com/durch))
|
||||
- Feature/flexible vesting + utility queries [\#1083](https://github.com/nymtech/nym/pull/1083) ([durch](https://github.com/durch))
|
||||
- Bump @openzeppelin/contracts from 4.3.1 to 4.4.2 in /contracts/basic-bandwidth-generation [\#1082](https://github.com/nymtech/nym/pull/1082) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump nth-check from 2.0.0 to 2.0.1 in /clients/native/examples/js-examples/websocket [\#1081](https://github.com/nymtech/nym/pull/1081) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump url-parse from 1.5.1 to 1.5.4 in /clients/native/examples/js-examples/websocket [\#1080](https://github.com/nymtech/nym/pull/1080) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump follow-redirects from 1.14.1 to 1.14.7 in /clients/native/examples/js-examples/websocket [\#1079](https://github.com/nymtech/nym/pull/1079) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump nanoid from 3.1.23 to 3.2.0 in /clients/native/examples/js-examples/websocket [\#1078](https://github.com/nymtech/nym/pull/1078) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Setup basic test for mixnode stats reporting [\#1077](https://github.com/nymtech/nym/pull/1077) ([octol](https://github.com/octol))
|
||||
- Make wallet\_address mandatory for mixnode init [\#1076](https://github.com/nymtech/nym/pull/1076) ([octol](https://github.com/octol))
|
||||
- Tidy nym-mixnode module visibility [\#1075](https://github.com/nymtech/nym/pull/1075) ([octol](https://github.com/octol))
|
||||
- Feature/wallet login with password [\#1074](https://github.com/nymtech/nym/pull/1074) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Add trait to mock client dependency in DelayForwarder [\#1073](https://github.com/nymtech/nym/pull/1073) ([octol](https://github.com/octol))
|
||||
- Bump rust-version to latest stable for nym-mixnode [\#1072](https://github.com/nymtech/nym/pull/1072) ([octol](https://github.com/octol))
|
||||
- Fixes CI for our wasm build [\#1069](https://github.com/nymtech/nym/pull/1069) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Add @octol as codeowner [\#1068](https://github.com/nymtech/nym/pull/1068) ([octol](https://github.com/octol))
|
||||
- set-up inclusion probability [\#1067](https://github.com/nymtech/nym/pull/1067) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Feature/wasm client [\#1066](https://github.com/nymtech/nym/pull/1066) ([neacsu](https://github.com/neacsu))
|
||||
- Changed bech32\_prefix from punk to nymt [\#1064](https://github.com/nymtech/nym/pull/1064) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump nanoid from 3.1.30 to 3.2.0 in /testnet-faucet [\#1063](https://github.com/nymtech/nym/pull/1063) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump nanoid from 3.1.30 to 3.2.0 in /nym-wallet [\#1062](https://github.com/nymtech/nym/pull/1062) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Rework vesting contract storage [\#1061](https://github.com/nymtech/nym/pull/1061) ([durch](https://github.com/durch))
|
||||
- Mixnet Contract constants extraction [\#1060](https://github.com/nymtech/nym/pull/1060) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- fix: make explorer footer year dynamic [\#1059](https://github.com/nymtech/nym/pull/1059) ([martinyung](https://github.com/martinyung))
|
||||
- Add mnemonic just on creation, to display it [\#1057](https://github.com/nymtech/nym/pull/1057) ([neacsu](https://github.com/neacsu))
|
||||
- Network Explorer: updates to API and UI to show the active set [\#1056](https://github.com/nymtech/nym/pull/1056) ([mmsinclair](https://github.com/mmsinclair))
|
||||
- Made contract addresses for query NymdClient construction optional [\#1055](https://github.com/nymtech/nym/pull/1055) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Introduced RPC query for total token supply [\#1053](https://github.com/nymtech/nym/pull/1053) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/tokio console [\#1052](https://github.com/nymtech/nym/pull/1052) ([durch](https://github.com/durch))
|
||||
- Implemented beta clippy lint recommendations [\#1051](https://github.com/nymtech/nym/pull/1051) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- add new function to update profit percentage [\#1050](https://github.com/nymtech/nym/pull/1050) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Upgrade Clap and use declarative argument parsing for nym-mixnode [\#1047](https://github.com/nymtech/nym/pull/1047) ([octol](https://github.com/octol))
|
||||
- Feature/additional bond validation [\#1046](https://github.com/nymtech/nym/pull/1046) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Fix clippy on relevant lints [\#1044](https://github.com/nymtech/nym/pull/1044) ([neacsu](https://github.com/neacsu))
|
||||
- Bump shelljs from 0.8.4 to 0.8.5 in /contracts/basic-bandwidth-generation [\#1043](https://github.com/nymtech/nym/pull/1043) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Endpoint for rewarded set inclusion probabilities [\#1042](https://github.com/nymtech/nym/pull/1042) ([durch](https://github.com/durch))
|
||||
- Bump follow-redirects from 1.14.4 to 1.14.7 in /contracts/basic-bandwidth-generation [\#1041](https://github.com/nymtech/nym/pull/1041) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump follow-redirects from 1.14.5 to 1.14.7 in /testnet-faucet [\#1040](https://github.com/nymtech/nym/pull/1040) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/node settings update [\#1036](https://github.com/nymtech/nym/pull/1036) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Migrate to cw-storage-plus 0.11.1 [\#1035](https://github.com/nymtech/nym/pull/1035) ([durch](https://github.com/durch))
|
||||
- Bump @openzeppelin/contracts from 4.4.1 to 4.4.2 in /contracts/basic-bandwidth-generation [\#1034](https://github.com/nymtech/nym/pull/1034) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/configurable wallet [\#1033](https://github.com/nymtech/nym/pull/1033) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/downcast reward estimation [\#1031](https://github.com/nymtech/nym/pull/1031) ([durch](https://github.com/durch))
|
||||
- Wallet UI updates [\#1028](https://github.com/nymtech/nym/pull/1028) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Remove migration code [\#1027](https://github.com/nymtech/nym/pull/1027) ([neacsu](https://github.com/neacsu))
|
||||
- Chore/stricter dependency requirements [\#1025](https://github.com/nymtech/nym/pull/1025) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator api client endpoints [\#1024](https://github.com/nymtech/nym/pull/1024) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Updated cosmrs to 0.4.1 [\#1023](https://github.com/nymtech/nym/pull/1023) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/testnet deploy scripts [\#1022](https://github.com/nymtech/nym/pull/1022) ([mfahampshire](https://github.com/mfahampshire))
|
||||
- Changed wallet's client to a full validator client [\#1021](https://github.com/nymtech/nym/pull/1021) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fix 404 link [\#1020](https://github.com/nymtech/nym/pull/1020) ([RiccardoMasutti](https://github.com/RiccardoMasutti))
|
||||
- Feature/additional mixnode endpoints [\#1019](https://github.com/nymtech/nym/pull/1019) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Introduced denom check when trying to withdraw vested coins [\#1018](https://github.com/nymtech/nym/pull/1018) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Add network defaults for qa [\#1017](https://github.com/nymtech/nym/pull/1017) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/expanded events [\#1015](https://github.com/nymtech/nym/pull/1015) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- update frontend to use new profit update api [\#1014](https://github.com/nymtech/nym/pull/1014) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Feature/node state endpoint [\#1013](https://github.com/nymtech/nym/pull/1013) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/hourly set updates [\#1012](https://github.com/nymtech/nym/pull/1012) ([durch](https://github.com/durch))
|
||||
- Feature/remove unused profit margin [\#1011](https://github.com/nymtech/nym/pull/1011) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/explorer node status [\#1010](https://github.com/nymtech/nym/pull/1010) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Use serial integer instead of random [\#1009](https://github.com/nymtech/nym/pull/1009) ([durch](https://github.com/durch))
|
||||
- Feature/configure profit [\#1008](https://github.com/nymtech/nym/pull/1008) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/fix gateway sign [\#1004](https://github.com/nymtech/nym/pull/1004) ([neacsu](https://github.com/neacsu))
|
||||
- Fix clippy [\#1003](https://github.com/nymtech/nym/pull/1003) ([neacsu](https://github.com/neacsu))
|
||||
- Update wallet version [\#998](https://github.com/nymtech/nym/pull/998) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Fix wallet build instructions [\#997](https://github.com/nymtech/nym/pull/997) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Make the separation between testnet-mode and erc20 bandwidth mode clearer [\#994](https://github.com/nymtech/nym/pull/994) ([neacsu](https://github.com/neacsu))
|
||||
- Bump @openzeppelin/contracts from 3.4.0 to 4.4.1 in /contracts/basic-bandwidth-generation [\#983](https://github.com/nymtech/nym/pull/983) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/implicit runtime [\#973](https://github.com/nymtech/nym/pull/973) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Differentiate staking and ownership [\#961](https://github.com/nymtech/nym/pull/961) ([durch](https://github.com/durch))
|
||||
Generated
+92
-15
@@ -3055,7 +3055,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym_wallet"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"argon2 0.3.4",
|
||||
@@ -3273,7 +3273,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"parking_lot_core 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3290,6 +3300,19 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec 1.8.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.3.2"
|
||||
@@ -3996,9 +4019,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -4016,9 +4039,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
@@ -4550,6 +4573,15 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "1.3.2"
|
||||
@@ -4635,9 +4667,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "state"
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cf4f5369e6d3044b5e365c9690f451516ac8f0954084622b49ea3fde2f6de5"
|
||||
checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b"
|
||||
dependencies = [
|
||||
"loom",
|
||||
]
|
||||
@@ -4656,7 +4688,7 @@ checksum = "33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"new_debug_unreachable",
|
||||
"parking_lot",
|
||||
"parking_lot 0.11.2",
|
||||
"phf_shared 0.10.0",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
@@ -4838,7 +4870,7 @@ dependencies = [
|
||||
"ndk-glue",
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
"parking_lot 0.11.2",
|
||||
"raw-window-handle",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
@@ -5241,7 +5273,9 @@ dependencies = [
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot 0.12.1",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
@@ -5898,11 +5932,11 @@ version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_msvc 0.30.0",
|
||||
"windows_i686_gnu 0.30.0",
|
||||
"windows_i686_msvc 0.30.0",
|
||||
"windows_x86_64_gnu 0.30.0",
|
||||
"windows_x86_64_msvc 0.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5915,12 +5949,31 @@ dependencies = [
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.36.1",
|
||||
"windows_i686_gnu 0.36.1",
|
||||
"windows_i686_msvc 0.36.1",
|
||||
"windows_x86_64_gnu 0.36.1",
|
||||
"windows_x86_64_msvc 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_gen"
|
||||
version = "0.30.0"
|
||||
@@ -5937,12 +5990,24 @@ version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_macros"
|
||||
version = "0.30.0"
|
||||
@@ -5973,12 +6038,24 @@ version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.7.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym_wallet"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
description = "Nym Native Wallet"
|
||||
authors = ["Nym Technologies SA"]
|
||||
license = ""
|
||||
@@ -32,14 +32,14 @@ log = "0.4"
|
||||
once_cell = "1.7.2"
|
||||
pretty_env_logger = "0.4"
|
||||
rand = "0.6.5"
|
||||
reqwest = "0.11.9"
|
||||
reqwest = {version = "0.11.9", features = ["json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
tauri = { version = "=1.0.0-rc.2", features = ["clipboard-all", "shell-open", "updater", "window-maximize"] }
|
||||
tendermint-rpc = "0.23.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.10", features = ["sync", "time"] }
|
||||
tokio = { version = "1.10", features = ["full"] }
|
||||
toml = "0.5.8"
|
||||
url = "2.2"
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ fn main() {
|
||||
mixnet::bond::unbond_gateway,
|
||||
mixnet::bond::unbond_mixnode,
|
||||
mixnet::bond::update_mixnode,
|
||||
mixnet::bond::get_number_of_mixnode_delegators,
|
||||
mixnet::bond::get_mix_node_description,
|
||||
mixnet::delegate::delegate_to_mixnode,
|
||||
mixnet::delegate::get_delegator_rewards,
|
||||
mixnet::delegate::get_pending_delegation_events,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::state::WalletState;
|
||||
use crate::{Gateway, MixNode};
|
||||
@@ -5,8 +7,18 @@ use nym_types::currency::DecCoin;
|
||||
use nym_types::gateway::GatewayBond;
|
||||
use nym_types::mixnode::MixNodeBond;
|
||||
use nym_types::transaction::TransactionExecuteResult;
|
||||
use reqwest::Error as ReqwestError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator_client::nymd::{Coin, Fee};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct NodeDescription {
|
||||
name: String,
|
||||
description: String,
|
||||
link: String,
|
||||
location: String,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_gateway(
|
||||
gateway: Gateway,
|
||||
@@ -198,3 +210,51 @@ pub async fn get_operator_rewards(
|
||||
);
|
||||
Ok(display_coin)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_number_of_mixnode_delegators(
|
||||
identity: String,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<usize, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let paged_delegations = client
|
||||
.nymd
|
||||
.get_mix_delegations_paged(identity, None, Some(20))
|
||||
.await?;
|
||||
|
||||
Ok(paged_delegations.delegations.len())
|
||||
}
|
||||
|
||||
async fn fetch_mix_node_description(
|
||||
host: &str,
|
||||
port: u16,
|
||||
) -> Result<NodeDescription, ReqwestError> {
|
||||
let milli_second = Duration::from_millis(1000);
|
||||
let client = reqwest::Client::builder().timeout(milli_second).build()?;
|
||||
let response = client
|
||||
.get(format!("http://{}:{}/description", host, port))
|
||||
.send()
|
||||
.await;
|
||||
|
||||
match response {
|
||||
Ok(res) => {
|
||||
let json = res.json::<NodeDescription>().await;
|
||||
match json {
|
||||
Ok(json) => Ok(json),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_mix_node_description(
|
||||
host: &str,
|
||||
port: u16,
|
||||
) -> Result<NodeDescription, BackendError> {
|
||||
fetch_mix_node_description(host, port)
|
||||
.await
|
||||
.map_err(|e| BackendError::ReqwestError { source: e })
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"accounts": [
|
||||
{
|
||||
"id": "default",
|
||||
"account": {
|
||||
"ciphertext": "cq5w4W5ex5eFFRcqLG+824XyUAUoYmrRY3NGw/rue6/mLoQKQE/07+BxzRuKjyYFasC1HBPg41KJwp2IY+/7+80rB9aXPpaKVLUcG9U40qgCw66WhgxTrXOnrt5toefpSTBL7f9N/PVwpuumfAgD9CS0ioB7/9Qoea7nYKkextGX15ex26B/ndQddvUkQ4gx+Vq7OLymv4l+nkdZ2nKMja349zd/BjnzPBB68/iIjyYlivVjtQ7FRbvpNRj6Mjg4905wGlO7bTpkw+RGiaGK4pK8fTWz8gAKr8GYoXPD",
|
||||
"salt": "SPVGdbVyoEayD4ZzM4I+Jg==",
|
||||
"iv": "tjpn/tRjD1gty+fQ"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"accounts": [
|
||||
{
|
||||
"id": "default",
|
||||
"account": {
|
||||
"ciphertext": "3MDgoU2i5QMc9r80yPeq2AMk5wpkke0tXum5NsOE5NcFciF+aHLQW0dvXbGszap1y3nN4+YZD3cgGrmtKh/cChqRGJDkniaxdf3XPHh9RkiWXw2KSHHeyGrFY0INJeiky1ZtUFhWhopcHJWSnfCmVC15YFpnM5xOKpITjHAFhGt98MaYR+mS+3zoUFrjYbaZRh2TR2lFWsbR8YU1uaTYqJZ1HX1PBCub6aS3vjQm0Fwa+hAtR/gMymXJc5qtruTO4NbqYtMj3Z9eIgoVB+56SLAXlIF1Uo1pjvV0mx1hWNNiIc10ujF/wl/nnKF6icOcmrfm9XhOtsvUYBsE/wAIJZw3LKXgSX+hJbOl+zLAwJZK1xiL8n/nM1IJZDn+Wu6z0OzRaj9S7T16+brMw1oaqjk56saM8n5z725fizJj+ur6gnPBWnoyHPaCHgHdB2PKQNY0ZlwRM6dVncRaEWQDLAboyMq3FXxK9UbusNcDFpYw6bdnuJlNVf6y9yxwyvkUrt5YtgfkLyoW42z1PVtVWsV9P8eE/A/tnYjXf34xvba3K8Y1/3DTi7uuydNrSR/XhA+pevz68VWCbY+j746Yi8Lz7altePphkjfJAezodobKvMplXzqInopIWNovyemw/+1E7WZbkQIOAXg1WC1+Y/df+dffRGuGRdDerfRLmA5XLej1M/wE3WQ7b9KwlAo6XJ4hnQKwyDCqYP/ButBXW1AOnnZpCq59gGbiccZJsTMZB4OP95yFPgz8//IeDgma2PDixVmDEp0SGHhN7dlSoNa5eoglblqzJu/TcTA6jmQFA3ef0GiA3QzBjmyB4bz0bFybh8XA1brVIVlsjRwXb3/UYaVqsP6Hy1QDUpZofXIJs5lK0hUd0ECdaNFXXgHd25ifPocp09WLFyK92H6i3ABDZ7pu3b4lTUt6kHt6LTVsKkyylmYf2iMHnCcmfy4uxGTXxRjPjMgKL8pd++OZ3q62jLBuoTjgdj6pccwDvD+NYQ2FFeHmBzxyTLqUyKltYiyFlJHWLKOcXyeDHzRhHic+e/wn3VhM3NdrvtqYWA9m72Ye1L1I7VX7KatGurG6CeiFiY5xHxxpLT7dF0fJ7uxRye4JnRyYQuU7iK72qCKjgYjwjCIha4qPi5Q/x6S+uVe7yX5Eb73L3eB+IlkyW9wPHmSOcE4GpbMU96tK8xoxT0T9eQlj050GDnJ/oI2XHfZTs1bIxsjfZqW03g==",
|
||||
"salt": "wXR3RnPmsoA3ncrixIvaUw==",
|
||||
"iv": "/Zjn1OXsLJhA43n/"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"accounts": [
|
||||
{
|
||||
"id": "first",
|
||||
"account": {
|
||||
"ciphertext": "icnpxLmr/H7FIIOaEf7DYNLuM6uhh7poEppXpYCllQD33TjY+8eLtVvhEQmjX60IQeFOd+1JCcrHa2B12vlBAYlfM4gBxA6d2ZJ8+Dw/vNvBNyChiyUx2euV3vPGOs22r/XDBsmEeF40XZcXftQZa2kzYaPnkbP+eiMOIWkcY4FYOEHwx5SxT4VBPZIrVTC3iDalJLWybVbbw/Bc2zbzEXI1ckg4Ccydj95SMil9BiyDpALfZqwlai7I97S+BjmcVxSCsYqFjTkRUHVMjrEr7fWHKU4DIOM=",
|
||||
"salt": "CtnbfkxTybqz0U4cPHW2jQ==",
|
||||
"iv": "77ZROU6dAMttEWwS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "second",
|
||||
"account": {
|
||||
"ciphertext": "nsqZHdQFlskglc5izKgnr8sBwdMmd82h2Rnjdos9EUca3cqkUdFYEjZDsK8OGR3GZ9alLTNt/1U97Rvvr2HPAWbzl23FW2YXaLTA6yj6ZwQK5w0MYE061NYbcxNHuzT9f5aQWkGULAk4RWb5t8eUX7y/NdJr3tA5xuGOLhooTfBB98/4RpupDsYGZp1DPC/GMFppOA3GmKs9bacZm805Bhfq5mwhXab1SjJQpFHMHisCMhxo/oLqulKML1tQMetBdqDTjJmPpdUnd1mi",
|
||||
"salt": "J2TMLjKv4dkZ/kXso9FGhg==",
|
||||
"iv": "CTqqoMa4LetvBKCP"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "nym-wallet",
|
||||
"version": "1.0.7"
|
||||
"version": "1.0.8"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Avatar } from '@mui/material';
|
||||
import { Avatar, Typography } from '@mui/material';
|
||||
import stc from 'string-to-color';
|
||||
import { TAccount } from 'src/types';
|
||||
|
||||
export const AccountAvatar = ({ name }: Pick<TAccount, 'name'>) => (
|
||||
<Avatar sx={{ bgcolor: stc(name), width: 20, height: 20 }}>{name?.split('')[0]}</Avatar>
|
||||
export const AccountAvatar = ({ name, small }: { name: TAccount['name']; small?: boolean }) => (
|
||||
<Avatar sx={{ bgcolor: stc(name), ...(small ? { width: 25, height: 25 } : {}) }}>
|
||||
<Typography fontSize={small ? 14 : 'inherit'} fontWeight={600}>
|
||||
{name?.split('')[0]}
|
||||
</Typography>
|
||||
</Avatar>
|
||||
);
|
||||
|
||||
@@ -5,10 +5,10 @@ import { AccountAvatar } from './AccountAvatar';
|
||||
|
||||
export const AccountOverview = ({ account, onClick }: { account: AccountEntry; onClick: () => void }) => (
|
||||
<Button
|
||||
startIcon={<AccountAvatar name={account.id} />}
|
||||
startIcon={<AccountAvatar name={account.id} small />}
|
||||
sx={{ color: 'text.primary' }}
|
||||
color="inherit"
|
||||
onClick={onClick}
|
||||
disableRipple
|
||||
>
|
||||
{account.id}
|
||||
</Button>
|
||||
|
||||
@@ -20,7 +20,7 @@ export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handle
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ color: (t) => t.palette.nym.text.muted }}>
|
||||
<Typography variant="body1" sx={{ color: (theme) => theme.palette.nym.text.muted }}>
|
||||
How to set up multiple accounts
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
@@ -29,7 +29,7 @@ export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handle
|
||||
<Alert
|
||||
severity="warning"
|
||||
icon={false}
|
||||
sx={(t) => (t.palette.mode === 'dark' ? { bgcolor: (t) => t.palette.background.paper } : {})}
|
||||
sx={(t) => (t.palette.mode === 'dark' ? { bgcolor: (theme) => theme.palette.background.paper } : {})}
|
||||
>
|
||||
<Typography>In order to create multiple accounts your wallet needs a password.</Typography>
|
||||
<Typography>Follow steps below to create password.</Typography>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Typography,
|
||||
Divider,
|
||||
} from '@mui/material';
|
||||
import { Add, ArrowDownwardSharp, Close } from '@mui/icons-material';
|
||||
import { AccountsContext } from 'src/context';
|
||||
@@ -51,7 +52,7 @@ export const AccountsModal = () => {
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ color: (theme) => theme.palette.text.disabled }}>
|
||||
<Typography fontSize="small" sx={{ color: 'grey.600' }}>
|
||||
Switch between accounts
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
@@ -69,6 +70,7 @@ export const AccountsModal = () => {
|
||||
/>
|
||||
))}
|
||||
</DialogContent>
|
||||
<Divider variant="middle" sx={{ mt: 3 }} />
|
||||
<DialogActions sx={{ p: 3 }}>
|
||||
<Button startIcon={<ArrowDownwardSharp />} onClick={() => setDialogToDisplay('Import')}>
|
||||
Import account
|
||||
|
||||
@@ -7,17 +7,16 @@ import {
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
TextField,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { ArrowBackSharp } from '@mui/icons-material';
|
||||
import { useClipboard } from 'use-clipboard-copy';
|
||||
import { createMnemonic, validateMnemonic } from 'src/requests';
|
||||
import { Console } from 'src/utils/console';
|
||||
import { AccountsContext } from 'src/context';
|
||||
import { ConfirmPassword, Mnemonic } from 'src/components';
|
||||
import { MnemonicInput } from 'src/components/textfields';
|
||||
import { StyledBackButton } from 'src/components/StyledBackButton';
|
||||
|
||||
const createAccountSteps = [
|
||||
'Copy and save mnemonic for your new account',
|
||||
@@ -30,14 +29,15 @@ const importAccountSteps = [
|
||||
'Confirm the password used to login to your wallet',
|
||||
];
|
||||
|
||||
const MnemonicStep = ({ mnemonic, onNext }: { mnemonic: string; onNext: () => void }) => {
|
||||
const MnemonicStep = ({ mnemonic, onNext, onBack }: { mnemonic: string; onNext: () => void; onBack: () => void }) => {
|
||||
const { copy, copied } = useClipboard({ copiedTimeout: 5000 });
|
||||
return (
|
||||
<Box sx={{ mt: 1 }}>
|
||||
<DialogContent>
|
||||
<Mnemonic mnemonic={mnemonic} handleCopy={copy} copied={copied} />
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3, pt: 0 }}>
|
||||
<DialogActions sx={{ p: 3, pt: 0, gap: 2 }}>
|
||||
<StyledBackButton onBack={onBack} />
|
||||
<Button disabled={!copied} fullWidth disableElevation variant="contained" size="large" onClick={onNext}>
|
||||
I saved my mnemonic
|
||||
</Button>
|
||||
@@ -50,10 +50,12 @@ const ImportMnemonic = ({
|
||||
value,
|
||||
onChange,
|
||||
onNext,
|
||||
onBack,
|
||||
}: {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
onNext: () => void;
|
||||
onBack: () => void;
|
||||
}) => {
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
@@ -77,7 +79,8 @@ const ImportMnemonic = ({
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3, pt: 0 }}>
|
||||
<DialogActions sx={{ p: 3, pt: 0, gap: 2 }}>
|
||||
<StyledBackButton onBack={onBack} />
|
||||
<Button
|
||||
disabled={value.length === 0}
|
||||
fullWidth
|
||||
@@ -93,7 +96,7 @@ const ImportMnemonic = ({
|
||||
);
|
||||
};
|
||||
|
||||
const NameAccount = ({ onNext }: { onNext: (value: string) => void }) => {
|
||||
const NameAccount = ({ onNext, onBack }: { onNext: (value: string) => void; onBack: () => void }) => {
|
||||
const [value, setValue] = useState('');
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
@@ -121,7 +124,8 @@ const NameAccount = ({ onNext }: { onNext: (value: string) => void }) => {
|
||||
fullWidth
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3, pt: 0 }}>
|
||||
<DialogActions sx={{ p: 3, pt: 0, gap: 2 }}>
|
||||
<StyledBackButton onBack={onBack} />
|
||||
<Button
|
||||
disabled={!value.length}
|
||||
fullWidth
|
||||
@@ -178,9 +182,6 @@ export const AddAccountModal = () => {
|
||||
<DialogTitle sx={{ pb: 0 }}>
|
||||
<Box display="flex" justifyContent="space-between" alignItems="center">
|
||||
<Typography variant="h6">{`${dialogToDisplay} new account`}</Typography>
|
||||
<IconButton onClick={() => (step === 0 ? handleClose() : setStep((s) => s - 1))}>
|
||||
<ArrowBackSharp />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography sx={{ mt: 2 }}>
|
||||
{dialogToDisplay === 'Add' ? createAccountSteps[step] : importAccountSteps[step]}
|
||||
@@ -190,12 +191,17 @@ export const AddAccountModal = () => {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return dialogToDisplay === 'Add' ? (
|
||||
<MnemonicStep mnemonic={data.mnemonic} onNext={() => setStep((s) => s + 1)} />
|
||||
<MnemonicStep
|
||||
mnemonic={data.mnemonic}
|
||||
onNext={() => setStep((s) => s + 1)}
|
||||
onBack={() => (step === 0 ? handleClose() : setStep((s) => s - 1))}
|
||||
/>
|
||||
) : (
|
||||
<ImportMnemonic
|
||||
value={data.mnemonic}
|
||||
onChange={(value) => setData((d) => ({ ...d, mnemonic: value }))}
|
||||
onNext={() => setStep((s) => s + 1)}
|
||||
onBack={() => (step === 0 ? handleClose() : setStep((s) => s - 1))}
|
||||
/>
|
||||
);
|
||||
case 1:
|
||||
@@ -205,6 +211,7 @@ export const AddAccountModal = () => {
|
||||
setData((d) => ({ ...d, accountName }));
|
||||
setStep((s) => s + 1);
|
||||
}}
|
||||
onBack={() => setStep((s) => s - 1)}
|
||||
/>
|
||||
);
|
||||
case 2:
|
||||
@@ -222,6 +229,7 @@ export const AddAccountModal = () => {
|
||||
}
|
||||
}
|
||||
}}
|
||||
onCancel={() => setStep((s) => s - 1)}
|
||||
isLoading={isLoading}
|
||||
error={error}
|
||||
/>
|
||||
|
||||
@@ -19,17 +19,18 @@ export const ConfirmPasswordModal = ({
|
||||
<Dialog open={Boolean(accountName)} onClose={onClose} fullWidth>
|
||||
<Paper>
|
||||
<DialogTitle>
|
||||
<Box display="flex" justifyContent="space-between" alignItems="center">
|
||||
<Typography variant="h6">Switch account</Typography>
|
||||
<IconButton onClick={onClose}>
|
||||
<ArrowBack />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ color: (theme) => theme.palette.text.disabled }}>
|
||||
<Typography variant="h6">Switch account</Typography>
|
||||
<Typography fontSize="small" sx={{ color: 'grey.600' }}>
|
||||
Confirm password
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<ConfirmPassword onConfirm={onConfirm} error={error} isLoading={isLoading} buttonTitle="Switch account" />
|
||||
<ConfirmPassword
|
||||
onConfirm={onConfirm}
|
||||
error={error}
|
||||
isLoading={isLoading}
|
||||
buttonTitle="Switch account"
|
||||
onCancel={onClose}
|
||||
/>
|
||||
</Paper>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -33,7 +33,7 @@ export const EditAccountModal = () => {
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ color: (theme) => theme.palette.text.disabled }}>
|
||||
<Typography fontSize="small" sx={{ color: 'grey.600' }}>
|
||||
New wallet address
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Paper,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
TextField,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { Close } from '@mui/icons-material';
|
||||
import { AccountsContext } from 'src/context';
|
||||
|
||||
export const ImportAccountModal = () => {
|
||||
const [mnemonic, setMnemonic] = useState('');
|
||||
|
||||
const { dialogToDisplay, setDialogToDisplay, handleImportAccount } = useContext(AccountsContext);
|
||||
|
||||
const handleClose = () => {
|
||||
setMnemonic('');
|
||||
setDialogToDisplay('Accounts');
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={dialogToDisplay === 'Import'} onClose={handleClose} fullWidth>
|
||||
<Paper>
|
||||
<DialogTitle>
|
||||
<Box display="flex" justifyContent="space-between" alignItems="center">
|
||||
<Typography variant="h6">Import account</Typography>
|
||||
<IconButton onClick={handleClose}>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ color: (theme) => theme.palette.text.disabled }}>
|
||||
Provide mnemonic of account you want to import
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ p: 0 }}>
|
||||
<Box sx={{ px: 3, mt: 1 }}>
|
||||
<TextField
|
||||
placeholder="Paste or type your mnemonic here"
|
||||
fullWidth
|
||||
value={mnemonic}
|
||||
onChange={(e) => setMnemonic(e.target.value)}
|
||||
autoFocus
|
||||
multiline
|
||||
rows={3}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3 }}>
|
||||
<Button
|
||||
fullWidth
|
||||
disableElevation
|
||||
variant="contained"
|
||||
size="large"
|
||||
onClick={() => handleImportAccount({ id: '', address: '' })}
|
||||
disabled={!mnemonic.length}
|
||||
>
|
||||
Import account
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Paper>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
import React, { useRef } from 'react';
|
||||
import { MoreVertSharp } from '@mui/icons-material';
|
||||
import { IconButton, ListItemIcon, ListItemText, Menu, MenuItem } from '@mui/material';
|
||||
|
||||
export const ActionsMenu: React.FC<{ open: boolean; onOpen: () => void; onClose: () => void }> = ({
|
||||
children,
|
||||
open,
|
||||
onOpen,
|
||||
onClose,
|
||||
}) => {
|
||||
const anchorEl: any = useRef<HTMLElement>();
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton ref={anchorEl} onClick={onOpen}>
|
||||
<MoreVertSharp />
|
||||
</IconButton>
|
||||
<Menu anchorEl={anchorEl.current} open={open} onClose={onClose}>
|
||||
{children}
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ActionsMenuItem = ({
|
||||
title,
|
||||
description,
|
||||
onClick,
|
||||
Icon,
|
||||
disabled,
|
||||
}: {
|
||||
title: string;
|
||||
description?: string;
|
||||
onClick?: () => void;
|
||||
Icon?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
}) => (
|
||||
<MenuItem sx={{ p: 2 }} onClick={onClick} disabled={disabled}>
|
||||
<ListItemIcon sx={{ color: 'text.primary' }}>{Icon}</ListItemIcon>
|
||||
<ListItemText sx={{ color: 'text.primary' }} primary={title} secondary={description} />
|
||||
</MenuItem>
|
||||
);
|
||||
@@ -7,13 +7,11 @@ import ModeNightOutlinedIcon from '@mui/icons-material/ModeNightOutlined';
|
||||
import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined';
|
||||
import { AppContext } from '../context/main';
|
||||
import { NetworkSelector } from './NetworkSelector';
|
||||
import { Node as NodeIcon } from '../svg-icons/node';
|
||||
import { MultiAccounts } from './Accounts';
|
||||
import { config } from '../config';
|
||||
|
||||
export const AppBar = () => {
|
||||
const { logOut, handleShowTerminal, appEnv, handleShowSettings, showSettings, mode, handleSwitchMode } =
|
||||
useContext(AppContext);
|
||||
const { logOut, handleShowTerminal, appEnv, mode, handleSwitchMode } = useContext(AppContext);
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
@@ -31,7 +29,7 @@ export const AppBar = () => {
|
||||
<Grid item container justifyContent="flex-end" md={12} lg={5} spacing={2}>
|
||||
<Grid item>
|
||||
<IconButton size="small" onClick={handleSwitchMode} sx={{ color: 'text.primary' }}>
|
||||
{mode === 'light' ? (
|
||||
{mode === 'dark' ? (
|
||||
<LightModeOutlinedIcon fontSize="small" />
|
||||
) : (
|
||||
<ModeNightOutlinedIcon fontSize="small" sx={{ transform: 'rotate(180deg)' }} />
|
||||
@@ -45,15 +43,6 @@ export const AppBar = () => {
|
||||
</IconButton>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item>
|
||||
<IconButton
|
||||
onClick={handleShowSettings}
|
||||
sx={{ color: showSettings ? 'primary.main' : 'text.primary' }}
|
||||
size="small"
|
||||
>
|
||||
<NodeIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
size="small"
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Logout } from '@mui/icons-material';
|
||||
import TerminalIcon from '@mui/icons-material/Terminal';
|
||||
import ModeNightOutlinedIcon from '@mui/icons-material/ModeNightOutlined';
|
||||
import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined';
|
||||
import { AppBar as MuiAppBar, Grid, IconButton, Toolbar } from '@mui/material';
|
||||
import { Node } from 'src/svg-icons/node';
|
||||
import { config } from '../../config';
|
||||
import { AppContext } from '../../context/main';
|
||||
import { MultiAccounts } from '../Accounts';
|
||||
import { NetworkSelector } from '../NetworkSelector';
|
||||
|
||||
export const AppBar = () => {
|
||||
const { showSettings, handleShowTerminal, appEnv, handleShowSettings, logOut, mode, handleSwitchMode } =
|
||||
useContext(AppContext);
|
||||
|
||||
return (
|
||||
<MuiAppBar position="sticky" sx={{ boxShadow: 'none', bgcolor: 'transparent', backgroundImage: 'none' }}>
|
||||
<Toolbar disableGutters>
|
||||
<Grid container justifyContent="space-between" alignItems="center" flexWrap="nowrap">
|
||||
<Grid item container alignItems="center" spacing={1}>
|
||||
<Grid item>
|
||||
<MultiAccounts />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<NetworkSelector />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container justifyContent="flex-end" md={12} lg={5} spacing={2}>
|
||||
<Grid item>
|
||||
<IconButton size="small" onClick={handleSwitchMode} sx={{ color: 'text.primary' }}>
|
||||
{mode === 'light' ? (
|
||||
<ModeNightOutlinedIcon fontSize="small" />
|
||||
) : (
|
||||
<LightModeOutlinedIcon fontSize="small" />
|
||||
)}
|
||||
</IconButton>
|
||||
</Grid>
|
||||
{(appEnv?.SHOW_TERMINAL || config.IS_DEV_MODE) && (
|
||||
<Grid item>
|
||||
<IconButton size="small" onClick={handleShowTerminal} sx={{ color: 'text.primary' }}>
|
||||
<TerminalIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item>
|
||||
<IconButton
|
||||
onClick={handleShowSettings}
|
||||
sx={{ color: showSettings ? 'primary.main' : 'text.primary' }}
|
||||
size="small"
|
||||
>
|
||||
<Node fontSize="small" />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton size="small" onClick={logOut} sx={{ color: 'text.primary' }}>
|
||||
<Logout fontSize="small" />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Toolbar>
|
||||
</MuiAppBar>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './AppBar';
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { Box, Button, Typography } from '@mui/material';
|
||||
import { NymCard } from '../NymCard';
|
||||
|
||||
export const Bond = ({
|
||||
onBond,
|
||||
disabled,
|
||||
}: {
|
||||
onBond: () => void;
|
||||
|
||||
disabled: boolean;
|
||||
}) => (
|
||||
<NymCard title="Bonding" borderless>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Typography>Bond a mixnode or a gateway</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'flex-end',
|
||||
justifyContent: 'space-between',
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
size="large"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
type="button"
|
||||
disableElevation
|
||||
onClick={onBond}
|
||||
disabled={disabled}
|
||||
>
|
||||
Bond
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</NymCard>
|
||||
);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user