Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f84921109 | |||
| 85f84f8273 | |||
| 93df5c1240 | |||
| c9657eee1d | |||
| e9ef129725 | |||
| ef540edb16 | |||
| 60f9f33f3a | |||
| 8d282f2b26 | |||
| 4d745e3b7e | |||
| 3a053b8dd6 | |||
| 1f144690da | |||
| eec1895acc | |||
| 99864cb7a9 | |||
| 3155728119 | |||
| 65a1d6d91e | |||
| 44cf9b054b | |||
| 39e2473ef3 | |||
| 93a108863c | |||
| 0905593123 | |||
| ed9223d5a3 | |||
| 962684ff56 | |||
| 7b3804c078 | |||
| 170f1823e1 | |||
| dc2020559a | |||
| 2b9444cce3 | |||
| 68c1c068ac | |||
| 3d0b70a237 | |||
| 65a6edc78c | |||
| 2ec8349897 | |||
| 38a2d94f80 | |||
| c7fa910516 | |||
| 2fe08274dd | |||
| be89d848dc | |||
| a230a9b8b9 | |||
| 72eae7cdf3 | |||
| 7cae195370 | |||
| dfb16e385c | |||
| 660e1cad0a | |||
| 7c1aa57a7e | |||
| a06e496f78 | |||
| 70599b97b9 | |||
| 02b194bde0 | |||
| 20ec049db5 | |||
| ebac4e8564 | |||
| da81664729 | |||
| fec3d46b33 | |||
| a4eb3a7dbf | |||
| 28d15f2c4f | |||
| 6078787daa | |||
| 6d93f36c82 | |||
| c6f93e38f5 | |||
| 2159f71888 | |||
| a9abea3446 | |||
| 8e2713c9ba | |||
| 2ba0ef0e35 | |||
| d3713cbc79 | |||
| 4d3fb2b585 | |||
| e65e611859 | |||
| ebfb9c4bc1 | |||
| 8e7918cc45 | |||
| c465eb3efc | |||
| b90136ac4e | |||
| ae5373168d | |||
| 6f3942f6b7 | |||
| 4a25725a11 | |||
| 13f38343aa | |||
| d34c829174 | |||
| f75b4843e8 | |||
| 6963ead65a | |||
| 0425cdeaf0 | |||
| 789914b096 | |||
| 8acd3a0975 | |||
| fa1519ec6a | |||
| da94b7e8df | |||
| 4aa8cb4647 | |||
| 5d13538508 | |||
| 4bbbcf629d | |||
| 34ef970fd8 | |||
| fec570613c | |||
| 14a904eff0 | |||
| 24ffb8fe8c | |||
| d1bf1f2005 | |||
| c42b3f7617 | |||
| 606144dd87 | |||
| 31cd62b676 | |||
| b43844bd7a | |||
| 53366c4151 | |||
| 7cb5afdeab | |||
| d18f4c0380 | |||
| c9c4059c90 | |||
| cd89feb57e | |||
| 17553d606e | |||
| 3fe33dec8b | |||
| 589074360d | |||
| 2e5406692c | |||
| b6d9ed960b | |||
| 1920177b2f | |||
| 1d89a887fb | |||
| f562433519 | |||
| 2affa76304 | |||
| d6aeb9142f | |||
| 70af84b6b1 | |||
| fc397053c8 | |||
| 3092c8e68e | |||
| 4a1efab5c8 | |||
| a2d57f269d | |||
| 38c4cc3345 | |||
| 6005bf6101 | |||
| 78b9ebb463 | |||
| ad7f993f0f | |||
| 9be8a53ea2 | |||
| a89f8cf2ab | |||
| a2dab0e64d | |||
| 52459f6545 | |||
| a82bc3356e | |||
| 8585a68d7f | |||
| e8540c13a5 | |||
| 5a24a8fafc | |||
| 1195b120ff | |||
| 405d4653df | |||
| 57187be113 | |||
| fbd634a866 | |||
| 8d4eba858e |
@@ -41,8 +41,8 @@ jobs:
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
|
||||
@@ -104,12 +104,9 @@ jobs:
|
||||
name: nym-binaries-artifacts
|
||||
path: |
|
||||
target/release/nym-client
|
||||
target/release/nym-gateway
|
||||
target/release/nym-mixnode
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
@@ -124,12 +121,9 @@ jobs:
|
||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
||||
run: |
|
||||
cp target/release/nym-client $OUTPUT_DIR
|
||||
cp target/release/nym-gateway $OUTPUT_DIR
|
||||
cp target/release/nym-mixnode $OUTPUT_DIR
|
||||
cp target/release/nym-socks5-client $OUTPUT_DIR
|
||||
cp target/release/nym-api $OUTPUT_DIR
|
||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||
cp target/release/nym-network-statistics $OUTPUT_DIR
|
||||
cp target/release/nymvisor $OUTPUT_DIR
|
||||
cp target/release/nym-node $OUTPUT_DIR
|
||||
cp target/release/nym-cli $OUTPUT_DIR
|
||||
|
||||
@@ -46,8 +46,8 @@ jobs:
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
name: ci-nym-connect-desktop-rust
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "nym-connect/desktop/src-tauri/**"
|
||||
- "nym-connect/desktop/src-tauri/Cargo.toml"
|
||||
- "clients/client-core/**"
|
||||
- "clients/socks5/**"
|
||||
- "common/**"
|
||||
- "gateway/gateway-requests/**"
|
||||
- "contracts/vesting/**"
|
||||
- "nym-api/nym-api-requests/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: [self-hosted, custom-linux]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check
|
||||
|
||||
- name: Build all binaries
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- name: Run all tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
name: Clippy checks
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features
|
||||
|
||||
- name: Run clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features -- -D warnings
|
||||
@@ -1,72 +0,0 @@
|
||||
name: ci-nym-connect-desktop
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-connect/desktop/**'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: Install project dependencies
|
||||
run: cd ../.. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
continue-on-error: true
|
||||
|
||||
- name: Set environment from the example
|
||||
run: cp .env.sample .env
|
||||
- run: yarn storybook:build
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "nym-connect/desktop/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nym-connect
|
||||
NYM_PROJECT_NAME: "nym-connect"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "nym-connect-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -1,92 +0,0 @@
|
||||
name: nightly-nym-connect-desktop-build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: ${{ env.MANIFEST_PATH }} --all -- --check
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: ${{ env.MANIFEST_PATH }} --release --workspace
|
||||
|
||||
- name: Unit tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v2
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v3
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Matrix - Node Install
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nightly
|
||||
NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -1,122 +0,0 @@
|
||||
name: publish-nym-connect-macos
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-12-large]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: |
|
||||
export WASM_PACK_VERSION="v0.12.1"
|
||||
curl -LO https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
tar xvzf wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz -C $HOME/.cargo/bin --strip-components=1
|
||||
rm wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
|
||||
- name: Install the Apple developer certificate for code signing
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
# import certificate and provisioning profile from secrets
|
||||
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
|
||||
|
||||
# create temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
|
||||
# import certificate to keychain
|
||||
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies and build it
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect_1.0.0_x64.dmg
|
||||
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1*_x64.dmg
|
||||
retention-days: 30
|
||||
|
||||
- name: Clean up keychain
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/dmg/*.dmg
|
||||
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -1,89 +0,0 @@
|
||||
name: publish-nym-connect-ubuntu
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [custom-ubuntu-20.04]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Tauri dependencies
|
||||
run: >
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Build app
|
||||
run: yarn build
|
||||
env:
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect.AppImage.tar.gz
|
||||
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1*_amd64.AppImage
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -1,108 +0,0 @@
|
||||
name: publish-nym-connect-win10
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [windows10]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- name: Clean up first
|
||||
continue-on-error: true
|
||||
working-directory: .
|
||||
run: |
|
||||
cd ..
|
||||
del /s /q /A:H nym
|
||||
rmdir /s /q nym
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Import signing certificate
|
||||
env:
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
||||
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
||||
Remove-Item -path certificate -include tempCert.txt
|
||||
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
shell: bash
|
||||
run: yarn --network-timeout 100000
|
||||
|
||||
- name: Build and sign it
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect_1.0.0_x64_en-US.msi
|
||||
path: nym-connect/desktop/target/release/bundle/msi/nym-connect_1*_x64_en-US.msi
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -1,29 +0,0 @@
|
||||
const Handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function addToContextAndValidate(context) {
|
||||
if (!context.env.NYM_CI_WWW_LOCATION) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
|
||||
}
|
||||
if (!context.env.NYM_CI_WWW_BASE) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
|
||||
}
|
||||
}
|
||||
|
||||
async function getMessageBody(context) {
|
||||
const source = fs
|
||||
.readFileSync(
|
||||
context.env.IS_SUCCESS === 'true'
|
||||
? path.resolve(__dirname, 'templates', 'success')
|
||||
: path.resolve(__dirname, 'templates', 'failure'),
|
||||
)
|
||||
.toString();
|
||||
const template = Handlebars.compile(source);
|
||||
return template(context);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addToContextAndValidate,
|
||||
getMessageBody,
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||
>
|
||||
> 🔴 **FAILURE** :cry:
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
>
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
>
|
||||
|
||||
Commit message:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -1,16 +0,0 @@
|
||||
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View storybook:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
|
||||
>
|
||||
> ✅ **SUCCESS**
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
>
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
>
|
||||
|
||||
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
+33
-1
@@ -4,7 +4,39 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.6-chomp] (2024-06-14)
|
||||
## [2024.7-doubledecker] (2024-07-04)
|
||||
|
||||
- Add an early return in `parse_raw_str_logs` for empty raw log strings. ([#4686])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /wasm/mix-fetch/internal-dev ([#4672])
|
||||
- add expiry returned on import ([#4670])
|
||||
- [bugfix] missing rustls feature ([#4666])
|
||||
- Bump ws from 8.13.0 to 8.17.1 in /wasm/client/internal-dev-node ([#4665])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /clients/native/examples/js-examples/websocket ([#4663])
|
||||
- Bump ws from 8.14.2 to 8.17.1 in /sdk/typescript/packages/nodejs-client ([#4662])
|
||||
- Update setup.md ([#4661])
|
||||
- New clippy lints ([#4660])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /nym-api/tests ([#4659])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /docker/typescript_client/upload_contract ([#4658])
|
||||
- Update vps-setup.md ([#4656])
|
||||
- Update configuration.md ([#4655])
|
||||
- Remove old PR template ([#4639])
|
||||
|
||||
[#4686]: https://github.com/nymtech/nym/pull/4686
|
||||
[#4672]: https://github.com/nymtech/nym/pull/4672
|
||||
[#4670]: https://github.com/nymtech/nym/pull/4670
|
||||
[#4666]: https://github.com/nymtech/nym/pull/4666
|
||||
[#4665]: https://github.com/nymtech/nym/pull/4665
|
||||
[#4663]: https://github.com/nymtech/nym/pull/4663
|
||||
[#4662]: https://github.com/nymtech/nym/pull/4662
|
||||
[#4661]: https://github.com/nymtech/nym/pull/4661
|
||||
[#4660]: https://github.com/nymtech/nym/pull/4660
|
||||
[#4659]: https://github.com/nymtech/nym/pull/4659
|
||||
[#4658]: https://github.com/nymtech/nym/pull/4658
|
||||
[#4656]: https://github.com/nymtech/nym/pull/4656
|
||||
[#4655]: https://github.com/nymtech/nym/pull/4655
|
||||
[#4639]: https://github.com/nymtech/nym/pull/4639
|
||||
|
||||
## [2024.6-chomp] (2024-06-25)
|
||||
|
||||
- Remove additional code as part of Ephemera Purge and SP and contracts ([#4650])
|
||||
- bugfix: make sure nym-api can handle non-cw2 (or without detailed build info) compliant contracts ([#4648])
|
||||
|
||||
Generated
+78
-68
@@ -2093,14 +2093,14 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "explorer-api"
|
||||
version = "1.1.35"
|
||||
version = "1.1.36"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.5.4",
|
||||
"dotenvy",
|
||||
"humantime-serde",
|
||||
"isocountry",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"maxminddb",
|
||||
"nym-bin-common",
|
||||
@@ -2221,7 +2221,7 @@ dependencies = [
|
||||
"atomic 0.6.0",
|
||||
"pear",
|
||||
"serde",
|
||||
"toml 0.8.12",
|
||||
"toml 0.8.14",
|
||||
"uncased",
|
||||
"version_check",
|
||||
]
|
||||
@@ -3272,15 +3272,6 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
@@ -3858,7 +3849,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.39"
|
||||
version = "1.1.40"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3959,6 +3950,54 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"bs58 0.5.1",
|
||||
"bytes",
|
||||
"clap 4.5.4",
|
||||
"fastrand 2.1.0",
|
||||
"futures",
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-authenticator-requests",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-id",
|
||||
"nym-network-defaults",
|
||||
"nym-sdk",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"nym-sphinx",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-bandwidth-controller"
|
||||
version = "0.1.0"
|
||||
@@ -4018,7 +4057,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
@@ -4097,7 +4136,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -4282,7 +4321,7 @@ dependencies = [
|
||||
"ff",
|
||||
"getrandom 0.2.15",
|
||||
"group",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.12.1",
|
||||
"nym-dkg",
|
||||
"nym-pemstore",
|
||||
"rand 0.8.5",
|
||||
@@ -4506,7 +4545,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-gateway"
|
||||
version = "1.1.37"
|
||||
version = "1.1.36"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -4523,6 +4562,7 @@ dependencies = [
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-credentials",
|
||||
@@ -4537,7 +4577,6 @@ dependencies = [
|
||||
"nym-node-http-api",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
@@ -4633,6 +4672,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"http 1.1.0",
|
||||
"nym-bin-common",
|
||||
"reqwest 0.12.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -4805,7 +4845,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-mixnode"
|
||||
version = "1.1.38"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.7.5",
|
||||
@@ -4910,7 +4950,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.37"
|
||||
version = "1.1.38"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -4939,7 +4979,6 @@ dependencies = [
|
||||
"nym-socks5-proxy-helpers",
|
||||
"nym-socks5-requests",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"pretty_env_logger",
|
||||
@@ -4960,26 +4999,9 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-statistics"
|
||||
version = "1.1.35"
|
||||
dependencies = [
|
||||
"dirs 4.0.0",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.1.3"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
@@ -4991,6 +5013,7 @@ dependencies = [
|
||||
"cupid",
|
||||
"humantime-serde",
|
||||
"ipnetwork 0.16.0",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-client-core-config-types",
|
||||
"nym-config",
|
||||
@@ -5014,7 +5037,7 @@ dependencies = [
|
||||
"sysinfo 0.30.12",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml 0.8.12",
|
||||
"toml 0.8.14",
|
||||
"tracing",
|
||||
"url",
|
||||
"zeroize",
|
||||
@@ -5160,7 +5183,7 @@ dependencies = [
|
||||
"chacha20poly1305",
|
||||
"criterion",
|
||||
"curve25519-dalek 4.1.2",
|
||||
"fastrand 1.9.0",
|
||||
"fastrand 2.1.0",
|
||||
"getrandom 0.2.15",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
@@ -5241,7 +5264,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -5260,6 +5283,7 @@ dependencies = [
|
||||
"nym-socks5-client-core",
|
||||
"nym-sphinx",
|
||||
"nym-topology",
|
||||
"nym-validator-client",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -5505,20 +5529,6 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-statistics-common"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"log",
|
||||
"reqwest 0.12.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-store-cipher"
|
||||
version = "0.1.0"
|
||||
@@ -5593,7 +5603,7 @@ dependencies = [
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"hmac",
|
||||
"itertools 0.11.0",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
@@ -5632,7 +5642,7 @@ dependencies = [
|
||||
"eyre",
|
||||
"flate2",
|
||||
"futures",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-coconut",
|
||||
@@ -5767,7 +5777,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -7594,9 +7604,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.5"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -8616,21 +8626,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.12"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.12",
|
||||
"toml_edit 0.22.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -8650,9 +8660,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.12"
|
||||
version = "0.22.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
|
||||
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"serde",
|
||||
|
||||
+14
-7
@@ -20,6 +20,7 @@ members = [
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"common/authenticator-requests",
|
||||
"common/async-file-watcher",
|
||||
"common/bandwidth-controller",
|
||||
"common/bin-common",
|
||||
@@ -76,7 +77,6 @@ members = [
|
||||
"common/socks5-client-core",
|
||||
"common/socks5/proxy-helpers",
|
||||
"common/socks5/requests",
|
||||
"common/statistics",
|
||||
"common/store-cipher",
|
||||
"common/task",
|
||||
"common/topology",
|
||||
@@ -96,10 +96,10 @@ members = [
|
||||
"mixnode",
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"nym-api",
|
||||
"nym-browser-extension/storage",
|
||||
"nym-api/nym-api-requests",
|
||||
@@ -127,7 +127,6 @@ default-members = [
|
||||
"clients/socks5",
|
||||
"gateway",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"mixnode",
|
||||
"nym-api",
|
||||
"tools/nymvisor",
|
||||
@@ -140,9 +139,6 @@ exclude = [
|
||||
"explorer",
|
||||
"contracts",
|
||||
"nym-wallet",
|
||||
"nym-connect/mobile/src-tauri",
|
||||
"nym-connect/desktop",
|
||||
"nym-vpn/ui/src-tauri",
|
||||
"cpu-cycles",
|
||||
"sdk/ffi/cpp",
|
||||
]
|
||||
@@ -195,12 +191,15 @@ cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
dashmap = "5.5.3"
|
||||
defguard_wireguard_rs = "0.4.2"
|
||||
digest = "0.10.7"
|
||||
dirs = "4.0"
|
||||
doc-comment = "0.3"
|
||||
dotenvy = "0.15.6"
|
||||
ecdsa = "0.16"
|
||||
ed25519-dalek = "2.1"
|
||||
etherparse = "0.13.0"
|
||||
eyre = "0.6.9"
|
||||
fastrand = "2.1.0"
|
||||
flate2 = "1.0.28"
|
||||
futures = "0.3.28"
|
||||
generic-array = "0.14.7"
|
||||
@@ -212,14 +211,15 @@ hex = "0.4.3"
|
||||
hex-literal = "0.3.3"
|
||||
hkdf = "0.12.3"
|
||||
hmac = "0.12.1"
|
||||
http = "1"
|
||||
httpcodec = "0.2.3"
|
||||
humantime = "2.1.0"
|
||||
humantime-serde = "1.1.1"
|
||||
http = "1"
|
||||
hyper = "1.3.1"
|
||||
indexed_db_futures = "0.3.0"
|
||||
inquire = "0.6.2"
|
||||
ip_network = "0.4.1"
|
||||
ipnetwork = "0.16"
|
||||
isocountry = "0.3.2"
|
||||
k256 = "0.13"
|
||||
lazy_static = "1.4.0"
|
||||
@@ -242,6 +242,7 @@ publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
rand = "0.8.5"
|
||||
rand-07 = "0.7.3"
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha_02 = "0.2"
|
||||
rand_core = "0.6.3"
|
||||
rand_distr = "0.4"
|
||||
@@ -255,6 +256,7 @@ rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
safer-ffi = "0.1.4"
|
||||
schemars = "0.8.1"
|
||||
semver = "1.0.23"
|
||||
serde = "1.0.152"
|
||||
serde_bytes = "0.11.6"
|
||||
serde_derive = "1.0"
|
||||
@@ -262,12 +264,14 @@ serde_json = "1.0.91"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.4.0"
|
||||
serde_yaml = "0.9.25"
|
||||
sha2 = "0.10.8"
|
||||
si-scale = "0.2.2"
|
||||
sphinx-packet = "0.1.1"
|
||||
sqlx = "0.6.3"
|
||||
strum = "0.25"
|
||||
subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.30.12"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.40"
|
||||
tempfile = "3.5.0"
|
||||
@@ -278,6 +282,7 @@ tokio-stream = "0.1.14"
|
||||
tokio-test = "0.4.2"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.10"
|
||||
toml = "0.8.14"
|
||||
tower = "0.4.13"
|
||||
tower-http = "0.5.2"
|
||||
tracing = "0.1.37"
|
||||
@@ -292,6 +297,7 @@ utoipa-swagger-ui = "6.0.0"
|
||||
vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.36"
|
||||
x25519-dalek = "2.0.0"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
prometheus = { version = "0.13.0" }
|
||||
@@ -339,6 +345,7 @@ wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen-futures = "0.4.39"
|
||||
wasmtimer = "0.2.0"
|
||||
web-sys = "0.3.69"
|
||||
itertools = "0.12.0"
|
||||
|
||||
|
||||
# Profile settings for individual crates
|
||||
|
||||
@@ -92,7 +92,6 @@ endef
|
||||
$(eval $(call add_cargo_workspace,main,.))
|
||||
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown,RUSTFLAGS='-C link-arg=-s'))
|
||||
$(eval $(call add_cargo_workspace,wallet,nym-wallet))
|
||||
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# SDK
|
||||
|
||||
@@ -7,86 +7,66 @@ SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
The platform is composed of multiple Rust crates. Top-level executable binary crates include:
|
||||
|
||||
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* nym-socks5-client - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* nym-gateway - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices.
|
||||
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
* `nym-node` - a tool for running a node within the Nym network. Nym Nodes containing functionality such as `mixnode`, `entry-gateway` and `exit-gateway` are fundamental components of Nym Mixnet architecture. Nym Nodes are ran by decentralised node operators. Read more about `nym-node` in [Operators Guide documentation](https://nymtech.net/operators/nodes/nym-node.html). Network functionality of `nym-node` (labeled with `--mode` flag) can be:
|
||||
- `mixnode` - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
- `gateway` - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices. Gateways can be further categorized as `entry-gateway` and `exit-gateway`. The latter has an extra embedded IP packet router and Network requester to route data to the internet.
|
||||
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
<!-- coming soon
|
||||
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
-->
|
||||
|
||||
```ascii
|
||||
┌─►mix──┐ mix mix
|
||||
│ │
|
||||
Entry │ │ Exit
|
||||
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
|
||||
│ │
|
||||
│ │
|
||||
mix └─►mix──┘ mix
|
||||
|
||||
```
|
||||
|
||||
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
||||
|
||||
|
||||
### Building
|
||||
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/pre-built-binaries.html).
|
||||
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
|
||||
* Wallet build instructions are available on Nym [Technical docs](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
|
||||
### Developing
|
||||
|
||||
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
|
||||
There's a [`sandbox.env`](https://github.com/nymtech/nym/envs/sandbox.env) file provided which you can rename to `.env` if you want convenient testing environment. Read more about sandbox environment in our [Operators Guide page](https://nymtech.net/operators/sandbox.html).
|
||||
|
||||
For Typescript components, please see [ts-packages](./ts-packages).
|
||||
References for developers:
|
||||
|
||||
* [Developers Portal](https://nymtech.net/developers)
|
||||
* [Typescript SDKs](https://sdk.nymtech.net/)
|
||||
* [Technical Documentation - Nym network overview](https://nymtech.net/docs/)
|
||||
* [Release Cycle - git flow](https://nymtech.net/operators/release-cycle.html)
|
||||
|
||||
### Developer chat
|
||||
|
||||
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
|
||||
|
||||
You can chat to us in two places:
|
||||
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
|
||||
* The various developer channels on [Discord](https://discord.gg/nym)
|
||||
* The various developer channels on [Discord](https://nymtech.net/go/discord)
|
||||
|
||||
### Rewards
|
||||
### Tokenomics & Rewards
|
||||
|
||||
Node, node operator and delegator rewards are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf). Below is a TLDR of the variables and formulas involved in calculating the epoch rewards. Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
|Symbol|Definition|
|
||||
|---|---|
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R#gh-dark-mode-only">|global share of rewards available, starts at 2% of the reward pool.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}#gh-dark-mode-only">|node reward for mixnode `i`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\sigma_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma_{i}#gh-dark-mode-only">|ratio of total node stake (node bond + all delegations) to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda_{i}#gh-dark-mode-only">|ratio of stake operator has pledged to their node to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\omega_{i}#gh-dark-mode-only">|fraction of total effort undertaken by node `i`, set to `1/k`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=k#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}k#gh-dark-mode-only">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10%.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PF_{i}#gh-dark-mode-only">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs.
|
||||
|
||||
Node reward for node `i` is determined as:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-dark-mode-only">
|
||||
where:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-dark-mode-only">
|
||||
|
||||
and
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-dark-mode-only">
|
||||
|
||||
Operator of node `i` is credited with the following amount:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
|
||||
|
||||
Delegate with stake `s` receives:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
|
||||
|
||||
where `s'` is stake `s` scaled over total token circulating supply.
|
||||
Nym network economic incentives, operator and validator rewards, and scalability of the network are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf).
|
||||
Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
### Licensing and copyright information
|
||||
|
||||
This is a monorepo and components that make up Nym as a system are licensed individually, so for accurate information, please check individual files.
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
- applications and binaries are GPLv3
|
||||
- libraries and components are Apache 2.0 or MIT
|
||||
- documentation is Apache 2.0 or CC0-1.0
|
||||
|
||||
Again, for accurate information, please check individual files.
|
||||
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -23,7 +23,7 @@ url = { workspace = true }
|
||||
|
||||
bs58 = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dirs = "4.0"
|
||||
dirs = { workspace = true }
|
||||
log = { workspace = true } # self explanatory
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
|
||||
@@ -37,7 +37,7 @@ zeroize = { workspace = true }
|
||||
|
||||
## internal
|
||||
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
|
||||
+78
-236
@@ -744,6 +744,18 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.20.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
|
||||
@@ -862,51 +874,6 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chrome-trace-event": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||
@@ -1593,39 +1560,6 @@
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -1639,18 +1573,6 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
@@ -1683,6 +1605,18 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
@@ -2137,39 +2071,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -2183,18 +2084,6 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@@ -2361,6 +2250,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
@@ -3853,6 +3751,18 @@
|
||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
@@ -5213,6 +5123,15 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.20.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
|
||||
@@ -5283,41 +5202,6 @@
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"chrome-trace-event": {
|
||||
@@ -5852,30 +5736,6 @@
|
||||
"micromatch": "^4.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -5885,15 +5745,6 @@
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5926,6 +5777,15 @@
|
||||
"websocket-driver": ">=0.5.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
@@ -6247,30 +6107,6 @@
|
||||
"micromatch": "^4.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
@@ -6280,15 +6116,6 @@
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6407,6 +6234,12 @@
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
@@ -7524,6 +7357,15 @@
|
||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
|
||||
@@ -106,8 +106,10 @@ impl SocketClient {
|
||||
};
|
||||
|
||||
let storage = self.initialise_storage().await?;
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
|
||||
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client);
|
||||
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
|
||||
.with_user_agent(user_agent);
|
||||
|
||||
if let Some(custom_mixnet) = &self.custom_mixnet {
|
||||
base_client = base_client.with_stored_topology(custom_mixnet)?;
|
||||
|
||||
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliNativeClient, _>(args).await?;
|
||||
let res = add_gateway::<CliNativeClient, _>(args, Some(user_agent)).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
|
||||
@@ -114,8 +114,9 @@ impl Display for InitResults {
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = initialise_client::<CliNativeClient>(args).await?;
|
||||
let res = initialise_client::<CliNativeClient>(args, Some(user_agent)).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
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"
|
||||
@@ -25,17 +25,18 @@ zeroize = { workspace = true }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
nym-crypto = { path = "../../common/crypto" }
|
||||
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
|
||||
nym-pemstore = { path = "../../common/pemstore" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-socks5-client-core = { path = "../../common/socks5-client-core" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliSocks5Client, _>(args).await?;
|
||||
let res = add_gateway::<CliSocks5Client, _>(args, Some(user_agent)).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
|
||||
@@ -129,8 +129,9 @@ impl Display for InitResults {
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = initialise_client::<CliSocks5Client>(args).await?;
|
||||
let res = initialise_client::<CliSocks5Client>(args, Some(user_agent)).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
@@ -116,7 +116,13 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error +
|
||||
let storage =
|
||||
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
|
||||
.await?;
|
||||
NymClient::new(config.core, storage, args.common_args.custom_mixnet)
|
||||
.run_forever()
|
||||
.await
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
NymClient::new(
|
||||
config.core,
|
||||
storage,
|
||||
user_agent,
|
||||
args.common_args.custom_mixnet,
|
||||
)
|
||||
.run_forever()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-wireguard-types = { path = "../wireguard-types" }
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 1;
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
bincode::DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.with_varint_encoding()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
const VERSION: u8 = 1;
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::{GatewayClient, InitMessage};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
fn generate_random() -> u64 {
|
||||
use rand::RngCore;
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
rng.next_u64()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorRequest {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorRequestData,
|
||||
pub reply_to: Recipient,
|
||||
pub request_id: u64,
|
||||
}
|
||||
|
||||
impl AuthenticatorRequest {
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Initial(init_message),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_final_request(gateway_client: GatewayClient, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Final(gateway_client),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorRequestData {
|
||||
Initial(InitMessage),
|
||||
Final(GatewayClient),
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::registration::RegistrationData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorResponse {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorResponseData,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
|
||||
impl AuthenticatorResponse {
|
||||
pub fn new_pending_registration_success(
|
||||
registration_data: RegistrationData,
|
||||
request_id: u64,
|
||||
reply_to: Recipient,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
||||
reply: registration_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_registered(reply_to: Recipient, request_id: u64) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recipient(&self) -> Recipient {
|
||||
self.reply_to
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<u64> {
|
||||
match &self.data {
|
||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorResponseData {
|
||||
PendingRegistration(PendingRegistrationResponse),
|
||||
Registered(RegisteredResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PendingRegistrationResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistrationData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RegisteredResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
|
||||
// should have a new trait for TaskStatus messages
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BandwidthStatusMessage {
|
||||
#[error("remaining bandwidth: {0}")]
|
||||
RemainingBandwidth(i64),
|
||||
|
||||
#[error("no bandwidth left")]
|
||||
NoBandwidth,
|
||||
}
|
||||
@@ -14,8 +14,11 @@ use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
|
||||
pub use event::BandwidthStatusMessage;
|
||||
|
||||
pub mod acquire;
|
||||
pub mod error;
|
||||
mod event;
|
||||
mod utils;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -9,9 +9,9 @@ repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
const-str = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = { workspace = true }
|
||||
clap_complete_fig = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"], optional = true }
|
||||
clap_complete = { workspace = true, optional = true }
|
||||
clap_complete_fig = { workspace = true, optional = true }
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = { workspace = true }
|
||||
semver = "0.11"
|
||||
@@ -34,7 +34,7 @@ vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "carg
|
||||
[features]
|
||||
default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
basic_tracing = ["tracing-subscriber"]
|
||||
tracing = [
|
||||
@@ -44,3 +44,4 @@ tracing = [
|
||||
"tracing-opentelemetry",
|
||||
"opentelemetry",
|
||||
]
|
||||
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
|
||||
|
||||
@@ -44,6 +44,10 @@ pub struct BinaryBuildInformation {
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
|
||||
pub cargo_profile: &'static str,
|
||||
|
||||
// VERGEN_CARGO_TARGET_TRIPLE
|
||||
/// Provides the cargo target triple that was used for the build.
|
||||
pub cargo_triple: &'static str,
|
||||
}
|
||||
|
||||
impl BinaryBuildInformation {
|
||||
@@ -66,6 +70,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_profile,
|
||||
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +100,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_profile,
|
||||
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +115,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: self.rustc_version.to_owned(),
|
||||
rustc_channel: self.rustc_channel.to_owned(),
|
||||
cargo_profile: self.cargo_profile.to_owned(),
|
||||
cargo_triple: self.cargo_triple.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +163,15 @@ pub struct BinaryBuildInformationOwned {
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
|
||||
pub cargo_profile: String,
|
||||
|
||||
// VERGEN_CARGO_TARGET_TRIPLE
|
||||
/// Provides the cargo target triple that was used for the build.
|
||||
#[serde(default = "unknown")]
|
||||
pub cargo_triple: String,
|
||||
}
|
||||
|
||||
fn unknown() -> String {
|
||||
"unknown".to_string()
|
||||
}
|
||||
|
||||
impl Display for BinaryBuildInformationOwned {
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod build_information;
|
||||
pub mod completions;
|
||||
pub mod logging;
|
||||
pub mod version_checker;
|
||||
|
||||
#[cfg(feature = "clap")]
|
||||
pub mod completions;
|
||||
|
||||
#[cfg(feature = "output_format")]
|
||||
pub mod output_format;
|
||||
|
||||
@@ -10,7 +10,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
base64 = "0.21.2"
|
||||
base64 = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
clap = { workspace = true, optional = true }
|
||||
@@ -20,7 +20,7 @@ log = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = "0.10.6"
|
||||
sha2 = { workspace = true }
|
||||
si-scale = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -16,6 +16,7 @@ use log::info;
|
||||
use nym_client_core_gateways_storage::GatewayDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::UserAgent;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
@@ -60,7 +61,10 @@ pub struct CommonClientAddGatewayArgs {
|
||||
pub custom_mixnet: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub async fn add_gateway<C, A>(args: A) -> Result<GatewayInfo, C::Error>
|
||||
pub async fn add_gateway<C, A>(
|
||||
args: A,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<GatewayInfo, C::Error>
|
||||
where
|
||||
A: AsRef<CommonClientAddGatewayArgs>,
|
||||
C: CliClient,
|
||||
@@ -111,7 +115,8 @@ where
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
|
||||
.await?
|
||||
};
|
||||
|
||||
// since we're registering with a brand new gateway,
|
||||
|
||||
@@ -16,6 +16,7 @@ use log::info;
|
||||
use nym_client_core_gateways_storage::GatewayDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::rngs::OsRng;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -96,6 +97,7 @@ pub struct InitResultsWithConfig<T> {
|
||||
|
||||
pub async fn initialise_client<C>(
|
||||
init_args: C::InitArgs,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<InitResultsWithConfig<C::Config>, C::Error>
|
||||
where
|
||||
C: InitialisableClient,
|
||||
@@ -163,7 +165,8 @@ where
|
||||
hardcoded_topology.get_gateways()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
|
||||
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
|
||||
.await?
|
||||
};
|
||||
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
|
||||
@@ -53,7 +53,7 @@ use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender,
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::HardcodedTopologyProvider;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
|
||||
use rand::rngs::OsRng;
|
||||
use std::fmt::Debug;
|
||||
use std::os::raw::c_int as RawFd;
|
||||
@@ -184,6 +184,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
|
||||
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
shutdown: Option<TaskClient>,
|
||||
user_agent: Option<UserAgent>,
|
||||
|
||||
setup_method: GatewaySetup,
|
||||
}
|
||||
@@ -207,6 +208,7 @@ where
|
||||
custom_topology_provider: None,
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
user_agent: None,
|
||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||
}
|
||||
}
|
||||
@@ -250,6 +252,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
|
||||
self.user_agent = Some(user_agent);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_stored_topology<P: AsRef<Path>>(
|
||||
mut self,
|
||||
file: P,
|
||||
@@ -467,6 +475,7 @@ where
|
||||
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
config_topology: config::Topology,
|
||||
nym_api_urls: Vec<Url>,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||
// if no custom provider was ... provided ..., create one using nym-api
|
||||
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
|
||||
@@ -477,6 +486,7 @@ where
|
||||
},
|
||||
nym_api_urls,
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
user_agent,
|
||||
)),
|
||||
config::TopologyStructure::GeoAware(group_by) => {
|
||||
Box::new(GeoAwareTopologyProvider::new(
|
||||
@@ -689,6 +699,7 @@ where
|
||||
self.custom_topology_provider.take(),
|
||||
self.config.debug.topology,
|
||||
self.config.get_nym_api_endpoints(),
|
||||
self.user_agent.clone(),
|
||||
);
|
||||
|
||||
// needs to be started as the first thing to block if required waiting for the gateway
|
||||
|
||||
@@ -5,6 +5,7 @@ use async_trait::async_trait;
|
||||
use log::{debug, error, warn};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::{NymTopology, NymTopologyError};
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
@@ -39,14 +40,26 @@ pub(crate) struct NymApiTopologyProvider {
|
||||
}
|
||||
|
||||
impl NymApiTopologyProvider {
|
||||
pub(crate) fn new(config: Config, mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
|
||||
pub(crate) fn new(
|
||||
config: Config,
|
||||
mut nym_api_urls: Vec<Url>,
|
||||
client_version: String,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Self {
|
||||
nym_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
let validator_client = if let Some(user_agent) = user_agent {
|
||||
nym_validator_client::client::NymApiClient::new_with_user_agent(
|
||||
nym_api_urls[0].clone(),
|
||||
user_agent,
|
||||
)
|
||||
} else {
|
||||
nym_validator_client::client::NymApiClient::new(nym_api_urls[0].clone())
|
||||
};
|
||||
|
||||
NymApiTopologyProvider {
|
||||
config,
|
||||
validator_client: nym_validator_client::client::NymApiClient::new(
|
||||
nym_api_urls[0].clone(),
|
||||
),
|
||||
validator_client,
|
||||
nym_api_urls,
|
||||
client_version,
|
||||
currently_used_api: 0,
|
||||
|
||||
@@ -9,6 +9,7 @@ use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_topology::{filter::VersionFilterable, gateway, mix};
|
||||
use nym_validator_client::client::IdentityKeyRef;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tungstenite::Message;
|
||||
@@ -59,11 +60,16 @@ impl<'a> GatewayWithLatency<'a> {
|
||||
pub async fn current_gateways<R: Rng>(
|
||||
rng: &mut R,
|
||||
nym_apis: &[Url],
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<Vec<gateway::Node>, ClientCoreError> {
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
let client = nym_validator_client::client::NymApiClient::new(nym_api.clone());
|
||||
let client = if let Some(user_agent) = user_agent {
|
||||
nym_validator_client::client::NymApiClient::new_with_user_agent(nym_api.clone(), user_agent)
|
||||
} else {
|
||||
nym_validator_client::client::NymApiClient::new(nym_api.clone())
|
||||
};
|
||||
|
||||
log::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::traits::GatewayPacketRouter;
|
||||
use crate::{cleanup_socket_message, try_decrypt_binary_message};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage};
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_credentials::CredentialSpendingData;
|
||||
@@ -105,8 +105,8 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
|
||||
// currently unused (but populated)
|
||||
negotiated_protocol: Option<u8>,
|
||||
|
||||
/// Listen to shutdown messages.
|
||||
shutdown: TaskClient,
|
||||
/// Listen to shutdown messages and send notifications back to the task manager
|
||||
task_client: TaskClient,
|
||||
}
|
||||
|
||||
impl<C, St> GatewayClient<C, St> {
|
||||
@@ -117,7 +117,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
shared_key: Option<Arc<SharedKeys>>,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
shutdown: TaskClient,
|
||||
task_client: TaskClient,
|
||||
) -> Self {
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -135,7 +135,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.shutdown.recv() => {
|
||||
_ = self.task_client.recv() => {
|
||||
log::trace!("GatewayClient control response: Received shutdown");
|
||||
log::debug!("GatewayClient control response: Exiting");
|
||||
break Err(GatewayClientError::ConnectionClosedGatewayShutdown);
|
||||
@@ -540,6 +540,9 @@ impl<C, St> GatewayClient<C, St> {
|
||||
self.bandwidth_remaining = bandwidth_remaining;
|
||||
self.negotiated_protocol = protocol_version;
|
||||
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
|
||||
self.task_client.send_status_msg(Box::new(
|
||||
BandwidthStatusMessage::RemainingBandwidth(bandwidth_remaining),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
|
||||
@@ -805,7 +808,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
),
|
||||
self.shutdown.clone(),
|
||||
self.task_client.clone(),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -879,8 +882,8 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
// perfectly fine here, because it's not meant to be used
|
||||
let (ack_tx, _) = mpsc::unbounded();
|
||||
let (mix_tx, _) = mpsc::unbounded();
|
||||
let shutdown = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
|
||||
let task_client = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, task_client.clone());
|
||||
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -898,7 +901,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,7 +909,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
self,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
shutdown: TaskClient,
|
||||
task_client: TaskClient,
|
||||
) -> GatewayClient<C, St> {
|
||||
// invariants that can't be broken
|
||||
// (unless somebody decided to expose some field that wasn't meant to be exposed)
|
||||
@@ -930,7 +933,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: self.reconnection_attempts,
|
||||
reconnection_backoff: self.reconnection_backoff,
|
||||
negotiated_protocol: self.negotiated_protocol,
|
||||
shutdown,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ cw-controllers = { workspace = true }
|
||||
prost = { workspace = true, default-features = false }
|
||||
flate2 = { workspace = true }
|
||||
sha2 = { version = "0.9.5" }
|
||||
itertools = { version = "0.10" }
|
||||
itertools = { workspace = true }
|
||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
cosmwasm-std = { workspace = true }
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ use nym_api_requests::models::{
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
use nym_http_api_client::UserAgent;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use url::Url;
|
||||
|
||||
@@ -258,6 +259,16 @@ impl NymApiClient {
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
|
||||
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
|
||||
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
|
||||
.expect("invalid api url")
|
||||
.with_user_agent(user_agent)
|
||||
.build::<ValidatorClientError>()
|
||||
.expect("failed to build nym api client");
|
||||
|
||||
NymApiClient { nym_api }
|
||||
}
|
||||
|
||||
pub fn api_url(&self) -> &Url {
|
||||
self.nym_api.current_url()
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ pub use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
||||
pub use client::NymApiClient;
|
||||
pub use client::{Client, CoconutApiClient, Config};
|
||||
pub use nym_api_requests::*;
|
||||
pub use nym_http_api_client::UserAgent;
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
pub use cosmrs::rpc::HttpClient as HttpRpcClient;
|
||||
|
||||
+27
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client_traits::CosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
|
||||
use crate::nyxd::cosmwasm_client::logs::{self, parse_raw_logs};
|
||||
use crate::nyxd::cosmwasm_client::logs::parse_raw_logs;
|
||||
use crate::nyxd::cosmwasm_client::types::*;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
@@ -19,6 +19,7 @@ use cosmrs::feegrant::{
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tendermint::abci::{Event, EventAttribute};
|
||||
use cosmrs::tx::{self, Msg};
|
||||
use cosmrs::{cosmwasm, AccountId, Any, Tx};
|
||||
use log::debug;
|
||||
@@ -51,6 +52,20 @@ fn single_unspecified_signer_auth(
|
||||
}
|
||||
.auth_info(empty_fee())
|
||||
}
|
||||
// Searches in events for an event of the given event type which contains an
|
||||
// attribute for with the given key.
|
||||
fn find_attribute<'a>(
|
||||
events: &'a [Event],
|
||||
event_type: &str,
|
||||
attr_key: &str,
|
||||
) -> Option<&'a EventAttribute> {
|
||||
events
|
||||
.iter()
|
||||
.find(|attr| attr.kind == event_type)?
|
||||
.attributes
|
||||
.iter()
|
||||
.find(|attr| attr.key == attr_key)
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -118,6 +133,7 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -127,7 +143,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or code_id is not a number, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let code_id = logs::find_attribute(&logs, "store_code", "code_id")
|
||||
let code_id = find_attribute(&events, "store_code", "code_id")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -140,6 +156,7 @@ where
|
||||
compressed_checksum,
|
||||
code_id,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -182,6 +199,7 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -190,7 +208,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or address is malformed, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let contract_address = logs::find_attribute(&logs, "instantiate", "_contract_address")
|
||||
let contract_address = find_attribute(&events, "instantiate", "_contract_address")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -199,6 +217,7 @@ where
|
||||
Ok(InstantiateResult {
|
||||
contract_address,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -231,6 +250,7 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -261,6 +281,7 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -298,6 +319,7 @@ where
|
||||
};
|
||||
Ok(MigrateResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -335,6 +357,7 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
@@ -378,6 +401,7 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
|
||||
@@ -9,16 +9,12 @@ pub use nym_coconut_bandwidth_contract_common::event_attributes::*;
|
||||
pub use nym_coconut_dkg_common::event_attributes::*;
|
||||
|
||||
// it seems that currently validators just emit stringified events (which are also returned as part of deliverTx response)
|
||||
// as theirs logs
|
||||
// as their logs
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Log {
|
||||
#[serde(default)]
|
||||
// weird thing is that the first msg_index seems to always be undefined on the raw logs
|
||||
pub msg_index: usize,
|
||||
// unless I'm missing something obvious, the "log" type in cosmjs is always an empty string
|
||||
// and launchpad cosmos validator was setting it to what essentially is just the raw version of what
|
||||
// we received (and we don't care about launchpad, we, as the time of writing this, work on the stargate)
|
||||
// log: String,
|
||||
pub events: Vec<cosmwasm_std::Event>,
|
||||
}
|
||||
|
||||
@@ -37,8 +33,13 @@ pub fn find_attribute<'a>(
|
||||
.find(|attr| attr.key == attribute_key)
|
||||
}
|
||||
|
||||
// those two functions were separated so that the internal logic could actually be tested
|
||||
// these two functions were separated so that the internal logic could actually be tested
|
||||
fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
|
||||
// From Cosmos SDK > 0.50 onwards, log field is not populated
|
||||
if raw.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let logs: Vec<Log> = serde_json::from_str(raw).map_err(|_| NyxdError::MalformedLogString)?;
|
||||
if logs.len() != logs.iter().unique_by(|log| log.msg_index).count() {
|
||||
// this check is only here because I don't yet fully understand raw log string generation and
|
||||
|
||||
@@ -232,6 +232,8 @@ pub struct UploadResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -269,6 +271,8 @@ pub struct InstantiateResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -279,6 +283,8 @@ pub struct InstantiateResult {
|
||||
pub struct ChangeAdminResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -289,6 +295,8 @@ pub struct ChangeAdminResult {
|
||||
pub struct MigrateResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -301,6 +309,8 @@ pub struct ExecuteResult {
|
||||
|
||||
pub data: Vec<u8>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use log::{debug, info};
|
||||
|
||||
use cosmwasm_std::Decimal;
|
||||
use nym_mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use log::{debug, info};
|
||||
use nym_mixnet_contract_common::{
|
||||
InitialRewardingParams, InstantiateMsg, OperatingCostRange, Percent, ProfitMarginRange,
|
||||
};
|
||||
use nym_network_defaults::mainnet::MIX_DENOM;
|
||||
use nym_network_defaults::TOTAL_SUPPLY;
|
||||
use nym_validator_client::nyxd::{AccountId, Coin};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn default_maximum_operating_cost() -> Coin {
|
||||
Coin::new(TOTAL_SUPPLY, MIX_DENOM.base)
|
||||
}
|
||||
|
||||
pub fn default_minimum_operating_cost() -> Coin {
|
||||
Coin::new(0, MIX_DENOM.base)
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
@@ -50,6 +61,18 @@ pub struct Args {
|
||||
|
||||
#[clap(long, default_value_t = 240)]
|
||||
pub active_set_size: u32,
|
||||
|
||||
#[clap(long, default_value_t = Percent::zero())]
|
||||
pub minimum_profit_margin_percent: Percent,
|
||||
|
||||
#[clap(long, default_value_t = Percent::hundred())]
|
||||
pub maximum_profit_margin_percent: Percent,
|
||||
|
||||
#[clap(long, default_value_t = default_minimum_operating_cost())]
|
||||
pub minimum_interval_operating_cost: Coin,
|
||||
|
||||
#[clap(long, default_value_t = default_maximum_operating_cost())]
|
||||
pub maximum_interval_operating_cost: Coin,
|
||||
}
|
||||
|
||||
pub async fn generate(args: Args) {
|
||||
@@ -97,6 +120,10 @@ pub async fn generate(args: Args) {
|
||||
.expect("Rewarding (mix) denom has to be set")
|
||||
});
|
||||
|
||||
if args.minimum_interval_operating_cost.denom != args.maximum_interval_operating_cost.denom {
|
||||
panic!("different denoms for operating cost bounds")
|
||||
}
|
||||
|
||||
let instantiate_msg = InstantiateMsg {
|
||||
rewarding_validator_address: rewarding_validator_address.to_string(),
|
||||
vesting_contract_address: vesting_contract_address.to_string(),
|
||||
@@ -104,6 +131,14 @@ pub async fn generate(args: Args) {
|
||||
epochs_in_interval: args.epochs_in_interval,
|
||||
epoch_duration: Duration::from_secs(args.epoch_duration),
|
||||
initial_rewarding_params,
|
||||
profit_margin: ProfitMarginRange {
|
||||
minimum: args.minimum_profit_margin_percent,
|
||||
maximum: args.maximum_profit_margin_percent,
|
||||
},
|
||||
interval_operating_cost: OperatingCostRange {
|
||||
minimum: args.minimum_interval_operating_cost.amount.into(),
|
||||
maximum: args.maximum_interval_operating_cost.amount.into(),
|
||||
},
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
@@ -29,7 +29,7 @@ time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
time = { workspace = true, features = ["serde", "macros"] }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{EpochEventId, EpochState, IdentityKey, MixId};
|
||||
use crate::{EpochEventId, EpochState, IdentityKey, MixId, OperatingCostRange, ProfitMarginRange};
|
||||
use contracts_common::signing::verifier::ApiVerifierError;
|
||||
use contracts_common::Percent;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -239,6 +240,19 @@ pub enum MixnetContractError {
|
||||
#[from]
|
||||
source: ApiVerifierError,
|
||||
},
|
||||
|
||||
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
|
||||
ProfitMarginOutsideRange {
|
||||
provided: Percent,
|
||||
range: ProfitMarginRange,
|
||||
},
|
||||
|
||||
#[error("the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}")]
|
||||
OperatingCostOutsideRange {
|
||||
denom: String,
|
||||
provided: Uint128,
|
||||
range: OperatingCostRange,
|
||||
},
|
||||
}
|
||||
|
||||
impl MixnetContractError {
|
||||
|
||||
@@ -10,7 +10,10 @@ use crate::helpers::IntoBaseDecimal;
|
||||
use crate::reward_params::{NodeRewardParams, RewardingParams};
|
||||
use crate::rewarding::helpers::truncate_reward;
|
||||
use crate::rewarding::RewardDistribution;
|
||||
use crate::{Delegation, EpochEventId, EpochId, IdentityKey, MixId, Percent, SphinxKey};
|
||||
use crate::{
|
||||
Delegation, EpochEventId, EpochId, IdentityKey, MixId, OperatingCostRange, Percent,
|
||||
ProfitMarginRange, SphinxKey,
|
||||
};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, StdResult, Uint128};
|
||||
use schemars::JsonSchema;
|
||||
@@ -152,6 +155,16 @@ impl MixNodeRewarding {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn normalise_profit_margin(&mut self, allowed_range: ProfitMarginRange) {
|
||||
self.cost_params.profit_margin_percent =
|
||||
allowed_range.normalise(self.cost_params.profit_margin_percent)
|
||||
}
|
||||
|
||||
pub fn normalise_operating_cost(&mut self, allowed_range: OperatingCostRange) {
|
||||
self.cost_params.interval_operating_cost.amount =
|
||||
allowed_range.normalise(self.cost_params.interval_operating_cost.amount)
|
||||
}
|
||||
|
||||
/// Determines whether this node is still bonded. This is performed via a simple check,
|
||||
/// if there are no tokens left associated with the operator, it means they have unbonded
|
||||
/// and those params only exist for the purposes of calculating rewards for delegators that
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::delegation::{self, OwnerProxySubKey};
|
||||
@@ -12,6 +12,7 @@ use crate::reward_params::{
|
||||
IntervalRewardParams, IntervalRewardingParamsUpdate, Performance, RewardingParams,
|
||||
};
|
||||
use crate::types::{ContractStateParams, LayerAssignment, MixId};
|
||||
use crate::{OperatingCostRange, ProfitMarginRange};
|
||||
use contracts_common::{signing::MessageSignature, IdentityKey, Percent};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Coin, Decimal};
|
||||
@@ -57,6 +58,12 @@ pub struct InstantiateMsg {
|
||||
pub epochs_in_interval: u32,
|
||||
pub epoch_duration: Duration,
|
||||
pub initial_rewarding_params: InitialRewardingParams,
|
||||
|
||||
#[serde(default)]
|
||||
pub profit_margin: ProfitMarginRange,
|
||||
|
||||
#[serde(default)]
|
||||
pub interval_operating_cost: OperatingCostRange,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
use crate::error::MixnetContractError;
|
||||
use crate::Layer;
|
||||
use contracts_common::Percent;
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
use cosmwasm_std::Coin;
|
||||
use cosmwasm_std::{Addr, Uint128};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::Index;
|
||||
|
||||
// type aliases for better reasoning about available data
|
||||
@@ -15,6 +17,65 @@ pub type SphinxKeyRef<'a> = &'a str;
|
||||
pub type MixId = u32;
|
||||
pub type BlockHeight = u64;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct RangedValue<T> {
|
||||
pub minimum: T,
|
||||
pub maximum: T,
|
||||
}
|
||||
|
||||
impl<T> Copy for RangedValue<T> where T: Copy {}
|
||||
|
||||
pub type ProfitMarginRange = RangedValue<Percent>;
|
||||
pub type OperatingCostRange = RangedValue<Uint128>;
|
||||
|
||||
impl<T> Display for RangedValue<T>
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} - {}", self.minimum, self.maximum)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ProfitMarginRange {
|
||||
fn default() -> Self {
|
||||
ProfitMarginRange {
|
||||
minimum: Percent::zero(),
|
||||
maximum: Percent::hundred(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OperatingCostRange {
|
||||
fn default() -> Self {
|
||||
OperatingCostRange {
|
||||
minimum: Uint128::zero(),
|
||||
|
||||
// 1 billion (native tokens, i.e. 1 billion * 1'000'000 base tokens) - the total supply
|
||||
maximum: Uint128::new(1_000_000_000_000_000),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RangedValue<T>
|
||||
where
|
||||
T: Copy + PartialOrd + PartialEq,
|
||||
{
|
||||
pub fn normalise(&self, value: T) -> T {
|
||||
if value < self.minimum {
|
||||
self.minimum
|
||||
} else if value > self.maximum {
|
||||
self.maximum
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn within_range(&self, value: T) -> bool {
|
||||
value >= self.minimum && value <= self.maximum
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies layer assignment for the given mixnode.
|
||||
#[cw_serde]
|
||||
pub struct LayerAssignment {
|
||||
@@ -154,4 +215,14 @@ pub struct ContractStateParams {
|
||||
|
||||
/// Minimum amount a gateway must pledge to get into the system.
|
||||
pub minimum_gateway_pledge: Coin,
|
||||
|
||||
/// Defines the allowed profit margin range of operators.
|
||||
/// default: 0% - 100%
|
||||
#[serde(default)]
|
||||
pub profit_margin: ProfitMarginRange,
|
||||
|
||||
/// Defines the allowed interval operating cost range of operators.
|
||||
/// default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)
|
||||
#[serde(default)]
|
||||
pub interval_operating_cost: OperatingCostRange,
|
||||
}
|
||||
|
||||
@@ -12,16 +12,16 @@ aes = { workspace = true, optional = true }
|
||||
bs58 = { workspace = true }
|
||||
blake3 = { workspace = true, features = ["traits-preview"], optional = true }
|
||||
ctr = { workspace = true, optional = true }
|
||||
digest = { version = "0.10.3", optional = true }
|
||||
digest = { workspace = true, optional = true }
|
||||
generic-array = { workspace = true, optional = true }
|
||||
hkdf = { workspace = true, optional = true }
|
||||
hmac = { workspace = true, optional = true }
|
||||
cipher = { workspace = true, optional = true }
|
||||
x25519-dalek = { version = "2.0", optional = true, features = ["static_secrets"]}
|
||||
ed25519-dalek = { version = "2.1", features = ["rand_core"], optional = true }
|
||||
x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true }
|
||||
ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true }
|
||||
rand = { workspace = true, optional = true }
|
||||
serde_bytes = { version = "0.11.6", optional = true }
|
||||
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
|
||||
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
|
||||
subtle-encoding = { workspace = true, features = ["bech32-preview"] }
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
|
||||
@@ -31,7 +31,7 @@ nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0", default-fea
|
||||
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["sphinx"]
|
||||
|
||||
@@ -19,7 +19,7 @@ bs58 = { workspace = true }
|
||||
|
||||
lazy_static = { workspace = true }
|
||||
rand = { version = "0.8.5", default-features = false}
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
rand_core = { workspace = true }
|
||||
sha2 = "0.9"
|
||||
serde = { workspace = true }
|
||||
|
||||
@@ -20,6 +20,8 @@ serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
|
||||
# for request timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
|
||||
workspace = true
|
||||
|
||||
@@ -14,6 +14,10 @@ use url::Url;
|
||||
|
||||
pub use reqwest::IntoUrl;
|
||||
|
||||
pub use user_agent::UserAgent;
|
||||
|
||||
mod user_agent;
|
||||
|
||||
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
pub type PathSegments<'a> = &'a [&'a str];
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use http::HeaderValue;
|
||||
use nym_bin_common::build_information::{BinaryBuildInformation, BinaryBuildInformationOwned};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UserAgent {
|
||||
pub application: String,
|
||||
pub version: String,
|
||||
pub platform: String,
|
||||
pub git_commit: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for UserAgent {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let abbreviated_commit = self.git_commit.chars().take(7).collect::<String>();
|
||||
write!(
|
||||
f,
|
||||
"{}/{}/{}/{}",
|
||||
self.application, self.version, self.platform, abbreviated_commit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<UserAgent> for HeaderValue {
|
||||
type Error = http::header::InvalidHeaderValue;
|
||||
|
||||
fn try_from(user_agent: UserAgent) -> Result<Self, Self::Error> {
|
||||
HeaderValue::from_str(&user_agent.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BinaryBuildInformation> for UserAgent {
|
||||
fn from(build_info: BinaryBuildInformation) -> Self {
|
||||
UserAgent {
|
||||
application: build_info.binary_name.to_string(),
|
||||
version: build_info.build_version.to_string(),
|
||||
platform: build_info.cargo_triple.to_string(),
|
||||
git_commit: build_info.commit_sha.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BinaryBuildInformationOwned> for UserAgent {
|
||||
fn from(build_info: BinaryBuildInformationOwned) -> Self {
|
||||
UserAgent {
|
||||
application: build_info.binary_name,
|
||||
version: build_info.build_version,
|
||||
platform: build_info.cargo_triple,
|
||||
git_commit: build_info.commit_sha,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ bytes = { workspace = true }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
rand = "0.8.5"
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
|
||||
@@ -27,7 +27,6 @@ pub const COCONUT_DKG_CONTRACT_ADDRESS: &str =
|
||||
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
|
||||
|
||||
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
|
||||
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
|
||||
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
|
||||
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
|
||||
@@ -110,10 +109,6 @@ pub fn export_to_env() {
|
||||
var_names::REWARDING_VALIDATOR_ADDRESS,
|
||||
REWARDING_VALIDATOR_ADDRESS,
|
||||
);
|
||||
set_var_to_default(
|
||||
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
);
|
||||
set_var_to_default(var_names::NYXD, NYXD_URL);
|
||||
set_var_to_default(var_names::NYM_API, NYM_API);
|
||||
set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
|
||||
@@ -155,10 +150,6 @@ pub fn export_to_env_if_not_set() {
|
||||
var_names::REWARDING_VALIDATOR_ADDRESS,
|
||||
REWARDING_VALIDATOR_ADDRESS,
|
||||
);
|
||||
set_var_conditionally_to_default(
|
||||
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
);
|
||||
set_var_conditionally_to_default(var_names::NYXD, NYXD_URL);
|
||||
set_var_conditionally_to_default(var_names::NYM_API, NYM_API);
|
||||
set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
|
||||
|
||||
@@ -19,7 +19,6 @@ pub const GROUP_CONTRACT_ADDRESS: &str = "GROUP_CONTRACT_ADDRESS";
|
||||
pub const MULTISIG_CONTRACT_ADDRESS: &str = "MULTISIG_CONTRACT_ADDRESS";
|
||||
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "COCONUT_DKG_CONTRACT_ADDRESS";
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "REWARDING_VALIDATOR_ADDRESS";
|
||||
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "STATISTICS_SERVICE_DOMAIN_ADDRESS";
|
||||
pub const NYXD: &str = "NYXD";
|
||||
pub const NYM_API: &str = "NYM_API";
|
||||
pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
|
||||
|
||||
@@ -6,6 +6,7 @@ use nym_credential_storage::models::StorableIssuedCredential;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::coconut::bandwidth::issued::BandwidthCredentialIssuedDataVariant;
|
||||
use nym_credentials::IssuedBandwidthCredential;
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{debug, warn};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
@@ -13,7 +14,7 @@ pub async fn import_credential<S>(
|
||||
credentials_store: S,
|
||||
raw_credential: Vec<u8>,
|
||||
credential_version: impl Into<Option<u8>>,
|
||||
) -> Result<(), NymIdError>
|
||||
) -> Result<Option<OffsetDateTime>, NymIdError>
|
||||
where
|
||||
S: Storage,
|
||||
<S as Storage>::StorageError: Send + Sync + 'static,
|
||||
@@ -29,9 +30,10 @@ where
|
||||
credential.typ()
|
||||
);
|
||||
|
||||
match credential.variant_data() {
|
||||
let expiry_date = match credential.variant_data() {
|
||||
BandwidthCredentialIssuedDataVariant::Voucher(voucher_info) => {
|
||||
debug!("with value of {}", voucher_info.value())
|
||||
debug!("with value of {}", voucher_info.value());
|
||||
None
|
||||
}
|
||||
BandwidthCredentialIssuedDataVariant::FreePass(freepass_info) => {
|
||||
debug!("with expiry at {}", freepass_info.expiry_date());
|
||||
@@ -42,9 +44,11 @@ where
|
||||
return Err(NymIdError::ExpiredCredentialImport {
|
||||
expiration: freepass_info.expiry_date(),
|
||||
});
|
||||
} else {
|
||||
Some(freepass_info.expiry_date())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// SAFETY:
|
||||
// for the epoch to run over u32::MAX, we'd have to advance it for few centuries every block...
|
||||
@@ -67,5 +71,5 @@ where
|
||||
.map_err(|source| NymIdError::StorageError {
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
Ok(())
|
||||
Ok(expiry_date)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] }
|
||||
itertools = "0.10"
|
||||
itertools = { workspace = true }
|
||||
digest = "0.9"
|
||||
rand = "0.8"
|
||||
thiserror = { workspace = true }
|
||||
@@ -33,7 +33,7 @@ default-features = false
|
||||
[dev-dependencies]
|
||||
criterion = { workspace = true, features = ["html_reports"] }
|
||||
doc-comment = { workspace = true }
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
[[bench]]
|
||||
name = "benchmarks"
|
||||
|
||||
@@ -9,7 +9,7 @@ repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
rand = { workspace = true }
|
||||
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
|
||||
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
|
||||
generic-array = { workspace = true, optional = true, features = ["serde"] }
|
||||
thiserror = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
@@ -24,4 +24,4 @@ nym-topology = { path = "../../topology" }
|
||||
version = "0.2.83"
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
@@ -17,7 +17,7 @@ cosmrs.workspace = true
|
||||
eyre = { workspace = true }
|
||||
futures.workspace = true
|
||||
humantime = { workspace = true }
|
||||
sha2 = "0.10.8"
|
||||
sha2 = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"] }
|
||||
tendermint.workspace = true
|
||||
|
||||
@@ -8,7 +8,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
dirs = "4.0"
|
||||
dirs = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
pin-project = { workspace = true }
|
||||
|
||||
@@ -27,6 +27,7 @@ use nym_task::manager::TaskStatus;
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use nym_validator_client::UserAgent;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -61,6 +62,8 @@ pub struct NymClient<S> {
|
||||
|
||||
setup_method: GatewaySetup,
|
||||
|
||||
user_agent: UserAgent,
|
||||
|
||||
/// Optional path to a .json file containing standalone network details.
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
}
|
||||
@@ -74,11 +77,17 @@ where
|
||||
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
|
||||
{
|
||||
pub fn new(config: Config, storage: S, custom_mixnet: Option<PathBuf>) -> Self {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
storage: S,
|
||||
user_agent: UserAgent,
|
||||
custom_mixnet: Option<PathBuf>,
|
||||
) -> Self {
|
||||
NymClient {
|
||||
config,
|
||||
storage,
|
||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||
user_agent,
|
||||
custom_mixnet,
|
||||
}
|
||||
}
|
||||
@@ -226,7 +235,8 @@ where
|
||||
|
||||
let mut base_builder =
|
||||
BaseClientBuilder::new(&self.config.base, self.storage, dkg_query_client)
|
||||
.with_gateway_setup(self.setup_method);
|
||||
.with_gateway_setup(self.setup_method)
|
||||
.with_user_agent(self.user_agent);
|
||||
|
||||
if let Some(custom_mixnet) = &self.custom_mixnet {
|
||||
base_builder = base_builder.with_stored_topology(custom_mixnet)?;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[package]
|
||||
name = "nym-statistics-common"
|
||||
version = "1.0.1"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
log = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"]}
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["time"] }
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::StatsError;
|
||||
use crate::StatsMessage;
|
||||
|
||||
pub const DEFAULT_STATISTICS_SERVICE_ADDRESS: &str = "127.0.0.1";
|
||||
pub const DEFAULT_STATISTICS_SERVICE_PORT: u16 = 8091;
|
||||
|
||||
pub const STATISTICS_SERVICE_VERSION: &str = "/v1";
|
||||
pub const STATISTICS_SERVICE_API_STATISTICS: &str = "statistic";
|
||||
|
||||
pub async fn build_and_send_statistics_request(
|
||||
msg: StatsMessage,
|
||||
url: String,
|
||||
) -> Result<(), StatsError> {
|
||||
reqwest::Client::new()
|
||||
.post(format!(
|
||||
"{url}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
|
||||
))
|
||||
.json(&msg)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn build_statistics_request_bytes(msg: StatsMessage) -> Result<Vec<u8>, StatsError> {
|
||||
let json_msg = msg.to_json()?;
|
||||
|
||||
let req = reqwest::Request::new(
|
||||
reqwest::Method::POST,
|
||||
reqwest::Url::parse(&format!(
|
||||
"http://{DEFAULT_STATISTICS_SERVICE_ADDRESS}:{DEFAULT_STATISTICS_SERVICE_PORT}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
let data = format!(
|
||||
"{} {} {:?}\n\
|
||||
Content-Type: application/json\n\
|
||||
Content-Length: {}\n\n\
|
||||
{}\n",
|
||||
req.method().as_str(),
|
||||
req.url().as_str(),
|
||||
req.version(),
|
||||
json_msg.len(),
|
||||
json_msg
|
||||
);
|
||||
|
||||
Ok(data.into_bytes())
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::error;
|
||||
use sqlx::types::chrono::{DateTime, Utc};
|
||||
use std::time::Duration;
|
||||
use tokio::time;
|
||||
|
||||
use crate::error::StatsError;
|
||||
use crate::StatsMessage;
|
||||
|
||||
const STATISTICS_TIMER_INTERVAL: Duration = Duration::from_secs(60);
|
||||
|
||||
#[async_trait]
|
||||
pub trait StatisticsCollector {
|
||||
async fn create_stats_message(
|
||||
&self,
|
||||
interval: Duration,
|
||||
timestamp: DateTime<Utc>,
|
||||
) -> StatsMessage;
|
||||
async fn send_stats_message(&self, stats_message: StatsMessage) -> Result<(), StatsError>;
|
||||
async fn reset_stats(&mut self);
|
||||
}
|
||||
|
||||
pub struct StatisticsSender<T: StatisticsCollector> {
|
||||
collector: T,
|
||||
interval: Duration,
|
||||
timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl<T: StatisticsCollector> StatisticsSender<T> {
|
||||
pub fn new(collector: T) -> Self {
|
||||
StatisticsSender {
|
||||
collector,
|
||||
interval: STATISTICS_TIMER_INTERVAL,
|
||||
timestamp: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
let mut interval = time::interval(self.interval);
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let stats_message = self
|
||||
.collector
|
||||
.create_stats_message(self.interval, self.timestamp)
|
||||
.await;
|
||||
if let Err(e) = self.collector.send_stats_message(stats_message).await {
|
||||
error!("Statistics not sent: {}", e);
|
||||
}
|
||||
self.collector.reset_stats().await;
|
||||
self.timestamp = Utc::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StatsError {
|
||||
#[error("Serde JSON error: {0}")]
|
||||
SerdeJsonError(#[from] serde_json::Error),
|
||||
|
||||
#[error("Reqwest error: {0}")]
|
||||
ReqwestError(#[from] reqwest::Error),
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use error::StatsError;
|
||||
|
||||
pub mod api;
|
||||
pub mod collector;
|
||||
pub mod error;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsMessage {
|
||||
pub stats_data: Vec<StatsData>,
|
||||
pub interval_seconds: u32,
|
||||
pub timestamp: String,
|
||||
}
|
||||
|
||||
impl StatsMessage {
|
||||
pub fn to_json(&self) -> Result<String, StatsError> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
pub fn from_json(s: &str) -> Result<Self, StatsError> {
|
||||
Ok(serde_json::from_str(s)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum StatsData {
|
||||
Service(StatsServiceData),
|
||||
Gateway(StatsGatewayData),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsGatewayData {
|
||||
pub gateway_id: String,
|
||||
pub inbox_count: u32,
|
||||
}
|
||||
|
||||
impl StatsGatewayData {
|
||||
pub fn new(gateway_id: String, inbox_count: u32) -> Self {
|
||||
StatsGatewayData {
|
||||
gateway_id,
|
||||
inbox_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct StatsServiceData {
|
||||
pub requested_service: String,
|
||||
pub request_bytes: u32,
|
||||
pub response_bytes: u32,
|
||||
}
|
||||
|
||||
impl StatsServiceData {
|
||||
pub fn new(requested_service: String, request_bytes: u32, response_bytes: u32) -> Self {
|
||||
StatsServiceData {
|
||||
requested_service,
|
||||
request_bytes,
|
||||
response_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,21 +8,21 @@ rust-version = "1.58"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.21.4"
|
||||
base64 = { workspace = true }
|
||||
eyre = { workspace = true }
|
||||
hmac = { workspace = true }
|
||||
itertools = "0.11"
|
||||
itertools = { workspace = true }
|
||||
log = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = "0.10.8"
|
||||
sha2 = { workspace = true }
|
||||
strum = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
ts-rs = { workspace = true }
|
||||
url = { workspace = true }
|
||||
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }
|
||||
x25519-dalek = { workspace = true, features = ["static_secrets"] }
|
||||
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmrs = { workspace = true }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use nym_mixnet_contract_common::ContractsCommonError;
|
||||
use nym_validator_client::error::TendermintRpcError;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
use nym_validator_client::{nyxd::error::NyxdError, ValidatorClientError};
|
||||
@@ -8,6 +9,9 @@ use thiserror::Error;
|
||||
// TODO: ask @MS why this even exists
|
||||
#[derive(Error, Debug)]
|
||||
pub enum TypesError {
|
||||
#[error(transparent)]
|
||||
ContractsCommon(#[from] ContractsCommonError),
|
||||
|
||||
#[error("{source}")]
|
||||
NyxdError {
|
||||
#[from]
|
||||
|
||||
@@ -124,7 +124,6 @@ pub struct GatewayNetworkRequesterDetails {
|
||||
pub encryption_key: String,
|
||||
|
||||
pub open_proxy: bool,
|
||||
pub enabled_statistics: bool,
|
||||
|
||||
// just a convenience wrapper around all the keys
|
||||
pub address: String,
|
||||
@@ -142,8 +141,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails {
|
||||
writeln!(f, "\tencryption key: {}", self.encryption_key)?;
|
||||
writeln!(f, "\taddress: {}", self.address)?;
|
||||
|
||||
writeln!(f, "\tuses open proxy: {}", self.open_proxy)?;
|
||||
writeln!(f, "\tsends statistics: {}", self.enabled_statistics)
|
||||
writeln!(f, "\tuses open proxy: {}", self.open_proxy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ pub async fn setup_gateway_from_api(
|
||||
nym_apis: &[Url],
|
||||
) -> Result<InitialisationResult, WasmCoreError> {
|
||||
let mut rng = thread_rng();
|
||||
let gateways = current_gateways(&mut rng, nym_apis).await?;
|
||||
let gateways = current_gateways(&mut rng, nym_apis, None).await?;
|
||||
setup_gateway_wasm(client_store, force_tls, chosen_gateway, &gateways).await
|
||||
}
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@ nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
## verify:
|
||||
hmac = { workspace = true, optional = true }
|
||||
sha2 = { version = "0.10.8", optional = true }
|
||||
sha2 = { workspace = true, optional = true }
|
||||
|
||||
## openapi:
|
||||
utoipa = { workspace = true, optional = true }
|
||||
serde_json = { workspace = true, optional = true }
|
||||
|
||||
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }
|
||||
x25519-dalek = { workspace = true, features = ["static_secrets"] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8.5"
|
||||
|
||||
@@ -10,8 +10,7 @@ pub use config::Config;
|
||||
pub use error::Error;
|
||||
pub use public_key::PeerPublicKey;
|
||||
pub use registration::{
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, GatewayClientRegistry,
|
||||
InitMessage, Nonce,
|
||||
ClientMac, ClientMessage, GatewayClient, GatewayClientRegistry, InitMessage, Nonce,
|
||||
};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
|
||||
@@ -7,6 +7,7 @@ use base64::{engine::general_purpose, Engine};
|
||||
use dashmap::DashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::IpAddr;
|
||||
use std::time::SystemTime;
|
||||
use std::{fmt, ops::Deref, str::FromStr};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
@@ -18,13 +19,13 @@ use sha2::Sha256;
|
||||
|
||||
pub type GatewayClientRegistry = DashMap<PeerPublicKey, GatewayClient>;
|
||||
pub type PendingRegistrations = DashMap<PeerPublicKey, RegistrationData>;
|
||||
pub type PrivateIPs = DashMap<IpAddr, Free>;
|
||||
pub type PrivateIPs = DashMap<IpAddr, Taken>;
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
pub type HmacSha256 = Hmac<Sha256>;
|
||||
|
||||
pub type Nonce = u64;
|
||||
pub type Free = bool;
|
||||
pub type Taken = Option<SystemTime>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
@@ -53,15 +54,6 @@ impl InitMessage {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub enum ClientRegistrationResponse {
|
||||
PendingRegistration(RegistrationData),
|
||||
Registered,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct RegistrationData {
|
||||
pub nonce: u64,
|
||||
pub gateway_data: GatewayClient,
|
||||
|
||||
@@ -11,13 +11,13 @@ license.workspace = true
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.21.3"
|
||||
base64 = { workspace = true }
|
||||
dashmap = { workspace = true }
|
||||
defguard_wireguard_rs = { workspace = true }
|
||||
# The latest version on crates.io at the time of writing this (6.0.0) has a
|
||||
# version mismatch with x25519-dalek/curve25519-dalek that is resolved in the
|
||||
# latest commit. So pick that for now.
|
||||
x25519-dalek = "2.0.0"
|
||||
x25519-dalek = { workspace = true }
|
||||
ip_network = { workspace = true }
|
||||
log.workspace = true
|
||||
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
|
||||
|
||||
@@ -24,5 +24,7 @@ pub fn default_mixnet_init_msg() -> nym_mixnet_contract_common::InstantiateMsg {
|
||||
rewarded_set_size: 240,
|
||||
active_set_size: 100,
|
||||
},
|
||||
profit_margin: Default::default(),
|
||||
interval_operating_cost: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,28 @@
|
||||
"initial_rewarding_params": {
|
||||
"$ref": "#/definitions/InitialRewardingParams"
|
||||
},
|
||||
"interval_operating_cost": {
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rewarding_denom": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -112,6 +134,42 @@
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1172,6 +1230,18 @@
|
||||
"minimum_mixnode_pledge"
|
||||
],
|
||||
"properties": {
|
||||
"interval_operating_cost": {
|
||||
"description": "Defines the allowed interval operating cost range of operators. default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)",
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum_gateway_pledge": {
|
||||
"description": "Minimum amount a gateway must pledge to get into the system.",
|
||||
"allOf": [
|
||||
@@ -1198,6 +1268,18 @@
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"description": "Defines the allowed profit margin range of operators. default: 0% - 100%",
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -1532,6 +1614,38 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
@@ -8063,6 +8177,18 @@
|
||||
"minimum_mixnode_pledge"
|
||||
],
|
||||
"properties": {
|
||||
"interval_operating_cost": {
|
||||
"description": "Defines the allowed interval operating cost range of operators. default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)",
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum_gateway_pledge": {
|
||||
"description": "Minimum amount a gateway must pledge to get into the system.",
|
||||
"allOf": [
|
||||
@@ -8089,6 +8215,62 @@
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"description": "Defines the allowed profit margin range of operators. default: 0% - 100%",
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Decimal": {
|
||||
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
|
||||
"type": "string"
|
||||
},
|
||||
"Percent": {
|
||||
"description": "Percent represents a value between 0 and 100% (i.e. between 0.0 and 1.0)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -8109,6 +8291,18 @@
|
||||
"minimum_mixnode_pledge"
|
||||
],
|
||||
"properties": {
|
||||
"interval_operating_cost": {
|
||||
"description": "Defines the allowed interval operating cost range of operators. default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)",
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum_gateway_pledge": {
|
||||
"description": "Minimum amount a gateway must pledge to get into the system.",
|
||||
"allOf": [
|
||||
@@ -8135,6 +8329,18 @@
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"description": "Defines the allowed profit margin range of operators. default: 0% - 100%",
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -8154,6 +8360,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Decimal": {
|
||||
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
|
||||
"type": "string"
|
||||
},
|
||||
"Percent": {
|
||||
"description": "Percent represents a value between 0 and 100% (i.e. between 0.0 and 1.0)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
|
||||
@@ -1055,6 +1055,18 @@
|
||||
"minimum_mixnode_pledge"
|
||||
],
|
||||
"properties": {
|
||||
"interval_operating_cost": {
|
||||
"description": "Defines the allowed interval operating cost range of operators. default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)",
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum_gateway_pledge": {
|
||||
"description": "Minimum amount a gateway must pledge to get into the system.",
|
||||
"allOf": [
|
||||
@@ -1081,6 +1093,18 @@
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"description": "Defines the allowed profit margin range of operators. default: 0% - 100%",
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -1415,6 +1439,38 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
|
||||
@@ -22,6 +22,28 @@
|
||||
"initial_rewarding_params": {
|
||||
"$ref": "#/definitions/InitialRewardingParams"
|
||||
},
|
||||
"interval_operating_cost": {
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rewarding_denom": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -108,6 +130,42 @@
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,18 @@
|
||||
"minimum_mixnode_pledge"
|
||||
],
|
||||
"properties": {
|
||||
"interval_operating_cost": {
|
||||
"description": "Defines the allowed interval operating cost range of operators. default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)",
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum_gateway_pledge": {
|
||||
"description": "Minimum amount a gateway must pledge to get into the system.",
|
||||
"allOf": [
|
||||
@@ -103,6 +115,62 @@
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"description": "Defines the allowed profit margin range of operators. default: 0% - 100%",
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Decimal": {
|
||||
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
|
||||
"type": "string"
|
||||
},
|
||||
"Percent": {
|
||||
"description": "Percent represents a value between 0 and 100% (i.e. between 0.0 and 1.0)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -8,6 +8,18 @@
|
||||
"minimum_mixnode_pledge"
|
||||
],
|
||||
"properties": {
|
||||
"interval_operating_cost": {
|
||||
"description": "Defines the allowed interval operating cost range of operators. default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)",
|
||||
"default": {
|
||||
"maximum": "1000000000000000",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Uint128"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum_gateway_pledge": {
|
||||
"description": "Minimum amount a gateway must pledge to get into the system.",
|
||||
"allOf": [
|
||||
@@ -34,6 +46,18 @@
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"profit_margin": {
|
||||
"description": "Defines the allowed profit margin range of operators. default: 0% - 100%",
|
||||
"default": {
|
||||
"maximum": "1",
|
||||
"minimum": "0"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RangedValue_for_Percent"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -53,6 +77,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Decimal": {
|
||||
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
|
||||
"type": "string"
|
||||
},
|
||||
"Percent": {
|
||||
"description": "Percent represents a value between 0 and 100% (i.e. between 0.0 and 1.0)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"RangedValue_for_Percent": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Percent"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RangedValue_for_Uint128": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maximum",
|
||||
"minimum"
|
||||
],
|
||||
"properties": {
|
||||
"maximum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
|
||||
@@ -11,7 +11,8 @@ use cosmwasm_std::{
|
||||
};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::{
|
||||
ContractState, ContractStateParams, ExecuteMsg, InstantiateMsg, Interval, MigrateMsg, QueryMsg,
|
||||
ContractState, ContractStateParams, ExecuteMsg, InstantiateMsg, Interval, MigrateMsg,
|
||||
OperatingCostRange, ProfitMarginRange, QueryMsg,
|
||||
};
|
||||
use nym_contracts_common::set_build_information;
|
||||
|
||||
@@ -24,6 +25,8 @@ fn default_initial_state(
|
||||
rewarding_validator_address: Addr,
|
||||
rewarding_denom: String,
|
||||
vesting_contract_address: Addr,
|
||||
profit_margin: ProfitMarginRange,
|
||||
interval_operating_cost: OperatingCostRange,
|
||||
) -> ContractState {
|
||||
ContractState {
|
||||
owner,
|
||||
@@ -40,6 +43,8 @@ fn default_initial_state(
|
||||
denom: rewarding_denom,
|
||||
amount: INITIAL_GATEWAY_PLEDGE_AMOUNT,
|
||||
},
|
||||
profit_margin,
|
||||
interval_operating_cost,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -71,6 +76,8 @@ pub fn instantiate(
|
||||
rewarding_validator_address.clone(),
|
||||
msg.rewarding_denom,
|
||||
vesting_contract_address,
|
||||
msg.profit_margin,
|
||||
msg.interval_operating_cost,
|
||||
);
|
||||
let starting_interval =
|
||||
Interval::init_interval(msg.epochs_in_interval, msg.epoch_duration, &env);
|
||||
@@ -631,7 +638,7 @@ pub fn migrate(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
|
||||
use cosmwasm_std::Decimal;
|
||||
use cosmwasm_std::{Decimal, Uint128};
|
||||
use mixnet_contract_common::reward_params::{IntervalRewardParams, RewardingParams};
|
||||
use mixnet_contract_common::{InitialRewardingParams, Percent};
|
||||
use std::time::Duration;
|
||||
@@ -657,6 +664,14 @@ mod tests {
|
||||
rewarded_set_size: 543,
|
||||
active_set_size: 123,
|
||||
},
|
||||
profit_margin: ProfitMarginRange {
|
||||
minimum: "0.05".parse().unwrap(),
|
||||
maximum: "0.95".parse().unwrap(),
|
||||
},
|
||||
interval_operating_cost: OperatingCostRange {
|
||||
minimum: "1000".parse().unwrap(),
|
||||
maximum: "10000".parse().unwrap(),
|
||||
},
|
||||
};
|
||||
|
||||
let sender = mock_info("sender", &[]);
|
||||
@@ -678,6 +693,14 @@ mod tests {
|
||||
denom: "uatom".into(),
|
||||
amount: INITIAL_GATEWAY_PLEDGE_AMOUNT,
|
||||
},
|
||||
profit_margin: ProfitMarginRange {
|
||||
minimum: Percent::from_percentage_value(5).unwrap(),
|
||||
maximum: Percent::from_percentage_value(95).unwrap(),
|
||||
},
|
||||
interval_operating_cost: OperatingCostRange {
|
||||
minimum: Uint128::new(1000),
|
||||
maximum: Uint128::new(10000),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ pub(crate) mod tests {
|
||||
minimum_mixnode_delegation: None,
|
||||
minimum_mixnode_pledge: coin(123u128, "unym"),
|
||||
minimum_gateway_pledge: coin(456u128, "unym"),
|
||||
profit_margin: Default::default(),
|
||||
interval_operating_cost: Default::default(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use cosmwasm_std::{Addr, Storage};
|
||||
use cosmwasm_std::{Coin, StdResult};
|
||||
use cw_storage_plus::Item;
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::ContractState;
|
||||
use mixnet_contract_common::{ContractState, OperatingCostRange, ProfitMarginRange};
|
||||
|
||||
pub(crate) const CONTRACT_STATE: Item<'_, ContractState> = Item::new(CONTRACT_STATE_KEY);
|
||||
|
||||
@@ -28,6 +28,22 @@ pub(crate) fn minimum_gateway_pledge(storage: &dyn Storage) -> Result<Coin, Mixn
|
||||
.map(|state| state.params.minimum_gateway_pledge)?)
|
||||
}
|
||||
|
||||
pub(crate) fn profit_margin_range(
|
||||
storage: &dyn Storage,
|
||||
) -> Result<ProfitMarginRange, MixnetContractError> {
|
||||
Ok(CONTRACT_STATE
|
||||
.load(storage)
|
||||
.map(|state| state.params.profit_margin)?)
|
||||
}
|
||||
|
||||
pub(crate) fn interval_oprating_cost_range(
|
||||
storage: &dyn Storage,
|
||||
) -> Result<OperatingCostRange, MixnetContractError> {
|
||||
Ok(CONTRACT_STATE
|
||||
.load(storage)
|
||||
.map(|state| state.params.interval_operating_cost)?)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn minimum_delegation_stake(
|
||||
storage: &dyn Storage,
|
||||
|
||||
@@ -121,6 +121,8 @@ pub mod tests {
|
||||
denom,
|
||||
amount: INITIAL_GATEWAY_PLEDGE_AMOUNT + Uint128::new(1234),
|
||||
},
|
||||
profit_margin: Default::default(),
|
||||
interval_operating_cost: Default::default(),
|
||||
};
|
||||
|
||||
let initial_params = storage::CONTRACT_STATE
|
||||
|
||||
@@ -25,7 +25,8 @@ use crate::mixnodes::signature_helpers::verify_mixnode_bonding_signature;
|
||||
use crate::signing::storage as signing_storage;
|
||||
use crate::support::helpers::{
|
||||
ensure_bonded, ensure_epoch_in_progress_state, ensure_is_authorized, ensure_no_existing_bond,
|
||||
ensure_no_pending_pledge_changes, ensure_proxy_match, ensure_sent_by_vesting_contract,
|
||||
ensure_no_pending_pledge_changes, ensure_operating_cost_within_range,
|
||||
ensure_profit_margin_within_range, ensure_proxy_match, ensure_sent_by_vesting_contract,
|
||||
validate_pledge,
|
||||
};
|
||||
|
||||
@@ -121,6 +122,12 @@ fn _try_add_mixnode(
|
||||
owner_signature: MessageSignature,
|
||||
proxy: Option<Addr>,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
// ensure the profit margin is within the defined range
|
||||
ensure_profit_margin_within_range(deps.storage, cost_params.profit_margin_percent)?;
|
||||
|
||||
// ensure the operating cost is within the defined range
|
||||
ensure_operating_cost_within_range(deps.storage, &cost_params.interval_operating_cost)?;
|
||||
|
||||
// check if the pledge contains any funds of the appropriate denomination
|
||||
let minimum_pledge = mixnet_params_storage::minimum_mixnode_pledge(deps.storage)?;
|
||||
let pledge = validate_pledge(pledge, minimum_pledge)?;
|
||||
@@ -477,6 +484,12 @@ pub(crate) fn _try_update_mixnode_cost_params(
|
||||
ensure_proxy_match(&proxy, &existing_bond.proxy)?;
|
||||
ensure_bonded(&existing_bond)?;
|
||||
|
||||
// ensure the profit margin is within the defined range
|
||||
ensure_profit_margin_within_range(deps.storage, new_costs.profit_margin_percent)?;
|
||||
|
||||
// ensure the operating cost is within the defined range
|
||||
ensure_operating_cost_within_range(deps.storage, &new_costs.interval_operating_cost)?;
|
||||
|
||||
let cosmos_event = new_mixnode_pending_cost_params_update_event(
|
||||
existing_bond.mix_id,
|
||||
&owner,
|
||||
|
||||
@@ -111,6 +111,14 @@ pub(crate) fn try_reward_mixnode(
|
||||
);
|
||||
}
|
||||
|
||||
// make sure node's profit margin is within the allowed range,
|
||||
// if not adjust it accordingly
|
||||
let params = mixnet_params_storage::CONTRACT_STATE
|
||||
.load(deps.storage)?
|
||||
.params;
|
||||
mix_rewarding.normalise_profit_margin(params.profit_margin);
|
||||
mix_rewarding.normalise_operating_cost(params.interval_operating_cost);
|
||||
|
||||
let rewarding_params = storage::REWARDING_PARAMS.load(deps.storage)?;
|
||||
let node_reward_params = NodeRewardParams::new(node_performance, node_status.is_active());
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use cosmwasm_std::{wasm_execute, Addr, BankMsg, Coin, CosmosMsg, MessageInfo, Re
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::mixnode::PendingMixNodeChanges;
|
||||
use mixnet_contract_common::{EpochState, EpochStatus, IdentityKeyRef, MixId, MixNodeBond};
|
||||
use nym_contracts_common::Percent;
|
||||
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
|
||||
// helper trait to attach `Msg` to a response if it's provided
|
||||
@@ -431,3 +432,34 @@ pub(crate) fn decode_ed25519_identity_key(
|
||||
|
||||
Ok(public_key)
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_profit_margin_within_range(
|
||||
storage: &dyn Storage,
|
||||
profit_margin: Percent,
|
||||
) -> Result<(), MixnetContractError> {
|
||||
let range = mixnet_params_storage::profit_margin_range(storage)?;
|
||||
if !range.within_range(profit_margin) {
|
||||
return Err(MixnetContractError::ProfitMarginOutsideRange {
|
||||
provided: profit_margin,
|
||||
range,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ensure_operating_cost_within_range(
|
||||
storage: &dyn Storage,
|
||||
operating_cost: &Coin,
|
||||
) -> Result<(), MixnetContractError> {
|
||||
let range = mixnet_params_storage::interval_oprating_cost_range(storage)?;
|
||||
if !range.within_range(operating_cost.amount) {
|
||||
return Err(MixnetContractError::OperatingCostOutsideRange {
|
||||
denom: operating_cost.denom.clone(),
|
||||
provided: operating_cost.amount,
|
||||
range,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1258,6 +1258,8 @@ pub mod test_helpers {
|
||||
epochs_in_interval: 720,
|
||||
epoch_duration: Duration::from_secs(60 * 60),
|
||||
initial_rewarding_params: initial_rewarding_params(),
|
||||
profit_margin: Default::default(),
|
||||
interval_operating_cost: Default::default(),
|
||||
};
|
||||
let env = mock_env();
|
||||
let info = mock_info("creator", &[]);
|
||||
|
||||
+14
-14
@@ -423,11 +423,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -559,9 +559,9 @@
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
@@ -1537,11 +1537,11 @@
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"brorand": {
|
||||
@@ -1659,9 +1659,9 @@
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Nym Docs"
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
description = "Nym technical documentation"
|
||||
language = "en"
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
|
||||
src = "src"
|
||||
|
||||
[rust]
|
||||
@@ -14,17 +14,19 @@ edition = "2018"
|
||||
#################
|
||||
|
||||
[preprocessor.theme]
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "70%"
|
||||
content-main-margin-left = "5%"
|
||||
content-main-margin-right = "5%"
|
||||
root-font-size = "70%"
|
||||
# DO NOT CHANGE or you might overwrite the custom hbs file
|
||||
turn-off = false
|
||||
pagetoc = true
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "80%"
|
||||
root-font-size = "70%"
|
||||
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
|
||||
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
|
||||
# this is because of a bug in the `mdbook-theme` plugin
|
||||
turn-off = true
|
||||
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
|
||||
# https://gitlab.com/tglman/mdbook-variables/
|
||||
[preprocessor.variables.variables]
|
||||
@@ -53,52 +55,56 @@ renderer = ["html"]
|
||||
#########
|
||||
|
||||
[build]
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
|
||||
##########
|
||||
# OUTPUT #
|
||||
##########
|
||||
|
||||
[output.html]
|
||||
theme = "nym_themes"
|
||||
theme = "themes"
|
||||
default-theme = "coal"
|
||||
preferred-dark-theme = "coal"
|
||||
curly-quotes = true
|
||||
copy-fonts = true
|
||||
no-section-label = false
|
||||
additional-css = ["./nym_themes/custom.css", "./nym_themes/mdbook-admonish.css", "./nym_themes/pagetoc.css"]
|
||||
additional-js = ["./nym_themes/pagetoc.js"]
|
||||
additional-css = [
|
||||
"./themes/custom.css",
|
||||
"./themes/mdbook-admonish.css",
|
||||
"./themes/pagetoc.css",
|
||||
]
|
||||
additional-js = ["./themes/pagetoc.js"]
|
||||
git-repository-url = "https://github.com/nymtech/nym"
|
||||
git-repository-icon = "fa-github"
|
||||
input-404 = "not-found.md"
|
||||
|
||||
[output.html.fold]
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
|
||||
# controlling rust sample code blocks
|
||||
[output.html.playground]
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
|
||||
# options for the built in text search
|
||||
[output.html.search]
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
|
||||
[output.linkcheck]
|
||||
warning-policy = "warn"
|
||||
|
||||
@@ -1,93 +1,59 @@
|
||||
#
|
||||
# Summary
|
||||
|
||||
- [Introduction](introduction.md)
|
||||
- [Clients Overview - Start Here!](clients-overview.md)
|
||||
|
||||
# Infrastructure
|
||||
# SDKs
|
||||
- [Rust SDK](sdk/rust/rust.md)
|
||||
- [Message Types](sdk/rust/message-types.md)
|
||||
- [Message Helpers](sdk/rust/message-helpers.md)
|
||||
- [Troubleshooting](sdk/rust/troubleshooting.md)
|
||||
- [Examples](sdk/rust/examples.md)
|
||||
- [Simple Send](sdk/rust/examples/simple.md)
|
||||
- [Create and Store Keys](sdk/rust/examples/keys.md)
|
||||
- [Manual Storage](sdk/rust/examples/storage.md)
|
||||
- [Anonymous Replies](sdk/rust/examples/surbs.md)
|
||||
- [Use Custom Network Topology](sdk/rust/examples/custom-network.md)
|
||||
- [Socks Proxy](sdk/rust/examples/socks.md)
|
||||
- [Split Send and Receive](sdk/rust/examples/split-send.md)
|
||||
- [Testnet Bandwidth Cred](sdk/rust/examples/credential.md)
|
||||
- [Example Cargo file](sdk/rust/examples/cargo.md)
|
||||
- [Typescript SDK](sdk/typescript.md)
|
||||
|
||||
- [What is Nym?](infrastructure/nym.md)
|
||||
- [Nym vs Other Systems](infrastructure/nym-vs-others.md)
|
||||
- [Node Types](infrastructure/node-types.md)
|
||||
# Binaries
|
||||
- [Pre-built Binaries](binaries/pre-built-binaries.md)
|
||||
- [Building from Source](binaries/building-nym.md)
|
||||
|
||||
# Quickstart
|
||||
# Standalone Clients
|
||||
- [Websocket Client](clients/websocket-client.md)
|
||||
- [Setup & Run](clients/websocket/setup.md)
|
||||
- [Configuration](clients/websocket/config.md)
|
||||
- [Using Your Client](clients/websocket/usage.md)
|
||||
- [Examples](clients/websocket/examples.md)
|
||||
- [Socks5 Client](clients/socks5-client.md)
|
||||
- [Setup & Run](clients/socks5/setup.md)
|
||||
- [Using Your Client](clients/socks5/usage.md)
|
||||
- [Webassembly Client](clients/webassembly-client.md)
|
||||
|
||||
- [Overview](quickstart/overview.md)
|
||||
- [Chat demo (webapp)](quickstart/chat-demo.md)
|
||||
- [Coconut Credential Playground (webapp)](quickstart/cred-playground.md)
|
||||
- [SOCKS Proxy (CLI)](quickstart/socks-proxy.md)
|
||||
- [NymConnect Beta (GUI)](quickstart/nymconnect-gui.md)
|
||||
|
||||
# User Manuals
|
||||
|
||||
- [NymVPN alpha](nymvpn/intro.md)
|
||||
- [CLI](nymvpn/cli.md)
|
||||
|
||||
<!-- OUTDATED STUFF:
|
||||
- [NymConnect X Monero](tutorials/monero.md)
|
||||
- [NymConnect X Matrix](tutorials/matrix.md)
|
||||
- [NymConnect X Telegram](tutorials/telegram.md)
|
||||
- [NymConnect X Electrum](tutorials/electrum.md)
|
||||
- [NymConnect X Firo wallet](tutorials/firo.md)
|
||||
-->
|
||||
# Tutorials
|
||||
- [Stub: Updates Coming Soon!](./tutorials/coming-soon.md)
|
||||
|
||||
# Code Examples
|
||||
|
||||
- [Custom Service Providers](examples/custom-services.md)
|
||||
- [Apps Using Network Requesters](examples/using-nrs.md)
|
||||
- [Browser only](examples/browser-only.md)
|
||||
- [Monorepo examples](examples/monorepo-examples.md)
|
||||
|
||||
# Integrations
|
||||
|
||||
- [Integration Options](integrations/integration-options.md)
|
||||
[//]: # (- [Mixnet Integration](integrations/mixnet-integration.md))
|
||||
- [Payment Integration](integrations/payment-integration.md)
|
||||
|
||||
# Tutorials
|
||||
|
||||
- [Rust SDK](tutorials/rust-sdk.md)
|
||||
- [Blockchain Service pt1](tutorials/cosmos-service/intro.md)
|
||||
- [Tutorial Overview](tutorials/cosmos-service/overview.md)
|
||||
- [Preparing Your Environment](tutorials/cosmos-service/preparing-env.md)
|
||||
- [Preparing Your Lib](tutorials/cosmos-service/lib.md)
|
||||
- [Preparing Your Client](tutorials/cosmos-service/client.md)
|
||||
- [Preparing Your Client pt2](tutorials/cosmos-service/client-src.md)
|
||||
- [Preparing Your Service](tutorials/cosmos-service/service.md)
|
||||
- [Preparing Your Service pt2](tutorials/cosmos-service/service-src.md)
|
||||
- [Querying the Chain](tutorials/cosmos-service/querying.md)
|
||||
|
||||
- [Typescript](tutorials/typescript.md)
|
||||
- [Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md)
|
||||
- [Tutorial Overview](tutorials/simple-service-provider/overview.md)
|
||||
- [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md)
|
||||
- [Building Your User Client](tutorials/simple-service-provider/user-client.md)
|
||||
- [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md)
|
||||
- [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md)
|
||||
- [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md)
|
||||
|
||||
[//]: # (TODO make generic )
|
||||
[//]: # (# Shipyard Builders Hackathon 2023 )
|
||||
[//]: # (- [General Info & Resources](shipyard/general.md))
|
||||
[//]: # (- [Hackathon Challenges](shipyard/challenges-overview.md))
|
||||
[//]: # (- [A Note on Infrastructure](shipyard/infra.md))
|
||||
[//]: # (- [Submission Guidelines](shipyard/guidelines.md))
|
||||
|
||||
# Events
|
||||
|
||||
- [Web3Privacy Now](./events/web3-privacy.md)
|
||||
- [HCPP23-serinko](./events/hcpp23-serinko.md)
|
||||
- [HCPP23-max](./events/hcpp23-max.md)
|
||||
|
||||
# FAQ
|
||||
- [General](faq/general-faq.md)
|
||||
- [Integrations](faq/integrations-faq.md)
|
||||
- [Rewards & Token](faq/rewards-faq.md)
|
||||
|
||||
# Community Resources
|
||||
|
||||
- [Nym DevRel AMAs](community-resources/ama.md)
|
||||
- [Community Applications and Guides](community-resources/community-applications-and-guides.md)
|
||||
- [Change Service Grantee Information](info-request.md)
|
||||
# User Manuals
|
||||
- [NymVPN alpha](nymvpn/intro.md)
|
||||
- [CLI](nymvpn/cli.md)
|
||||
|
||||
---
|
||||
# Misc.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user