Compare commits
266 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a7e956c93 | |||
| 3410a2b2e0 | |||
| 1349242367 | |||
| 8f812cc610 | |||
| 05aa0dbd8e | |||
| 5b69b0e7d9 | |||
| be88a9b277 | |||
| fce2c704af | |||
| d8a95d3810 | |||
| 191aa149df | |||
| f4df1a9168 | |||
| 62316244d9 | |||
| a26c6d7a29 | |||
| 8fda246a3c | |||
| 5620fd7009 | |||
| 122612fa03 | |||
| 53db18df2c | |||
| e00910bcb8 | |||
| 0af9b3c6c8 | |||
| 2d60a9da3f | |||
| 795efb9f0b | |||
| 695d34735c | |||
| 314d7a7526 | |||
| a86c1a6a60 | |||
| 7ad2865250 | |||
| 49440bf60e | |||
| b3b43b56be | |||
| 4a23729a6a | |||
| 5711bbd0c1 | |||
| 1b1f0293ec | |||
| 9285aaf487 | |||
| 55bd7f8a61 | |||
| b66c4cf0bb | |||
| 4696470b19 | |||
| 5dacf0c8f8 | |||
| cbafd37102 | |||
| e537359c73 | |||
| 2ed3e646be | |||
| c725ae4e2b | |||
| 5ab2c738df | |||
| cd70b0de75 | |||
| 6359b38a5d | |||
| 00b5a46cbc | |||
| e97a068bf0 | |||
| c7147ebfb2 | |||
| a344cda916 | |||
| 15a6af49f0 | |||
| 97956afdf6 | |||
| 7b71775e08 | |||
| 5fbccc3406 | |||
| 5964f104c5 | |||
| ac8afe133f | |||
| 19736b1204 | |||
| 6e5f6bf0df | |||
| 0bfc1be1d5 | |||
| 67435e9cdf | |||
| a47899aa77 | |||
| aedacf6c65 | |||
| 44fa52a7a7 | |||
| f6e20c8201 | |||
| 1da6ee2058 | |||
| 109fb96fca | |||
| 557bfa7b34 | |||
| 4c9727b1ef | |||
| a0408b74dc | |||
| 8a1ed12f58 | |||
| c38c5c2f0d | |||
| 03300a859e | |||
| 2fe5401a38 | |||
| d8a44cd9c1 | |||
| a0b41db22d | |||
| 7d6d8669b0 | |||
| a1a2f37fce | |||
| 91341733c1 | |||
| 93cd8821c3 | |||
| b79ec60381 | |||
| 2c2dd54028 | |||
| 4306cec49c | |||
| 5781d3043f | |||
| d843407ba7 | |||
| 053e047cca | |||
| 516561dcf9 | |||
| 290dbc1a03 | |||
| 524863aae7 | |||
| 61ad336b18 | |||
| 867b745a38 | |||
| 78e54287da | |||
| 96c29b974b | |||
| eadd116ae4 | |||
| f1175280cf | |||
| 34a47a9449 | |||
| dff11df2bd | |||
| feb888a154 | |||
| 415fe4605c | |||
| 70e6539298 | |||
| fe76ba68a0 | |||
| 863580a6f2 | |||
| 4c558db08e | |||
| 9d5b582908 | |||
| c12b20f1d6 | |||
| edeb8369df | |||
| 22b2405aa2 | |||
| 63254ecffe | |||
| 407d280019 | |||
| 41e1009095 | |||
| 1fafc126fb | |||
| 9a51135d22 | |||
| 1b2790da80 | |||
| f8943eebce | |||
| d7b53cba40 | |||
| 89d2f0ac12 | |||
| 110b4d384e | |||
| 6d79b6f600 | |||
| 4631c72c6b | |||
| 12aa5f1f4f | |||
| 825f25800a | |||
| d9b4d8fde6 | |||
| a98613d83c | |||
| 34de42fe7a | |||
| 766261f774 | |||
| 6e2eaf29e7 | |||
| c99309dd79 | |||
| 37c875d8ee | |||
| b2b0a1478b | |||
| c6b193eb4f | |||
| aa67e183a6 | |||
| b27fa51092 | |||
| d01b6a12d6 | |||
| a133457722 | |||
| ad995b1934 | |||
| a881740c20 | |||
| 90cc68435c | |||
| c3ce9e24e2 | |||
| bdda08c0b4 | |||
| 0e48ff5e9e | |||
| 68d6ece6c2 | |||
| e17ae9dce0 | |||
| 493f036687 | |||
| 1f4f312e8e | |||
| d829837275 | |||
| 36253e3f36 | |||
| 7743554bb8 | |||
| de05e32845 | |||
| 136f4a8473 | |||
| 57e2628928 | |||
| 879e324696 | |||
| 351552b863 | |||
| 847f3a0ecc | |||
| 58958a2449 | |||
| 3051d84e8d | |||
| 2d7003dfae | |||
| 92b9edf0da | |||
| a91c997aed | |||
| 5787653210 | |||
| adbeeb3e5f | |||
| 4899ccf4ef | |||
| 9e0bcc025f | |||
| 16d6444169 | |||
| 997faeb1e6 | |||
| 565e7768e3 | |||
| 730f03de30 | |||
| 2e366a094d | |||
| b134334ec7 | |||
| f95b9b7f4a | |||
| 11ed3b3e45 | |||
| 271a5fbab6 | |||
| 90a97b398e | |||
| fc2236c3c8 | |||
| a71e228a25 | |||
| da9c2e5a7c | |||
| e025564678 | |||
| cf6188d794 | |||
| dd7308d92f | |||
| 73ca14aae2 | |||
| 0fee189a89 | |||
| a0c6efafd2 | |||
| c3d3164533 | |||
| fa2e0a9010 | |||
| fcc5398aab | |||
| 9f1f765f73 | |||
| 6403d0055b | |||
| 7bbb10e52c | |||
| 1aad69a527 | |||
| 4ad02d5328 | |||
| 45b74008f1 | |||
| 2ddf9646ec | |||
| b258cd8733 | |||
| ed48a2ddd4 | |||
| 7a1a7c003e | |||
| ef36c29b91 | |||
| 4025fed882 | |||
| 9aaa74204b | |||
| 9d7a6b2aec | |||
| 4b13a5cf61 | |||
| c9489fb48e | |||
| 6c3653c128 | |||
| 02a4452eca | |||
| d47633faa8 | |||
| a3da077ce9 | |||
| 131952c036 | |||
| 8d2ef605ed | |||
| fbcc2907bb | |||
| c0bb5503cf | |||
| ef7beaa12f | |||
| 31568b544c | |||
| 2953837f25 | |||
| ee98820bb4 | |||
| ed76000dd0 | |||
| 0dfe1460e4 | |||
| e06087ad3f | |||
| 0f41dda013 | |||
| 51d66c3e0c | |||
| 0a6a015987 | |||
| efd8ba5978 | |||
| 0c7181a211 | |||
| f14b40a769 | |||
| d8f80434b4 | |||
| f47a111640 | |||
| ae5a9ccc50 | |||
| 40465665f0 | |||
| 8c437ac964 | |||
| f3b17ad2f8 | |||
| 9121078576 | |||
| c505a00fac | |||
| 09bad9c6b4 | |||
| 597f5e9545 | |||
| 54cb7be1e1 | |||
| 431c98e591 | |||
| 35f2e71202 | |||
| 0134030341 | |||
| 97c775bc68 | |||
| 62ba6b30ae | |||
| 24354275d3 | |||
| 76335e9adc | |||
| bab8eb746e | |||
| f298f5d4fa | |||
| 85b078a3e8 | |||
| 0115b02be3 | |||
| a4ffd135e7 | |||
| bbce67902b | |||
| e6930046c4 | |||
| 0c9402503a | |||
| 81e133b789 | |||
| 7be07c29c1 | |||
| 31bc439f65 | |||
| 6479480cf7 | |||
| 4af70ef255 | |||
| eba58f6451 | |||
| 35206655e0 | |||
| e14db00fc2 | |||
| 2f98912778 | |||
| 72b92784cc | |||
| 38b95c2673 | |||
| f0f9899f82 | |||
| 09c46e3403 | |||
| 9fbab5aaad | |||
| 2032b3bdae | |||
| 8f57919571 | |||
| 3cdca0ad8d | |||
| 4c13d91bfb | |||
| 8355e6ce5e | |||
| 4caa9390cf | |||
| bbb1e5e15a | |||
| 6d30e7ea8e | |||
| 92e902c81e | |||
| c47bc174bc |
@@ -2,7 +2,7 @@
|
|||||||
name: 'Documentation'
|
name: 'Documentation'
|
||||||
about: Suggest a fix or enhancement to the documentation or developer portal content
|
about: Suggest a fix or enhancement to the documentation or developer portal content
|
||||||
title: "[DOCS]"
|
title: "[DOCS]"
|
||||||
labels: documentation
|
labels: documentation, needs-triage
|
||||||
assignees: mfahampshire
|
assignees: mfahampshire
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an enhancement to the product
|
about: Suggest an enhancement to the product
|
||||||
title: "[Feature Request]"
|
title: "[Feature Request]"
|
||||||
labels: enhancement
|
labels: enhancement, needs-triage
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name: Report
|
name: Report
|
||||||
about: To help identify and reproduce issues
|
about: To help identify and reproduce issues
|
||||||
title: "[Issue]"
|
title: "[Issue]"
|
||||||
labels: bug, bug-needs-triage, qa
|
labels: bug, bug-needs-triage, qa, needs-triage
|
||||||
assignees: tommyv1987
|
assignees: tommyv1987
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
- name: install npm
|
- name: install npm
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Matrix - Node Install
|
- name: Matrix - Node Install
|
||||||
run: npm install
|
run: npm install
|
||||||
working-directory: .github/workflows/support-files
|
working-directory: .github/workflows/support-files
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Setup yarn
|
- name: Setup yarn
|
||||||
run: npm install -g yarn
|
run: npm install -g yarn
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "16"
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "16"
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
name: Check Contract Schema
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'contracts/**'
|
||||||
|
- 'common/**'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'contracts/**'
|
||||||
|
- 'common/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-schema:
|
||||||
|
name: Generate and check schema
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Generate the schema
|
||||||
|
run: make contract-schema
|
||||||
|
|
||||||
|
- name: Check for diff
|
||||||
|
run: git diff --exit-code
|
||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "16"
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "16"
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -20,11 +20,22 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install -g yarn
|
run: npm install -g yarn
|
||||||
- run: 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
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Set environment from the example
|
- name: Set environment from the example
|
||||||
run: cp .env.sample .env
|
run: cp .env.sample .env
|
||||||
- run: yarn storybook:build
|
- run: yarn storybook:build
|
||||||
|
|||||||
@@ -48,12 +48,12 @@ jobs:
|
|||||||
RUSTFLAGS: '-C link-arg=-s'
|
RUSTFLAGS: '-C link-arg=-s'
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --manifest-path contracts/Cargo.toml --workspace --target wasm32-unknown-unknown
|
args: --manifest-path contracts/Cargo.toml --workspace --lib --target wasm32-unknown-unknown
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --manifest-path contracts/Cargo.toml
|
args: --lib --manifest-path contracts/Cargo.toml
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
@@ -64,4 +64,4 @@ jobs:
|
|||||||
if: ${{ matrix.rust != 'nightly' }}
|
if: ${{ matrix.rust != 'nightly' }}
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
|
args: --lib --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
name: Linting for Network Explorer (eslint/prettier)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'explorer/**'
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: explorer
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: custom-runner-linux
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- name: Setup yarn
|
|
||||||
run: npm install -g yarn
|
|
||||||
- name: Run ESLint
|
|
||||||
# GitHub should automatically annotate the PR
|
|
||||||
run: yarn && yarn lint
|
|
||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Setup yarn
|
- name: Setup yarn
|
||||||
run: npm install -g yarn
|
run: npm install -g yarn
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Matrix - Node Install
|
- name: Matrix - Node Install
|
||||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Matrix - Node Install
|
- name: Matrix - Node Install
|
||||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Matrix - Node Install
|
- name: Matrix - Node Install
|
||||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|||||||
@@ -15,19 +15,36 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [macos-latest]
|
platform: [macos-latest]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
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
|
- name: Install the Apple developer certificate for code signing
|
||||||
env:
|
env:
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
@@ -51,11 +68,15 @@ jobs:
|
|||||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.1
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
shell: bash
|
||||||
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies and build it
|
- name: Install app dependencies and build it
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -67,13 +88,15 @@ jobs:
|
|||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
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
|
run: yarn && yarn build
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: nym-connect_1.0.0_x64.dmg
|
name: nym-connect_1.0.0_x64.dmg
|
||||||
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1.0.0_x64.dmg
|
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1*_x64.dmg
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Clean up keychain
|
- name: Clean up keychain
|
||||||
@@ -81,10 +104,39 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||||
|
|
||||||
- name: Upload to release based on tag name
|
- id: create-release
|
||||||
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-connect/desktop/target/release/bundle/dmg/*.dmg
|
nym-connect/desktop/target/release/bundle/dmg/*.dmg
|
||||||
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
|
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
ref=${{ github.ref_name }}
|
||||||
|
semver="${ref##nym-connect-}" && semver="${semver##v}"
|
||||||
|
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "filename=nym-connect_${semver}_x64.dmg " >> "$GITHUB_OUTPUT"
|
||||||
|
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/dmg/nym-connect_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-tauri
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-tauri.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-tauri.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/nym-connect/desktop/CHANGELOG.md
|
||||||
|
archive_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-connect.app.tar.gz
|
||||||
|
sig_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-connect.app.tar.gz.sig
|
||||||
|
version: ${{ needs.publish-tauri.outputs.version }}
|
||||||
|
filename: ${{ needs.publish-tauri.outputs.filename }}
|
||||||
|
file_hash: ${{ needs.publish-tauri.outputs.file_hash }}
|
||||||
|
name: NymConnect
|
||||||
|
category: connect
|
||||||
|
platform: MacOS
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -15,8 +15,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [custom-runner-linux]
|
platform: [custom-runner-linux]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
@@ -26,19 +33,25 @@ jobs:
|
|||||||
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
shell: bash
|
||||||
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.1
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
@@ -48,18 +61,49 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||||
|
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: nym-connect.AppImage.tar.gz
|
name: nym-connect.AppImage.tar.gz
|
||||||
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1.0.0_amd64.AppImage
|
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1*_amd64.AppImage
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Upload to release based on tag name
|
- id: create-release
|
||||||
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
|
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
|
||||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
|
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
ref=${{ github.ref_name }}
|
||||||
|
semver="${ref##nym-connect-}" && semver="${semver##v}"
|
||||||
|
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "filename=nym-connect_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/appimage/nym-connect_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-tauri
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-tauri.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-tauri.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/nym-connect/desktop/CHANGELOG.md
|
||||||
|
archive_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-connect_${{ needs.publish-tauri.outputs.version }}_amd64.AppImage.tar.gz
|
||||||
|
sig_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-connect_${{ needs.publish-tauri.outputs.version }}_amd64.AppImage.tar.gz.sig
|
||||||
|
version: ${{ needs.publish-tauri.outputs.version }}
|
||||||
|
filename: ${{ needs.publish-tauri.outputs.filename }}
|
||||||
|
file_hash: ${{ needs.publish-tauri.outputs.file_hash }}
|
||||||
|
name: NymConnect
|
||||||
|
category: connect
|
||||||
|
platform: Ubuntu
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -15,8 +15,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [windows10]
|
platform: [windows10]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clean up first
|
- name: Clean up first
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -39,10 +46,10 @@ jobs:
|
|||||||
Remove-Item -path certificate -include tempCert.txt
|
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)
|
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
@@ -50,15 +57,21 @@ jobs:
|
|||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.1
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
shell: bash
|
||||||
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
|
shell: bash
|
||||||
run: yarn --network-timeout 100000
|
run: yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Build and sign it
|
- name: Build and sign it
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
@@ -66,19 +79,50 @@ jobs:
|
|||||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||||
|
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||||
run: yarn build
|
run: yarn build
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: nym-connect_1.0.0_x64_en-US.msi
|
name: nym-connect_1.0.0_x64_en-US.msi
|
||||||
path: nym-connect/desktop/target/release/bundle/msi/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
|
retention-days: 30
|
||||||
|
|
||||||
- name: Upload to release based on tag name
|
- id: create-release
|
||||||
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-connect/desktop/target/release/bundle/msi/*.msi
|
nym-connect/desktop/target/release/bundle/msi/*.msi
|
||||||
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
|
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
ref=${{ github.ref_name }}
|
||||||
|
semver="${ref##nym-connect-}" && semver="${semver##v}"
|
||||||
|
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "filename=nym-connect_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/msi/nym-connect_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-tauri
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-tauri.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-tauri.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/nym-connect/desktop/CHANGELOG.md
|
||||||
|
archive_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-connect_${{ needs.publish-tauri.outputs.version }}_x64_en-US.msi.zip
|
||||||
|
sig_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-connect_${{ needs.publish-tauri.outputs.version }}_x64_en-US.msi.zip.sig
|
||||||
|
version: ${{ needs.publish-tauri.outputs.version }}
|
||||||
|
filename: ${{ needs.publish-tauri.outputs.filename }}
|
||||||
|
file_hash: ${{ needs.publish-tauri.outputs.file_hash }}
|
||||||
|
name: NymConnect
|
||||||
|
category: connect
|
||||||
|
platform: Windows
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ name: Publish Nym binaries
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
add_tokio_unstable:
|
add_tokio_unstable:
|
||||||
description: 'True to add RUSTFLAGS="--cfg tokio_unstable"'
|
description: 'True to add RUSTFLAGS="--cfg tokio_unstable"'
|
||||||
required: true
|
required: true
|
||||||
default: false
|
default: false
|
||||||
type: boolean
|
type: boolean
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NETWORK: mainnet
|
NETWORK: mainnet
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-nym:
|
publish-nym:
|
||||||
@@ -21,15 +21,33 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [custom-runner-linux]
|
platform: [custom-runner-linux]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
client_hash: ${{ steps.binary-hashes.outputs.client_hash }}
|
||||||
|
mixnode_hash: ${{ steps.binary-hashes.outputs.mixnode_hash }}
|
||||||
|
gateway_hash: ${{ steps.binary-hashes.outputs.gateway_hash }}
|
||||||
|
socks5_hash: ${{ steps.binary-hashes.outputs.socks5_hash }}
|
||||||
|
netreq_hash: ${{ steps.binary-hashes.outputs.netreq_hash }}
|
||||||
|
cli_hash: ${{ steps.binary-hashes.outputs.cli_hash }}
|
||||||
|
netstat_hash: ${{ steps.binary-hashes.outputs.netstat_hash }}
|
||||||
|
client_version: ${{ steps.binary-versions.outputs.client_version }}
|
||||||
|
mixnode_version: ${{ steps.binary-versions.outputs.mixnode_version }}
|
||||||
|
gateway_version: ${{ steps.binary-versions.outputs.gateway_version }}
|
||||||
|
socks5_version: ${{ steps.binary-versions.outputs.socks5_version }}
|
||||||
|
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
|
||||||
|
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
|
||||||
|
netstat_version: ${{ steps.binary-versions.outputs.netstat_version }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Dependencies (Linux)
|
- 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 libudev-dev squashfs-tools
|
run: sudo apt-get update && sudo apt-get -y install ripgrep libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Sets env vars for tokio if set in manual dispatch inputs
|
- name: Sets env vars for tokio if set in manual dispatch inputs
|
||||||
run: |
|
run: |
|
||||||
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
|
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
|
||||||
@@ -62,7 +80,8 @@ jobs:
|
|||||||
target/release/nym-cli
|
target/release/nym-cli
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Upload to release based on tag name
|
- id: create-release
|
||||||
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
@@ -76,3 +95,150 @@ jobs:
|
|||||||
target/release/nym-network-requester
|
target/release/nym-network-requester
|
||||||
target/release/nym-network-statistics
|
target/release/nym-network-statistics
|
||||||
target/release/nym-cli
|
target/release/nym-cli
|
||||||
|
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
semver="${${{ github.ref_name }}##nym-binaries-}" && semver="${semver##v}"
|
||||||
|
echo "version=$semver" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- id: binary-hashes
|
||||||
|
name: Generate binary hashes
|
||||||
|
run: |
|
||||||
|
echo "client_hash=${{ hashFiles('target/release/nym-client') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "mixnode_hash=${{ hashFiles('target/release/nym-mixnode') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "gateway_hash=${{ hashFiles('target/release/nym-gateway') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "socks5_hash=${{ hashFiles('target/release/nym-socks5-client') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "netreq_hash=${{ hashFiles('target/release/nym-network-requester') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "cli_hash=${{ hashFiles('target/release/nym-cli') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "netstat_hash=${{ hashFiles('target/release/nym-network-statistics') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- id: binary-versions
|
||||||
|
name: Get binary versions
|
||||||
|
run: |
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' clients/native/Cargo.toml) && echo "client_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' mixnode/Cargo.toml) && echo "mixnode_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' gateway/Cargo.toml) && echo "gateway_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' clients/socks5/Cargo.toml) && echo "socks5_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' service-providers/network-requester/Cargo.toml) && echo "netreq_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' tools/nym-cli/Cargo.toml) && echo "cli_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
v=$(rg '^version = "(.*)"' -or '$1' service-providers/network-statistics/Cargo.toml) && echo "netstat_version=$v" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data-client:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.client_version }}
|
||||||
|
filename: nym-client
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.client_hash }}
|
||||||
|
name: Client
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
push-release-data-mixnode:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.mixnode_version }}
|
||||||
|
filename: nym-mixnode
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.mixnode_hash }}
|
||||||
|
name: Mixnode
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
push-release-data-gateway:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.gateway_version }}
|
||||||
|
filename: nym-gateway
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.gateway_hash }}
|
||||||
|
name: Gateway
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
push-release-data-socks5:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.socks5_version }}
|
||||||
|
filename: nym-socks5-client
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.socks5_hash }}
|
||||||
|
name: Socks5 Client
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
push-release-data-network-requester:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.netreq_version }}
|
||||||
|
filename: nym-network-requester
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.netreq_hash }}
|
||||||
|
name: Network Requester
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
push-release-data-cli:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.cli_version }}
|
||||||
|
filename: nym-cli
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.cli_hash }}
|
||||||
|
name: Cli
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
push-release-data-network-stat:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-nym
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-nym.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-nym.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/CHANGELOG.md
|
||||||
|
version: ${{ needs.publish-nym.outputs.netstat_version }}
|
||||||
|
filename: nym-network-statistics
|
||||||
|
file_hash: ${{ needs.publish-nym.outputs.netstat_hash }}
|
||||||
|
name: Network Statistics
|
||||||
|
category: binaries
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -15,15 +15,22 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [macos-latest]
|
platform: [macos-latest]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -51,11 +58,15 @@ jobs:
|
|||||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.1
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
shell: bash
|
||||||
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies and build it
|
- name: Install app dependencies and build it
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -80,11 +91,40 @@ jobs:
|
|||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
run: |
|
run: |
|
||||||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||||
|
- id: create-release
|
||||||
- name: Upload to release based on tag name
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/target/release/bundle/dmg/*.dmg
|
nym-wallet/target/release/bundle/dmg/*.dmg
|
||||||
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
|
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
|
||||||
|
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
ref=${{ github.ref_name }}
|
||||||
|
semver="${ref##nym-wallet-}" && semver="${semver##v}"
|
||||||
|
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "filename=nym-wallet_${semver}_x64.dmg" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/dmg/nym-wallet_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-tauri
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-tauri.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-tauri.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/nym-wallet/CHANGELOG.md
|
||||||
|
archive_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-wallet.app.tar.gz
|
||||||
|
sig_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-wallet.app.tar.gz.sig
|
||||||
|
version: ${{ needs.publish-tauri.outputs.version }}
|
||||||
|
filename: ${{ needs.publish-tauri.outputs.filename }}
|
||||||
|
file_hash: ${{ needs.publish-tauri.outputs.file_hash }}
|
||||||
|
name: Wallet
|
||||||
|
category: wallet
|
||||||
|
platform: MacOS
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
name: Publish Nym Wallet (Ubuntu)
|
name: Publish Nym Wallet (Ubuntu)
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
@@ -14,8 +15,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [custom-runner-linux]
|
platform: [custom-runner-linux]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
@@ -25,19 +33,24 @@ jobs:
|
|||||||
sudo apt-get install -y webkit2gtk-4.0
|
sudo apt-get install -y webkit2gtk-4.0
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
shell: bash
|
||||||
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.1
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
@@ -47,9 +60,48 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
- name: Upload to release based on tag name
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: nym-wallet_1.0.0_amd64.AppImage.tar.gz
|
||||||
|
path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- id: create-release
|
||||||
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage
|
nym-wallet/target/release/bundle/appimage/*.AppImage
|
||||||
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
|
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||||
|
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
ref=${{ github.ref_name }}
|
||||||
|
semver="${ref##nym-wallet-}" && semver="${semver##v}"
|
||||||
|
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "filename=nym-wallet_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/appimage/nym-wallet_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-tauri
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-tauri.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-tauri.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/nym-wallet/CHANGELOG.md
|
||||||
|
archive_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-wallet_${{ needs.publish-tauri.outputs.version }}_amd64.AppImage.tar.gz
|
||||||
|
sig_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-wallet_${{ needs.publish-tauri.outputs.version }}_amd64.AppImage.tar.gz.sig
|
||||||
|
version: ${{ needs.publish-tauri.outputs.version }}
|
||||||
|
filename: ${{ needs.publish-tauri.outputs.filename }}
|
||||||
|
file_hash: ${{ needs.publish-tauri.outputs.file_hash }}
|
||||||
|
name: Wallet
|
||||||
|
category: wallet
|
||||||
|
platform: Ubuntu
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -15,8 +15,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [windows10]
|
platform: [windows10]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.id }}
|
||||||
|
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||||
|
version: ${{ steps.release-info.outputs.version }}
|
||||||
|
filename: ${{ steps.release-info.outputs.filename }}
|
||||||
|
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clean up first
|
- name: Clean up first
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -39,10 +46,10 @@ jobs:
|
|||||||
Remove-Item -path certificate -include tempCert.txt
|
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)
|
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
@@ -50,15 +57,21 @@ jobs:
|
|||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.1
|
uses: timheuer/base64-to-file@v1.2
|
||||||
with:
|
with:
|
||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
shell: bash
|
||||||
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
|
shell: bash
|
||||||
run: yarn --network-timeout 100000
|
run: yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Build and sign it
|
- name: Build and sign it
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
@@ -75,10 +88,40 @@ jobs:
|
|||||||
path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi
|
path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Upload to release based on tag name
|
- id: create-release
|
||||||
|
name: Upload to release based on tag name
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
nym-wallet/target/release/bundle/msi/*.msi
|
nym-wallet/target/release/bundle/msi/*.msi
|
||||||
nym-wallet/target/release/bundle/msi/*.msi.zip*
|
nym-wallet/target/release/bundle/msi/*.msi.zip*
|
||||||
|
|
||||||
|
- id: release-info
|
||||||
|
name: Prepare release info
|
||||||
|
run: |
|
||||||
|
ref=${{ github.ref_name }}
|
||||||
|
semver="${ref##nym-wallet-}" && semver="${semver##v}"
|
||||||
|
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "filename=nym-wallet_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/msi/nym-wallet_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
push-release-data:
|
||||||
|
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/push-release-data.yml
|
||||||
|
needs: publish-tauri
|
||||||
|
with:
|
||||||
|
release_tag: ${{ github.ref_name }}
|
||||||
|
release_id: ${{ needs.publish-tauri.outputs.release_id }}
|
||||||
|
release_date: ${{ needs.publish-tauri.outputs.release_date }}
|
||||||
|
download_base_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}
|
||||||
|
changelog_url: https://github.com/nymtech/nym/blob/${{ github.ref_name }}/nym-wallet/CHANGELOG.md
|
||||||
|
archive_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-wallet_${{ needs.publish-tauri.outputs.version }}_x64_en-US.msi.zip
|
||||||
|
sig_url: https://github.com/nymtech/nym/releases/download/${{ github.ref_name }}/nym-wallet_${{ needs.publish-tauri.outputs.version }}_x64_en-US.msi.zip.sig
|
||||||
|
version: ${{ needs.publish-tauri.outputs.version }}
|
||||||
|
filename: ${{ needs.publish-tauri.outputs.filename }}
|
||||||
|
file_hash: ${{ needs.publish-tauri.outputs.file_hash }}
|
||||||
|
name: Wallet
|
||||||
|
category: wallet
|
||||||
|
platform: Windows
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -16,9 +16,15 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Setup yarn
|
- name: Setup yarn
|
||||||
run: npm install -g 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: Build dependencies
|
- name: Build dependencies
|
||||||
run: yarn && yarn build
|
run: yarn && yarn build
|
||||||
- name: Build storybook
|
- name: Build storybook
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ jobs:
|
|||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Node v16
|
- name: Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Install yarn for building application
|
- name: Install yarn for building application
|
||||||
run: yarn install
|
run: yarn install
|
||||||
|
|||||||
@@ -68,8 +68,10 @@ jobs:
|
|||||||
working-directory: nym-connect/native/android
|
working-directory: nym-connect/native/android
|
||||||
env:
|
env:
|
||||||
ANDROID_SDK_ROOT: ${{ env.ANDROID_HOME }}
|
ANDROID_SDK_ROOT: ${{ env.ANDROID_HOME }}
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.NYMS5_ANDROID_SENTRY_AUTH_TOKEN }}
|
||||||
# build for arm64 and x86_64
|
# build for arm64 and x86_64
|
||||||
run: |
|
run: |
|
||||||
|
echo "auth.token=$SENTRY_AUTH_TOKEN" | tee -a sentry.properties
|
||||||
./gradlew :app:assembleArch64Debug
|
./gradlew :app:assembleArch64Debug
|
||||||
./gradlew :app:assembleArch64Release
|
./gradlew :app:assembleArch64Release
|
||||||
|
|
||||||
@@ -107,4 +109,3 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
apk/nyms5-arch64-debug.apk
|
apk/nyms5-arch64-debug.apk
|
||||||
apk/nyms5-arch64-release.apk
|
apk/nyms5-arch64-release.apk
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
name: Push release data
|
||||||
|
|
||||||
|
env:
|
||||||
|
strapi_download_url: 'https://strapi.feat-nym-update-nym-web.websites.dev.nymte.ch/api/downloaders'
|
||||||
|
strapi_updater_url: 'https://strapi.feat-nym-update-nym-web.websites.dev.nymte.ch/api/updaters'
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
release_tag:
|
||||||
|
required: true
|
||||||
|
description: Release tag
|
||||||
|
type: string
|
||||||
|
release_id:
|
||||||
|
required: true
|
||||||
|
description: Release ID
|
||||||
|
type: string
|
||||||
|
release_date:
|
||||||
|
required: true
|
||||||
|
description: Release date
|
||||||
|
type: string
|
||||||
|
download_base_url:
|
||||||
|
required: true
|
||||||
|
description: Download base URL
|
||||||
|
type: string
|
||||||
|
changelog_url:
|
||||||
|
required: true
|
||||||
|
description: Changelog URL
|
||||||
|
type: string
|
||||||
|
archive_url:
|
||||||
|
required: false
|
||||||
|
description: Binary archive URL
|
||||||
|
type: string
|
||||||
|
sig_url:
|
||||||
|
required: false
|
||||||
|
description: Archive signature URL
|
||||||
|
type: string
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
description: Release version (semver)
|
||||||
|
type: string
|
||||||
|
filename:
|
||||||
|
required: true
|
||||||
|
description: Binary file name
|
||||||
|
type: string
|
||||||
|
file_hash:
|
||||||
|
required: true
|
||||||
|
description: Binary hash (sha256)
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
required: true
|
||||||
|
description: Name
|
||||||
|
type: string
|
||||||
|
category:
|
||||||
|
required: true
|
||||||
|
description: Category
|
||||||
|
type: string
|
||||||
|
platform:
|
||||||
|
required: false
|
||||||
|
description: Platform
|
||||||
|
type: string
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
# ⚠ since inputs are limited to 10 max for workflow_dispatch
|
||||||
|
# some properties were omitted
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
description: Release version (semver)
|
||||||
|
type: string
|
||||||
|
default: '1.0.0'
|
||||||
|
release_id:
|
||||||
|
required: true
|
||||||
|
description: Release ID
|
||||||
|
type: string
|
||||||
|
default: '1234'
|
||||||
|
release_date:
|
||||||
|
required: true
|
||||||
|
description: Release date
|
||||||
|
type: string
|
||||||
|
default: '2023-06-26T10:09:16Z'
|
||||||
|
download_base_url:
|
||||||
|
required: true
|
||||||
|
description: Download base URL
|
||||||
|
type: string
|
||||||
|
default: 'https://github.com/nymtech/nym/releases/download/nym-wallet-v1.0.0'
|
||||||
|
changelog_url:
|
||||||
|
required: true
|
||||||
|
description: Changelog URL
|
||||||
|
type: string
|
||||||
|
default: 'https://github.com/nymtech/nym/blob/nym-wallet-v1.0.0/nym-wallet/CHANGELOG.md'
|
||||||
|
filename:
|
||||||
|
required: true
|
||||||
|
description: Binary file name
|
||||||
|
type: string
|
||||||
|
default: 'nym-wallet_1.0.0_amd64.AppImage'
|
||||||
|
file_hash:
|
||||||
|
required: true
|
||||||
|
description: Binary hash (sha256)
|
||||||
|
type: string
|
||||||
|
default: 'xxx'
|
||||||
|
name:
|
||||||
|
required: true
|
||||||
|
description: Name
|
||||||
|
type: string
|
||||||
|
default: 'Wallet'
|
||||||
|
category:
|
||||||
|
required: true
|
||||||
|
description: Category
|
||||||
|
default: 'wallet'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- wallet
|
||||||
|
- connect
|
||||||
|
- binaries
|
||||||
|
platform:
|
||||||
|
required: false
|
||||||
|
description: Platform
|
||||||
|
default: 'Ubuntu'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- Ubuntu
|
||||||
|
- Windows
|
||||||
|
- MacOS
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push-download-data:
|
||||||
|
name: Push download data to Strapi
|
||||||
|
runs-on: custom-runner-linux
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Release info
|
||||||
|
run: |
|
||||||
|
echo "version: ${{ inputs.version }}"
|
||||||
|
echo "tag: ${{ inputs.release_tag }}"
|
||||||
|
|
||||||
|
- id: get_sig
|
||||||
|
name: Get sig
|
||||||
|
if: ${{ inputs.sig_url != null }}
|
||||||
|
run: |
|
||||||
|
output=$(curl -LsSf ${{ inputs.sig_url }})
|
||||||
|
echo "sig=$output" >> "$GITHUB_OUTPUT"
|
||||||
|
- id: strapi-request
|
||||||
|
name: Strapi request
|
||||||
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
with:
|
||||||
|
url: ${{ env.strapi_download_url }}
|
||||||
|
method: 'POST'
|
||||||
|
bearerToken: ${{ secrets.STRAPI_API_TOKEN_RELEASES }}
|
||||||
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
|
data: |
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"releaseId": "${{ inputs.release_id }}",
|
||||||
|
"releaseDate": "${{ inputs.release_date }}",
|
||||||
|
"downloadBaseUrl": "${{ inputs.download_base_url }}",
|
||||||
|
"changelogUrl": "${{ inputs.changelog_url }}",
|
||||||
|
"version": "${{ inputs.version }}",
|
||||||
|
"filename": "${{ inputs.filename }}",
|
||||||
|
"name": "${{ inputs.name }}",
|
||||||
|
"category": "${{ inputs.category }}",
|
||||||
|
"platform": "${{ inputs.platform }}",
|
||||||
|
"sha256": "${{ inputs.file_hash }}",
|
||||||
|
"sig": "${{ steps.get_sig.outputs.sig }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- name: Strapi Response
|
||||||
|
run: |
|
||||||
|
echo ${{ steps.strapi-request.outputs.response }}
|
||||||
|
|
||||||
|
push-update-data:
|
||||||
|
name: Push update data to Strapi
|
||||||
|
runs-on: custom-runner-linux
|
||||||
|
# only push update data for tauri apps (desktop wallet and NC)
|
||||||
|
if: ${{ inputs.category == 'wallet' || inputs.category == 'connect' }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Release info
|
||||||
|
run: |
|
||||||
|
echo "version: ${{ inputs.version }}"
|
||||||
|
echo "tag: ${{ inputs.release_tag }}"
|
||||||
|
- id: get_sig
|
||||||
|
name: Get sig
|
||||||
|
if: ${{ inputs.sig_url != null }}
|
||||||
|
run: |
|
||||||
|
output=$(curl -LsSf ${{ inputs.sig_url }})
|
||||||
|
echo "sig=$output" >> "$GITHUB_OUTPUT"
|
||||||
|
- id: strapi-request
|
||||||
|
name: Strapi request
|
||||||
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
with:
|
||||||
|
url: ${{ env.strapi_updater_url }}
|
||||||
|
method: 'POST'
|
||||||
|
bearerToken: ${{ secrets.STRAPI_API_TOKEN_RELEASES }}
|
||||||
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
|
data: |
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"releaseId": "${{ inputs.release_id }}",
|
||||||
|
"releaseDate": "${{ inputs.release_date }}",
|
||||||
|
"downloadUrl": "${{ inputs.archive_url }}",
|
||||||
|
"changelog": "See ${{ inputs.changelog_url }} for the changelog",
|
||||||
|
"version": "${{ inputs.version }}",
|
||||||
|
"filename": "${{ inputs.filename }}",
|
||||||
|
"category": "${{ inputs.category }}",
|
||||||
|
"platform": "${{ inputs.platform }}",
|
||||||
|
"sha256": "${{ inputs.file_hash }}",
|
||||||
|
"sig": "${{ steps.get_sig.outputs.sig }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- name: Strapi Response
|
||||||
|
run: |
|
||||||
|
echo ${{ steps.strapi-request.outputs.response }}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
name: Typescript SDK docs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "sdk/typescript/**"
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "sdk/typescript/**"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: custom-runner-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 Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
|
- name: Install
|
||||||
|
run: yarn
|
||||||
|
- name: Matrix - Node Install
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files
|
||||||
|
- name: Matrix - Send Notification
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: ts-packages
|
||||||
|
NYM_PROJECT_NAME: "ts-packages"
|
||||||
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||||
|
NYM_CI_WWW_LOCATION: "ts-${{ 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
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
name: Publish SDK to NPM
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: [custom-runner-linux]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
|
- name: Setup 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 dependencies
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
- name: Build and publish
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||||
|
working-directory: ./sdk/typescript/packages/sdk
|
||||||
|
run: scripts/publish.sh
|
||||||
@@ -1 +1 @@
|
|||||||
16
|
18
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ async function addToContextAndValidate(context) {
|
|||||||
async function getMessageBody(context) {
|
async function getMessageBody(context) {
|
||||||
try {
|
try {
|
||||||
const source = fs
|
const source = fs
|
||||||
.readFileSync("deny.message").toString();
|
.readFileSync("./notifications/deny.message").toString();
|
||||||
return source;
|
return source;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
@@ -3,62 +3,70 @@ name: CI for linting Typescript
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- 'ts-packages/**'
|
- "ts-packages/**"
|
||||||
- 'sdk/typescript/**'
|
- "sdk/typescript/**"
|
||||||
- 'nym-connect/desktop/src/**'
|
- "nym-connect/desktop/src/**"
|
||||||
- 'nym-connect/desktop/package.json'
|
- "nym-connect/desktop/package.json"
|
||||||
- 'nym-connect/mobile/src/**'
|
- "nym-connect/mobile/src/**"
|
||||||
- 'nym-connect/mobile/package.json'
|
- "nym-connect/mobile/package.json"
|
||||||
- 'nym-wallet/src/**'
|
- "nym-wallet/src/**"
|
||||||
- 'nym-wallet/package.json'
|
- "nym-wallet/package.json"
|
||||||
|
- "explorer/**"
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'ts-packages/**'
|
- "ts-packages/**"
|
||||||
- 'sdk/typescript/**'
|
- "sdk/typescript/**"
|
||||||
- 'nym-connect/desktop/src/**'
|
- "nym-connect/desktop/src/**"
|
||||||
- 'nym-connect/desktop/package.json'
|
- "nym-connect/desktop/package.json"
|
||||||
- 'nym-connect/mobile/src/**'
|
- "nym-connect/mobile/src/**"
|
||||||
- 'nym-connect/mobile/package.json'
|
- "nym-connect/mobile/package.json"
|
||||||
- 'nym-wallet/src/**'
|
- "nym-wallet/src/**"
|
||||||
- 'nym-wallet/package.json'
|
- "nym-wallet/package.json"
|
||||||
|
- "explorer/**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: custom-runner-linux
|
runs-on: custom-runner-linux
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install rsync
|
- name: Install rsync
|
||||||
run: sudo apt-get install rsync
|
run: sudo apt-get install rsync
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- name: Setup yarn
|
- name: Install Rust stable
|
||||||
run: npm install -g yarn
|
uses: actions-rs/toolchain@v1
|
||||||
- name: Install
|
with:
|
||||||
run: yarn
|
toolchain: stable
|
||||||
- name: Build packages
|
- name: Install wasm-pack
|
||||||
run: yarn build
|
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
- name: Lint
|
- name: Setup yarn
|
||||||
run: yarn lint && yarn tsc
|
run: npm install -g yarn
|
||||||
- name: Matrix - Node Install
|
- name: Install
|
||||||
run: npm install
|
run: yarn
|
||||||
working-directory: .github/workflows/support-files
|
- name: Build packages
|
||||||
- name: Matrix - Send Notification
|
run: yarn build
|
||||||
env:
|
- name: Lint
|
||||||
NYM_NOTIFICATION_KIND: ts-packages
|
run: yarn lint && yarn tsc
|
||||||
NYM_PROJECT_NAME: "ts-packages"
|
- name: Matrix - Node Install
|
||||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
run: npm install
|
||||||
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
|
working-directory: .github/workflows/support-files
|
||||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
- name: Matrix - Send Notification
|
||||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
env:
|
||||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
NYM_NOTIFICATION_KIND: ts-packages
|
||||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
NYM_PROJECT_NAME: "ts-packages"
|
||||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
|
||||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||||
uses: docker://keybaseio/client:stable-node
|
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||||
with:
|
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
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
|
||||||
|
|||||||
+50
-1
@@ -4,9 +4,58 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [v1.1.24] (2023-08-08)
|
||||||
|
|
||||||
|
- Latency based gateway selection is serial and slow ([#3710])
|
||||||
|
- Network-requester: strip comments from allow lists ([#3625])
|
||||||
|
- Remove (or start maintaining) `upgrade` commands from all binaries ([#3600])
|
||||||
|
- Set sphinx as default packet type ([#3748])
|
||||||
|
- Apply fix from feature/ephemera to develop too (#3698) ([#3742])
|
||||||
|
- Feature/coco demos ([#3732])
|
||||||
|
- Add updates to community list projects ([#3722])
|
||||||
|
- Add geo-aware mixnet topology provider ([#3713])
|
||||||
|
- Add updates to community list projects ([#3711])
|
||||||
|
|
||||||
|
[#3710]: https://github.com/nymtech/nym/issues/3710
|
||||||
|
[#3625]: https://github.com/nymtech/nym/issues/3625
|
||||||
|
[#3600]: https://github.com/nymtech/nym/issues/3600
|
||||||
|
[#3748]: https://github.com/nymtech/nym/pull/3748
|
||||||
|
[#3742]: https://github.com/nymtech/nym/pull/3742
|
||||||
|
[#3732]: https://github.com/nymtech/nym/pull/3732
|
||||||
|
[#3722]: https://github.com/nymtech/nym/pull/3722
|
||||||
|
[#3713]: https://github.com/nymtech/nym/pull/3713
|
||||||
|
[#3711]: https://github.com/nymtech/nym/pull/3711
|
||||||
|
|
||||||
|
## [v1.1.23] (2023-07-04)
|
||||||
|
|
||||||
|
- nym-cli: add client identity key signing support ([#3576])
|
||||||
|
- Feature/node tester package ([#3634])
|
||||||
|
- Add medium toggle to socks5 client ([#3615])
|
||||||
|
- Don't fully turn off background task when cover traffic is disabled ([#3596])
|
||||||
|
|
||||||
|
[#3576]: https://github.com/nymtech/nym/issues/3576
|
||||||
|
[#3634]: https://github.com/nymtech/nym/pull/3634
|
||||||
|
[#3615]: https://github.com/nymtech/nym/pull/3615
|
||||||
|
[#3596]: https://github.com/nymtech/nym/pull/3596
|
||||||
|
|
||||||
|
## [v1.1.22] (2023-06-20)
|
||||||
|
|
||||||
|
- CLI tool for querying network-requesters ([#3539])
|
||||||
|
- Statically link OpenSSL ([#3510])
|
||||||
|
- NymConnect - add sentry.io reporting ([#3421])
|
||||||
|
- init command does not change version number in config.toml ([#3336])
|
||||||
|
- [Bug] Config version does not correspond to binary version ([#3434])
|
||||||
|
|
||||||
|
[#3539]: https://github.com/nymtech/nym/issues/3539
|
||||||
|
[#3510]: https://github.com/nymtech/nym/issues/3510
|
||||||
|
[#3421]: https://github.com/nymtech/nym/issues/3421
|
||||||
|
[#3336]: https://github.com/nymtech/nym/issues/3336
|
||||||
|
[#3434]: https://github.com/nymtech/nym/issues/3434
|
||||||
|
|
||||||
## [v1.1.21] (2023-06-13)
|
## [v1.1.21] (2023-06-13)
|
||||||
|
|
||||||
- mixFetch: Change socks5 `SendRequest` to include OrderedMessage index as a field rather than making it serialized inside the `data` field
|
- mixFetch: Change socks5 `SendRequest` to include OrderedMessage index as a field rather than making it serialized inside the `data` field
|
||||||
|
([#3534])
|
||||||
- Explorer - add more data columns to the Service Provider section: ([#3474])
|
- Explorer - add more data columns to the Service Provider section: ([#3474])
|
||||||
- network-requester: support report if they run an open proxy using `ControlRequest` API ([#3461])
|
- network-requester: support report if they run an open proxy using `ControlRequest` API ([#3461])
|
||||||
- Refactor client configs (London discussion) ([#3444])
|
- Refactor client configs (London discussion) ([#3444])
|
||||||
|
|||||||
Generated
+523
-301
File diff suppressed because it is too large
Load Diff
+23
-12
@@ -74,6 +74,7 @@ members = [
|
|||||||
"common/types",
|
"common/types",
|
||||||
"common/wasm-utils",
|
"common/wasm-utils",
|
||||||
"explorer-api",
|
"explorer-api",
|
||||||
|
"explorer-api/explorer-api-requests",
|
||||||
"gateway",
|
"gateway",
|
||||||
"gateway/gateway-requests",
|
"gateway/gateway-requests",
|
||||||
"integrations/bity",
|
"integrations/bity",
|
||||||
@@ -102,7 +103,7 @@ default-members = [
|
|||||||
"explorer-api",
|
"explorer-api",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"]
|
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-browser-extension/storage", "cpu-cycles"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
authors = ["Nym Technologies SA"]
|
authors = ["Nym Technologies SA"]
|
||||||
@@ -117,28 +118,38 @@ anyhow = "1.0.71"
|
|||||||
async-trait = "0.1.64"
|
async-trait = "0.1.64"
|
||||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
cosmwasm-derive = "=1.0.0"
|
cosmwasm-derive = "=1.3.0"
|
||||||
cosmwasm-schema = "=1.0.0"
|
cosmwasm-schema = "=1.3.0"
|
||||||
cosmwasm-std = "=1.0.0"
|
cosmwasm-std = "=1.3.0"
|
||||||
cosmwasm-storage = "=1.0.0"
|
# use 0.5.0 as that's the version used by cosmwasm-std 1.3.0
|
||||||
cw-controllers = "=0.13.4"
|
# (and ideally we don't want to pull the same dependency twice)
|
||||||
cw-storage-plus = "=0.13.4"
|
serde-json-wasm = "=0.5.0"
|
||||||
cw-utils = "=0.13.4"
|
cosmwasm-storage = "=1.3.0"
|
||||||
cw2 = { version = "=0.13.4" }
|
cosmrs = "=0.14.0"
|
||||||
cw3 = { version = "=0.13.4" }
|
# same version as used by cosmrs
|
||||||
cw3-fixed-multisig = { version = "=0.13.4" }
|
cw-utils = "=1.0.1"
|
||||||
cw4 = { version = "=0.13.4" }
|
cw-storage-plus = "=1.1.0"
|
||||||
|
cw2 = { version = "=1.1.0" }
|
||||||
|
cw3 = { version = "=1.1.0" }
|
||||||
|
cw4 = { version = "=1.1.0" }
|
||||||
|
cw-controllers = { version = "=1.1.0" }
|
||||||
dotenvy = "0.15.6"
|
dotenvy = "0.15.6"
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
getrandom = "0.2.10"
|
getrandom = "0.2.10"
|
||||||
|
k256 = "0.13"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
once_cell = "1.7.2"
|
once_cell = "1.7.2"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
reqwest = "0.11.18"
|
||||||
serde = "1.0.152"
|
serde = "1.0.152"
|
||||||
serde_json = "1.0.91"
|
serde_json = "1.0.91"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
|
tendermint-rpc = "0.32" # same version as used by cosmrs
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.38"
|
||||||
tokio = "1.24.1"
|
tokio = "1.24.1"
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
zeroize = "1.6.0"
|
zeroize = "1.6.0"
|
||||||
|
|
||||||
|
# wasm-related dependencies
|
||||||
|
wasmtimer = "0.2.0"
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ endef
|
|||||||
# Generate targets for the various cargo workspaces
|
# Generate targets for the various cargo workspaces
|
||||||
|
|
||||||
$(eval $(call add_cargo_workspace,main,.))
|
$(eval $(call add_cargo_workspace,main,.))
|
||||||
$(eval $(call add_cargo_workspace,contracts,contracts,--target wasm32-unknown-unknown))
|
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown))
|
||||||
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
|
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
|
||||||
$(eval $(call add_cargo_workspace,wallet,nym-wallet,))
|
$(eval $(call add_cargo_workspace,wallet,nym-wallet,))
|
||||||
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
|
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
|
||||||
@@ -104,7 +104,7 @@ NAME_SERVICE_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_name_service.wasm
|
|||||||
wasm: wasm-build wasm-opt
|
wasm: wasm-build wasm-opt
|
||||||
|
|
||||||
wasm-build:
|
wasm-build:
|
||||||
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
|
RUSTFLAGS='-C link-arg=-s' cargo build --lib --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
|
||||||
|
|
||||||
wasm-opt:
|
wasm-opt:
|
||||||
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
|
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
|
||||||
@@ -112,6 +112,9 @@ wasm-opt:
|
|||||||
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
|
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
|
||||||
wasm-opt --disable-sign-ext -Os $(NAME_SERVICE_CONTRACT) -o $(NAME_SERVICE_CONTRACT)
|
wasm-opt --disable-sign-ext -Os $(NAME_SERVICE_CONTRACT) -o $(NAME_SERVICE_CONTRACT)
|
||||||
|
|
||||||
|
contract-schema:
|
||||||
|
$(MAKE) -C contracts schema
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Misc
|
# Misc
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
|||||||
* 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-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-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-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-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||||
|
|
||||||
[](https://opensource.org/licenses/Apache-2.0)
|
[](https://opensource.org/licenses/Apache-2.0)
|
||||||
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
||||||
@@ -21,7 +21,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
|||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/build-nym.html).
|
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).
|
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||||
|
|
||||||
### Developing
|
### Developing
|
||||||
@@ -32,9 +32,9 @@ For Typescript components, please see [ts-packages](./ts-packages).
|
|||||||
|
|
||||||
### Developer chat
|
### 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.
|
> 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:
|
You can chat to us in two places:
|
||||||
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
|
* 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://discord.gg/nym)
|
||||||
|
|
||||||
@@ -84,4 +84,3 @@ where `s'` is stake `s` scaled over total token circulating supply.
|
|||||||
### Licensing and copyright information
|
### Licensing and copyright information
|
||||||
|
|
||||||
This program is available as open source under the terms of the Apache 2.0 license. However, some elements are being licensed under CC0-1.0 and MIT. For accurate information, please check individual files.
|
This program is available as open source under the terms of the Apache 2.0 license. However, some elements are being licensed under CC0-1.0 and MIT. For accurate information, please check individual files.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<svg
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
viewBox="0 0 80 80"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g clip-path="url(#clip0_421_13045)">
|
||||||
|
<path
|
||||||
|
d="M40 80C62.0914 80 80 62.0914 80 40C80 17.9086 62.0914 0 40 0C17.9086 0 0 17.9086 0 40C0 62.0914 17.9086 80 40 80Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M40 77.2636C60.5801 77.2636 77.2636 60.5801 77.2636 40C77.2636 19.4199 60.5801 2.73645 40 2.73645C19.4199 2.73645 2.73645 19.4199 2.73645 40C2.73645 60.5801 19.4199 77.2636 40 77.2636Z"
|
||||||
|
fill="white"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M24.0224 32.471H23.9776V32.5084V45.5775L18.4673 32.4934L18.4598 32.471H18.4299H15.3047H11.7981H11.7607V32.5084V47.4916V47.529H11.7981H15.3047H15.3421V47.4916V34.4L20.8748 47.5065L20.8822 47.529H20.9121H24.0224H27.5215H27.5589V47.4916V32.5084V32.471H27.5215H24.0224Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M23.8965 32.39H27.64V47.6101H20.8238L20.7989 47.5352L15.4232 34.8006V47.6101H11.6797V32.39H18.5183L18.5432 32.4649L23.8965 45.1761V32.39ZM23.9776 45.5776L18.4673 32.4935L18.4598 32.471H11.7608V47.529H15.3421V34.4L20.8748 47.5065L20.8823 47.529H27.5589V32.471H23.9776V45.5776Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M68.2019 32.471H61.5178H61.4804L61.4729 32.5009L58.0486 45.6374L54.6169 32.5009L54.6094 32.471H54.5795H47.8804H47.8355V32.5084V47.4916V47.529H47.8804H51.3795H51.4169V47.4916V34.5047L54.8038 47.499L54.8112 47.529H54.8486H61.2337H61.2636L61.2711 47.499L64.658 34.5047V47.4916V47.529H64.6954H68.2019H68.2393V47.4916V32.5084V32.471H68.2019Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M61.4171 32.39H68.3204V47.6101H64.5769V35.1372L61.3497 47.5187L61.3495 47.5195L61.3269 47.6101H54.7479L54.7253 47.5195L54.7251 47.5187L51.4979 35.1372V47.6101H47.7545V32.39H54.6727L54.6953 32.4804L54.6955 32.4813L58.0485 45.3163L61.3943 32.4813L61.3945 32.4805L61.4171 32.39ZM58.0486 45.6374L54.6168 32.5009L54.6094 32.471H47.8355V47.529H51.4168V34.5047L54.8038 47.4991L54.8112 47.529H61.2636L61.2711 47.4991L64.658 34.5047V47.529H68.2393V32.471H61.4804L61.4729 32.5009L58.0486 45.6374Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M42.0711 32.471H42.0486L42.0412 32.486L37.7869 39.8804L33.5103 32.486L33.5028 32.471H33.4804H29.4355H29.3608L29.3982 32.5308L35.9851 43.9402V47.4916V47.529H36.0225H39.529H39.5664V47.4916V43.9402L46.1533 32.5308L46.1907 32.471H46.1159H42.0711Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M41.9985 32.39H46.337L46.2228 32.5726L39.6475 43.9619V47.6101H35.904V43.9619L29.3286 32.5726L29.2145 32.39H33.5529L33.5817 32.4475L37.7868 39.7181L41.9697 32.4476L41.9985 32.39ZM42.0411 32.486L37.7869 39.8804L33.5103 32.486L33.5028 32.471H29.3608L29.3981 32.5308L35.9851 43.9402V47.529H39.5664V43.9402L46.1533 32.5308L46.1907 32.471H42.0486L42.0411 32.486Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_421_13045">
|
||||||
|
<rect width="80" height="80" fill="white" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -21,5 +21,5 @@ nym-credential-storage = { path = "../../common/credential-storage" }
|
|||||||
nym-bin-common = { path = "../../common/bin-common"}
|
nym-bin-common = { path = "../../common/bin-common"}
|
||||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||||
nym-pemstore = { path = "../../common/pemstore" }
|
nym-pemstore = { path = "../../common/pemstore" }
|
||||||
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
|
nym-validator-client = { path = "../../common/client-libs/validator-client" }
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ The credential binary is still experimental software. The infrastructure for usi
|
|||||||
|
|
||||||
From the project's root directory, run:
|
From the project's root directory, run:
|
||||||
```
|
```
|
||||||
cargo build -p credential
|
cargo build -p nym-credential-client
|
||||||
```
|
```
|
||||||
which generates the `credential` binary in `target/debug/credential`.
|
which generates the `nym-credential-client` binary in `target/debug/nym-credential-client`.
|
||||||
|
|
||||||
|
|
||||||
### Running
|
### Running
|
||||||
@@ -25,7 +25,7 @@ which generates the `credential` binary in `target/debug/credential`.
|
|||||||
For example, you can get a credential worth 3 nym (3000000 unym) in a socks5 client that was already initialized like so:
|
For example, you can get a credential worth 3 nym (3000000 unym) in a socks5 client that was already initialized like so:
|
||||||
|
|
||||||
```
|
```
|
||||||
./target/debug/credential --config-env-file envs/sandbox.env --client-home-directory ~/.nym/socks5-clients/cred_client --nyxd-url https://sandbox-validator1.nymtech.net --mnemonic $MNEMONIC --recovery-dir /tmp/recovery --amount 3000000
|
./target/debug/nym-credential-client --config-env-file envs/sandbox.env --client-home-directory ~/.nym/socks5-clients/cred_client --nyxd-url https://sandbox-validator1.nymtech.net --mnemonic $MNEMONIC --recovery-dir /tmp/recovery --amount 3000000
|
||||||
```
|
```
|
||||||
|
|
||||||
More information regarding how to run the binary can be found by running it with the `--help` argument.
|
More information regarding how to run the binary can be found by running it with the `--help` argument.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.21"
|
version = "1.1.24"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
description = "Implementation of the Nym Client"
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -48,7 +48,7 @@ nym-sphinx = { path = "../../common/nymsphinx" }
|
|||||||
nym-pemstore = { path = "../../common/pemstore" }
|
nym-pemstore = { path = "../../common/pemstore" }
|
||||||
nym-task = { path = "../../common/task" }
|
nym-task = { path = "../../common/task" }
|
||||||
nym-topology = { path = "../../common/topology" }
|
nym-topology = { path = "../../common/topology" }
|
||||||
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
|
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
|
||||||
nym-client-websocket-requests = { path = "websocket-requests" }
|
nym-client-websocket-requests = { path = "websocket-requests" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use clap::Args;
|
||||||
|
use nym_bin_common::bin_info_owned;
|
||||||
|
use nym_bin_common::output_format::OutputFormat;
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
pub(crate) struct BuildInfo {
|
||||||
|
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||||
|
output: OutputFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn execute(args: BuildInfo) {
|
||||||
|
println!("{}", args.output.format(&bin_info_owned!()))
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ use clap::CommandFactory;
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use nym_bin_common::build_information::BinaryBuildInformation;
|
use nym_bin_common::bin_info;
|
||||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||||
use nym_client_core::client::base_client::storage::gateway_details::{
|
use nym_client_core::client::base_client::storage::gateway_details::{
|
||||||
OnDiskGatewayDetails, PersistedGatewayDetails,
|
OnDiskGatewayDetails, PersistedGatewayDetails,
|
||||||
@@ -22,13 +22,12 @@ use nym_config::OptionalSet;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
|
|
||||||
|
pub(crate) mod build_info;
|
||||||
pub(crate) mod init;
|
pub(crate) mod init;
|
||||||
pub(crate) mod run;
|
pub(crate) mod run;
|
||||||
pub(crate) mod upgrade;
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
|
||||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for passing LONG_VERSION to clap
|
// Helper for passing LONG_VERSION to clap
|
||||||
@@ -43,6 +42,10 @@ pub(crate) struct Cli {
|
|||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||||
|
|
||||||
|
/// Flag used for disabling the printed banner in tty.
|
||||||
|
#[clap(long)]
|
||||||
|
pub(crate) no_banner: bool,
|
||||||
|
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Commands,
|
command: Commands,
|
||||||
}
|
}
|
||||||
@@ -51,10 +54,12 @@ pub(crate) struct Cli {
|
|||||||
pub(crate) enum Commands {
|
pub(crate) enum Commands {
|
||||||
/// Initialise a Nym client. Do this first!
|
/// Initialise a Nym client. Do this first!
|
||||||
Init(init::Init),
|
Init(init::Init),
|
||||||
|
|
||||||
/// Run the Nym client with provided configuration client optionally overriding set parameters
|
/// Run the Nym client with provided configuration client optionally overriding set parameters
|
||||||
Run(run::Run),
|
Run(run::Run),
|
||||||
/// Try to upgrade the client
|
|
||||||
Upgrade(upgrade::Upgrade),
|
/// Show build information of this binary
|
||||||
|
BuildInfo(build_info::BuildInfo),
|
||||||
|
|
||||||
/// Generate shell completions
|
/// Generate shell completions
|
||||||
Completions(ArgShell),
|
Completions(ArgShell),
|
||||||
@@ -75,13 +80,13 @@ pub(crate) struct OverrideConfig {
|
|||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let bin_name = "nym-native-client";
|
let bin_name = "nym-native-client";
|
||||||
|
|
||||||
match &args.command {
|
match args.command {
|
||||||
Commands::Init(m) => init::execute(m).await?,
|
Commands::Init(m) => init::execute(&m).await?,
|
||||||
Commands::Run(m) => run::execute(m).await?,
|
Commands::Run(m) => run::execute(&m).await?,
|
||||||
Commands::Upgrade(m) => upgrade::execute(m),
|
Commands::BuildInfo(m) => build_info::execute(m),
|
||||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::client::config::Config;
|
|
||||||
use crate::commands::try_load_current_config;
|
|
||||||
use clap::Args;
|
|
||||||
use nym_bin_common::version_checker::Version;
|
|
||||||
use std::process;
|
|
||||||
|
|
||||||
fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
|
|
||||||
eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Args, Clone)]
|
|
||||||
pub(crate) struct Upgrade {
|
|
||||||
/// Id of the nym-client we want to upgrade
|
|
||||||
#[clap(long)]
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_config_version(config: &Config) -> Version {
|
|
||||||
let version = Version::parse(&config.base.client.version).unwrap_or_else(|err| {
|
|
||||||
eprintln!("failed to parse client version! - {err}");
|
|
||||||
process::exit(1)
|
|
||||||
});
|
|
||||||
|
|
||||||
if version.is_prerelease() || !version.build.is_empty() {
|
|
||||||
eprintln!(
|
|
||||||
"Trying to upgrade from a non-released version {version}. This is not supported!"
|
|
||||||
);
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
version
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_package_version() -> Version {
|
|
||||||
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
|
||||||
|
|
||||||
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
|
|
||||||
// however, we are not using them ourselves at the moment and hence it should be fine.
|
|
||||||
// if we change our mind, we could easily tweak this code
|
|
||||||
if version.is_prerelease() || !version.build.is_empty() {
|
|
||||||
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
version
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
|
|
||||||
let config_version = parse_config_version(&config);
|
|
||||||
if &config_version == package_version {
|
|
||||||
println!("You're using the most recent version!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unimplemented_upgrade(package_version, &config_version)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn execute(args: &Upgrade) {
|
|
||||||
let package_version = parse_package_version();
|
|
||||||
|
|
||||||
let id = &args.id;
|
|
||||||
|
|
||||||
let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
|
|
||||||
eprintln!("failed to load existing config file! - {err}");
|
|
||||||
process::exit(1)
|
|
||||||
});
|
|
||||||
|
|
||||||
if existing_config.base.client.version.is_empty() {
|
|
||||||
eprintln!("the existing configuration file does not seem to contain version number.");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
do_upgrade(existing_config, args, &package_version)
|
|
||||||
}
|
|
||||||
@@ -14,10 +14,13 @@ pub mod websocket;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
setup_logging();
|
|
||||||
maybe_print_banner(crate_name!(), crate_version!());
|
|
||||||
|
|
||||||
let args = commands::Cli::parse();
|
let args = commands::Cli::parse();
|
||||||
setup_env(args.config_env_file.as_ref());
|
setup_env(args.config_env_file.as_ref());
|
||||||
commands::execute(&args).await
|
|
||||||
|
if !args.no_banner {
|
||||||
|
maybe_print_banner(crate_name!(), crate_version!());
|
||||||
|
}
|
||||||
|
setup_logging();
|
||||||
|
|
||||||
|
commands::execute(args).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,10 +117,11 @@ impl Handler {
|
|||||||
let Ok(base_length) = self
|
let Ok(base_length) = self
|
||||||
.lane_queue_lengths
|
.lane_queue_lengths
|
||||||
.lock()
|
.lock()
|
||||||
.map(|guard| guard.get(&conn_lane).unwrap_or_default()) else {
|
.map(|guard| guard.get(&conn_lane).unwrap_or_default())
|
||||||
|
else {
|
||||||
// I'd argue we should panic here as this error it not recoverable
|
// I'd argue we should panic here as this error it not recoverable
|
||||||
error!("The lane queue length lock is poisoned!!");
|
error!("The lane queue length lock is poisoned!!");
|
||||||
return None
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the number of pending replies waiting for reply surbs
|
// get the number of pending replies waiting for reply surbs
|
||||||
@@ -174,7 +175,7 @@ impl Handler {
|
|||||||
|
|
||||||
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
||||||
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
||||||
return None
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.get_lane_queue_length(connection_id).await
|
self.get_lane_queue_length(connection_id).await
|
||||||
@@ -206,7 +207,7 @@ impl Handler {
|
|||||||
|
|
||||||
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
||||||
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
||||||
return None
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.get_lane_queue_length(connection_id).await
|
self.get_lane_queue_length(connection_id).await
|
||||||
@@ -233,7 +234,7 @@ impl Handler {
|
|||||||
|
|
||||||
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
// Only reply back with a `LaneQueueLength` if the sender providided a connection id
|
||||||
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
let TransmissionLane::ConnectionId(connection_id) = lane else {
|
||||||
return None
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.get_lane_queue_length(connection_id).await
|
self.get_lane_queue_length(connection_id).await
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// all variable size data is always prefixed with u64 length
|
// all variable size data is always prefixed with u64 length
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// all variable size data is always prefixed with u64 length
|
// all variable size data is always prefixed with u64 length
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::error::ErrorKind;
|
use crate::error::ErrorKind;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.21"
|
version = "1.1.24"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
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"
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use clap::Args;
|
||||||
|
use nym_bin_common::bin_info_owned;
|
||||||
|
use nym_bin_common::output_format::OutputFormat;
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
pub(crate) struct BuildInfo {
|
||||||
|
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||||
|
output: OutputFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn execute(args: BuildInfo) {
|
||||||
|
println!("{}", args.output.format(&bin_info_owned!()))
|
||||||
|
}
|
||||||
@@ -94,6 +94,8 @@ impl From<Init> for OverrideConfig {
|
|||||||
use_anonymous_replies: init_config.use_reply_surbs,
|
use_anonymous_replies: init_config.use_reply_surbs,
|
||||||
fastmode: init_config.fastmode,
|
fastmode: init_config.fastmode,
|
||||||
no_cover: init_config.no_cover,
|
no_cover: init_config.no_cover,
|
||||||
|
geo_routing: None,
|
||||||
|
medium_toggle: false,
|
||||||
nyxd_urls: init_config.nyxd_urls,
|
nyxd_urls: init_config.nyxd_urls,
|
||||||
enabled_credentials_mode: init_config.enabled_credentials_mode,
|
enabled_credentials_mode: init_config.enabled_credentials_mode,
|
||||||
outfox: false,
|
outfox: false,
|
||||||
|
|||||||
@@ -10,25 +10,25 @@ use clap::CommandFactory;
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use nym_bin_common::build_information::BinaryBuildInformation;
|
use nym_bin_common::bin_info;
|
||||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||||
use nym_client_core::client::base_client::storage::gateway_details::{
|
use nym_client_core::client::base_client::storage::gateway_details::{
|
||||||
OnDiskGatewayDetails, PersistedGatewayDetails,
|
OnDiskGatewayDetails, PersistedGatewayDetails,
|
||||||
};
|
};
|
||||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||||
use nym_client_core::config::GatewayEndpointConfig;
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
|
use nym_client_core::config::{GatewayEndpointConfig, TopologyStructure};
|
||||||
use nym_client_core::error::ClientCoreError;
|
use nym_client_core::error::ClientCoreError;
|
||||||
use nym_config::OptionalSet;
|
use nym_config::OptionalSet;
|
||||||
use nym_sphinx::params::PacketType;
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
pub(crate) mod build_info;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub(crate) mod run;
|
pub(crate) mod run;
|
||||||
pub(crate) mod upgrade;
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref PRETTY_BUILD_INFORMATION: String =
|
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
|
||||||
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for passing LONG_VERSION to clap
|
// Helper for passing LONG_VERSION to clap
|
||||||
@@ -43,6 +43,10 @@ pub(crate) struct Cli {
|
|||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||||
|
|
||||||
|
/// Flag used for disabling the printed banner in tty.
|
||||||
|
#[clap(long)]
|
||||||
|
pub(crate) no_banner: bool,
|
||||||
|
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Commands,
|
command: Commands,
|
||||||
}
|
}
|
||||||
@@ -55,8 +59,8 @@ pub(crate) enum Commands {
|
|||||||
/// Run the Nym client with provided configuration client optionally overriding set parameters
|
/// Run the Nym client with provided configuration client optionally overriding set parameters
|
||||||
Run(run::Run),
|
Run(run::Run),
|
||||||
|
|
||||||
/// Try to upgrade the client
|
/// Show build information of this binary
|
||||||
Upgrade(upgrade::Upgrade),
|
BuildInfo(build_info::BuildInfo),
|
||||||
|
|
||||||
/// Generate shell completions
|
/// Generate shell completions
|
||||||
Completions(ArgShell),
|
Completions(ArgShell),
|
||||||
@@ -72,18 +76,20 @@ pub(crate) struct OverrideConfig {
|
|||||||
use_anonymous_replies: Option<bool>,
|
use_anonymous_replies: Option<bool>,
|
||||||
fastmode: bool,
|
fastmode: bool,
|
||||||
no_cover: bool,
|
no_cover: bool,
|
||||||
|
geo_routing: Option<CountryGroup>,
|
||||||
|
medium_toggle: bool,
|
||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
enabled_credentials_mode: Option<bool>,
|
enabled_credentials_mode: Option<bool>,
|
||||||
outfox: bool,
|
outfox: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let bin_name = "nym-socks5-client";
|
let bin_name = "nym-socks5-client";
|
||||||
|
|
||||||
match &args.command {
|
match args.command {
|
||||||
Commands::Init(m) => init::execute(m).await?,
|
Commands::Init(m) => init::execute(&m).await?,
|
||||||
Commands::Run(m) => run::execute(m).await?,
|
Commands::Run(m) => run::execute(&m).await?,
|
||||||
Commands::Upgrade(m) => upgrade::execute(m),
|
Commands::BuildInfo(m) => build_info::execute(m),
|
||||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||||
}
|
}
|
||||||
@@ -91,6 +97,17 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||||
|
let disable_cover_traffic_with_keepalive = args.medium_toggle;
|
||||||
|
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
|
||||||
|
let no_per_hop_delays = args.medium_toggle;
|
||||||
|
|
||||||
|
let topology_structure = if args.medium_toggle || args.geo_routing.is_some() {
|
||||||
|
// TODO: rethink the default group. I just picked one for now.
|
||||||
|
TopologyStructure::GeoAware(args.geo_routing.unwrap_or(CountryGroup::Europe))
|
||||||
|
} else {
|
||||||
|
TopologyStructure::default()
|
||||||
|
};
|
||||||
|
|
||||||
let packet_type = if args.outfox {
|
let packet_type = if args.outfox {
|
||||||
PacketType::Outfox
|
PacketType::Outfox
|
||||||
} else {
|
} else {
|
||||||
@@ -101,8 +118,23 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
BaseClientConfig::with_high_default_traffic_volume,
|
BaseClientConfig::with_high_default_traffic_volume,
|
||||||
args.fastmode,
|
args.fastmode,
|
||||||
)
|
)
|
||||||
|
.with_base(
|
||||||
|
// NOTE: This interacts with disabling cover traffic fully, so we want to this to be set before
|
||||||
|
BaseClientConfig::with_disabled_cover_traffic_with_keepalive,
|
||||||
|
disable_cover_traffic_with_keepalive,
|
||||||
|
)
|
||||||
|
.with_base(
|
||||||
|
BaseClientConfig::with_secondary_packet_size,
|
||||||
|
secondary_packet_size,
|
||||||
|
)
|
||||||
|
.with_base(BaseClientConfig::with_no_per_hop_delays, no_per_hop_delays)
|
||||||
|
// NOTE: see comment above about the order of the other disble cover traffic config
|
||||||
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
|
||||||
.with_base(BaseClientConfig::with_packet_type, packet_type)
|
.with_base(BaseClientConfig::with_packet_type, packet_type)
|
||||||
|
.with_base(
|
||||||
|
BaseClientConfig::with_topology_structure,
|
||||||
|
topology_structure,
|
||||||
|
)
|
||||||
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
|
||||||
.with_optional(Config::with_port, args.port)
|
.with_optional(Config::with_port, args.port)
|
||||||
.with_optional_base_custom_env(
|
.with_optional_base_custom_env(
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use clap::Args;
|
|||||||
use log::*;
|
use log::*;
|
||||||
use nym_bin_common::version_checker::is_minor_version_compatible;
|
use nym_bin_common::version_checker::is_minor_version_compatible;
|
||||||
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
use nym_client_core::client::base_client::storage::OnDiskPersistent;
|
||||||
|
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||||
use nym_crypto::asymmetric::identity;
|
use nym_crypto::asymmetric::identity;
|
||||||
use nym_socks5_client_core::NymClient;
|
use nym_socks5_client_core::NymClient;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
@@ -60,6 +61,15 @@ pub(crate) struct Run {
|
|||||||
#[clap(long, hide = true)]
|
#[clap(long, hide = true)]
|
||||||
no_cover: bool,
|
no_cover: bool,
|
||||||
|
|
||||||
|
/// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only.
|
||||||
|
#[clap(long, hide = true, value_parser = validate_country_group)]
|
||||||
|
geo_routing: Option<CountryGroup>,
|
||||||
|
|
||||||
|
/// Enable medium mixnet traffic, for experiments only.
|
||||||
|
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||||
|
#[clap(long, hide = true)]
|
||||||
|
medium_toggle: bool,
|
||||||
|
|
||||||
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
|
||||||
/// with bandwidth credential requirement.
|
/// with bandwidth credential requirement.
|
||||||
#[clap(long, hide = true)]
|
#[clap(long, hide = true)]
|
||||||
@@ -77,6 +87,8 @@ impl From<Run> for OverrideConfig {
|
|||||||
use_anonymous_replies: run_config.use_anonymous_replies,
|
use_anonymous_replies: run_config.use_anonymous_replies,
|
||||||
fastmode: run_config.fastmode,
|
fastmode: run_config.fastmode,
|
||||||
no_cover: run_config.no_cover,
|
no_cover: run_config.no_cover,
|
||||||
|
geo_routing: run_config.geo_routing,
|
||||||
|
medium_toggle: run_config.medium_toggle,
|
||||||
nyxd_urls: run_config.nyxd_urls,
|
nyxd_urls: run_config.nyxd_urls,
|
||||||
enabled_credentials_mode: run_config.enabled_credentials_mode,
|
enabled_credentials_mode: run_config.enabled_credentials_mode,
|
||||||
outfox: run_config.outfox,
|
outfox: run_config.outfox,
|
||||||
@@ -84,6 +96,13 @@ impl From<Run> for OverrideConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
|
||||||
|
match s.parse() {
|
||||||
|
Ok(cg) => Ok(cg),
|
||||||
|
Err(_) => Err(format!("failed to parse country group: {}", s)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this only checks compatibility between config the binary. It does not take into consideration
|
// this only checks compatibility between config the binary. It does not take into consideration
|
||||||
// network version. It might do so in the future.
|
// network version. It might do so in the future.
|
||||||
fn version_check(cfg: &Config) -> bool {
|
fn version_check(cfg: &Config) -> bool {
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::commands::try_load_current_config;
|
|
||||||
use crate::config::Config;
|
|
||||||
use clap::Args;
|
|
||||||
use nym_bin_common::version_checker::Version;
|
|
||||||
use std::process;
|
|
||||||
|
|
||||||
fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
|
|
||||||
eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Args, Clone)]
|
|
||||||
pub(crate) struct Upgrade {
|
|
||||||
/// Id of the nym-client we want to upgrade
|
|
||||||
#[clap(long)]
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_config_version(config: &Config) -> Version {
|
|
||||||
let version = Version::parse(&config.core.base.client.version).unwrap_or_else(|err| {
|
|
||||||
eprintln!("failed to parse client version! - {err}");
|
|
||||||
process::exit(1)
|
|
||||||
});
|
|
||||||
|
|
||||||
if version.is_prerelease() || !version.build.is_empty() {
|
|
||||||
eprintln!(
|
|
||||||
"Trying to upgrade from a non-released version {version}. This is not supported!"
|
|
||||||
);
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
version
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_package_version() -> Version {
|
|
||||||
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
|
||||||
|
|
||||||
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
|
|
||||||
// however, we are not using them ourselves at the moment and hence it should be fine.
|
|
||||||
// if we change our mind, we could easily tweak this code
|
|
||||||
if version.is_prerelease() || !version.build.is_empty() {
|
|
||||||
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
version
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
|
|
||||||
let config_version = parse_config_version(&config);
|
|
||||||
if &config_version == package_version {
|
|
||||||
println!("You're using the most recent version!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unimplemented_upgrade(package_version, &config_version)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn execute(args: &Upgrade) {
|
|
||||||
let package_version = parse_package_version();
|
|
||||||
|
|
||||||
let id = &args.id;
|
|
||||||
|
|
||||||
let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
|
|
||||||
eprintln!("failed to load existing config file! - {err}");
|
|
||||||
process::exit(1)
|
|
||||||
});
|
|
||||||
|
|
||||||
if existing_config.core.base.client.version.is_empty() {
|
|
||||||
eprintln!("the existing configuration file does not seem to contain version number.");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
do_upgrade(existing_config, args, &package_version)
|
|
||||||
}
|
|
||||||
@@ -13,10 +13,13 @@ pub mod error;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
setup_logging();
|
|
||||||
maybe_print_banner(crate_name!(), crate_version!());
|
|
||||||
|
|
||||||
let args = commands::Cli::parse();
|
let args = commands::Cli::parse();
|
||||||
setup_env(args.config_env_file.as_ref());
|
setup_env(args.config_env_file.as_ref());
|
||||||
commands::execute(&args).await
|
|
||||||
|
if !args.no_banner {
|
||||||
|
maybe_print_banner(crate_name!(), crate_version!());
|
||||||
|
}
|
||||||
|
setup_logging();
|
||||||
|
|
||||||
|
commands::execute(args).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
16
|
18
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
"version": "0.19.0",
|
"version": "0.19.0",
|
||||||
"description": "A TypeScript client for interacting with smart contracts in Nym validators",
|
"description": "A TypeScript client for interacting with smart contracts in Nym validators",
|
||||||
"repository": "https://github.com/nymtech/nym",
|
"repository": "https://github.com/nymtech/nym",
|
||||||
"main": "./dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c ./rollup.config.mjs",
|
"build": "rollup -c ./rollup.config.mjs",
|
||||||
"build:types": "rollup-type-bundler --dist ./dist/nym-validator-client",
|
"build:types": "rollup-type-bundler --dist ./dist",
|
||||||
"build:prod": "sh ./scripts/build-prod.sh",
|
"build:prod": "sh ./scripts/build-prod.sh",
|
||||||
"test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts",
|
"test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts",
|
||||||
"testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts",
|
"testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts",
|
||||||
@@ -29,16 +29,23 @@
|
|||||||
],
|
],
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@cosmjs/cosmwasm-stargate": "^0.29.5",
|
||||||
|
"@cosmjs/crypto": "^0.29.5",
|
||||||
|
"@cosmjs/math": "^0.29.5",
|
||||||
|
"@cosmjs/proto-signing": "^0.29.5",
|
||||||
|
"@cosmjs/stargate": "^0.29.5",
|
||||||
|
"@cosmjs/tendermint-rpc": "^0.29.5",
|
||||||
"@favware/rollup-type-bundler": "^2.0.0",
|
"@favware/rollup-type-bundler": "^2.0.0",
|
||||||
"@nymproject/types": "^1.0.0",
|
"@nymproject/types": "^1.0.0",
|
||||||
"@rollup/plugin-commonjs": "^24.0.1",
|
"@rollup/plugin-commonjs": "^24.0.1",
|
||||||
"@rollup/plugin-json": "^6.0.0",
|
"@rollup/plugin-json": "^6.0.0",
|
||||||
"@rollup/plugin-typescript": "^11.0.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
"rollup": "^3.17.2",
|
"@rollup/plugin-typescript": "^11.0.0",
|
||||||
"rollup-plugin-dts": "^5.2.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
||||||
"@typescript-eslint/parser": "^5.7.0",
|
"@typescript-eslint/parser": "^5.7.0",
|
||||||
|
"axios": "^1.3.3",
|
||||||
|
"cosmjs-types": "^0.4.1",
|
||||||
|
"dotenv": "^16.0.3",
|
||||||
"eslint": "^7.18.0",
|
"eslint": "^7.18.0",
|
||||||
"eslint-config-airbnb": "^19.0.2",
|
"eslint-config-airbnb": "^19.0.2",
|
||||||
"eslint-config-airbnb-typescript": "^16.1.0",
|
"eslint-config-airbnb-typescript": "^16.1.0",
|
||||||
@@ -47,21 +54,15 @@
|
|||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-mocha": "^10.0.3",
|
"eslint-plugin-mocha": "^10.0.3",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"expect": "^28.1.3",
|
||||||
"mocha": "^10.0.0",
|
"mocha": "^10.0.0",
|
||||||
|
"moq.ts": "^7.3.4",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
|
"rollup": "^3.17.2",
|
||||||
|
"rollup-plugin-dts": "^5.2.0",
|
||||||
|
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||||
"ts-mocha": "^10.0.0",
|
"ts-mocha": "^10.0.0",
|
||||||
"typedoc": "^0.22.13",
|
"typedoc": "^0.22.13",
|
||||||
"typescript": "^4.6.2",
|
"typescript": "^4.6.2"
|
||||||
"cosmjs-types": "^0.4.1",
|
|
||||||
"dotenv": "^16.0.3",
|
|
||||||
"expect": "^28.1.3",
|
|
||||||
"moq.ts": "^7.3.4",
|
|
||||||
"@cosmjs/cosmwasm-stargate": "^0.29.5",
|
|
||||||
"@cosmjs/crypto": "^0.29.5",
|
|
||||||
"@cosmjs/math": "^0.29.5",
|
|
||||||
"@cosmjs/proto-signing": "^0.29.5",
|
|
||||||
"@cosmjs/stargate": "^0.29.5",
|
|
||||||
"@cosmjs/tendermint-rpc": "^0.29.5",
|
|
||||||
"axios": "^1.3.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import typescript from '@rollup/plugin-typescript';
|
import typescript from '@rollup/plugin-typescript';
|
||||||
import resolve from '@rollup/plugin-node-resolve';
|
import nodePolyfills from 'rollup-plugin-node-polyfills';
|
||||||
import json from '@rollup/plugin-json';
|
import json from '@rollup/plugin-json';
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
input: './src/index.ts',
|
input: 'src/index.ts',
|
||||||
output: {
|
output: {
|
||||||
dir: 'dist/nym-validator-client',
|
dir: 'dist',
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
},
|
},
|
||||||
plugins: [resolve(), typescript(), commonjs(), json()],
|
plugins: [nodePolyfills(), typescript(), commonjs(), json()],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ node ./scripts/buildPackageJson.mjs
|
|||||||
|
|
||||||
# Copy README
|
# Copy README
|
||||||
|
|
||||||
cp README.md dist/nym-validator-client
|
cp README.md dist/
|
||||||
|
|
||||||
# move the output outside of the yarn/npm workspaces
|
# move the output outside of the yarn/npm workspaces
|
||||||
|
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ const packageJson = {
|
|||||||
types,
|
types,
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync('./dist/nym-validator-client/package.json', JSON.stringify(packageJson, null, 2));
|
fs.writeFileSync('./dist/package.json', JSON.stringify(packageJson, null, 2));
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import {
|
|||||||
} from '@nymproject/types';
|
} from '@nymproject/types';
|
||||||
import QueryClient from './query-client';
|
import QueryClient from './query-client';
|
||||||
import SigningClient, { ISigningClient } from './signing-client';
|
import SigningClient, { ISigningClient } from './signing-client';
|
||||||
// import { DelegationBlock } from './types/shared';
|
|
||||||
|
|
||||||
export interface INymClient {
|
export interface INymClient {
|
||||||
readonly mixnetContract: string;
|
readonly mixnetContract: string;
|
||||||
@@ -626,7 +625,17 @@ export default class ValidatorClient implements INymClient {
|
|||||||
|
|
||||||
// SIMULATE
|
// SIMULATE
|
||||||
|
|
||||||
public async simulateSend(signingAddress: string, from: string, to: string, amount: Coin[]) {
|
public async simulateSend({
|
||||||
return (this.client as SigningClient).simulateSend(signingAddress, from, to, amount);
|
signingAddress,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
amount,
|
||||||
|
}: {
|
||||||
|
signingAddress: string;
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
amount: Coin[];
|
||||||
|
}) {
|
||||||
|
return (this.client as ISigningClient).simulateSend(signingAddress, from, to, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,12 @@ describe('Simualtions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can simulate sending tokens', async () => {
|
it('can simulate sending tokens', async () => {
|
||||||
const res = await client.simulateSend(client.address, client.address, client.address, [
|
const res = await client.simulateSend({
|
||||||
{ amount: '400000', denom: 'unym' },
|
signingAddress: client.address,
|
||||||
]);
|
from: client.address,
|
||||||
|
to: client.address,
|
||||||
|
amount: [{ amount: '400000', denom: 'unym' }],
|
||||||
|
});
|
||||||
|
|
||||||
expect(typeof res).toBe('number');
|
expect(typeof res).toBe('number');
|
||||||
}).timeout(10000);
|
}).timeout(10000);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./dist/nym-validator-client",
|
"outDir": "dist",
|
||||||
"module": "ES2020",
|
"module": "ES2020",
|
||||||
"target": "es2021",
|
"target": "es2021",
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
|
|||||||
Generated
+501
-240
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-wasm"
|
name = "nym-client-wasm"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||||
version = "1.1.0"
|
version = "1.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"]
|
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
@@ -33,7 +33,7 @@ wasm-bindgen-futures = "0.4"
|
|||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
zeroize = "1.6.0"
|
zeroize = "1.6.0"
|
||||||
|
|
||||||
wasm-timer = { git = "https://github.com/mmsinclair/wasm-timer", rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"}
|
wasmtimer = { version = "0.2.0", features = ["tokio"] }
|
||||||
|
|
||||||
# internal
|
# internal
|
||||||
nym-node-tester-utils = { path = "../../common/node-tester-utils" }
|
nym-node-tester-utils = { path = "../../common/node-tester-utils" }
|
||||||
|
|||||||
@@ -3,3 +3,6 @@ clippy:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
wasm-pack test --node
|
wasm-pack test --node
|
||||||
|
|
||||||
|
wasm-build:
|
||||||
|
wasm-pack build
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --config webpack.config.js",
|
"build": "webpack --config webpack.config.js",
|
||||||
|
"build:wasm": "cd ../ && make wasm-build",
|
||||||
"start": "webpack-dev-server --port 8001"
|
"start": "webpack-dev-server --port 8001"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -36,4 +37,4 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nymproject/nym-client-wasm": "file:../pkg"
|
"@nymproject/nym-client-wasm": "file:../pkg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,333 +12,371 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
importScripts('nym_client_wasm.js');
|
importScripts("nym_client_wasm.js");
|
||||||
|
|
||||||
console.log('Initializing worker');
|
console.log("Initializing worker");
|
||||||
|
|
||||||
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
|
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
|
||||||
const {
|
const {
|
||||||
NymNodeTester,
|
NymNodeTester,
|
||||||
WasmGateway,
|
WasmGateway,
|
||||||
WasmMixNode,
|
WasmMixNode,
|
||||||
WasmNymTopology,
|
WasmNymTopology,
|
||||||
default_debug,
|
default_debug,
|
||||||
NymClientBuilder,
|
NymClientBuilder,
|
||||||
NymClient,
|
NymClient,
|
||||||
set_panic_hook,
|
set_panic_hook,
|
||||||
Config,
|
Config,
|
||||||
GatewayEndpointConfig,
|
GatewayEndpointConfig,
|
||||||
ClientStorage,
|
ClientStorage,
|
||||||
current_network_topology,
|
current_network_topology,
|
||||||
make_key,
|
make_key,
|
||||||
make_key2
|
make_key2,
|
||||||
} = wasm_bindgen;
|
} = wasm_bindgen;
|
||||||
|
|
||||||
let client = null;
|
let client = null;
|
||||||
let tester = null;
|
let tester = null;
|
||||||
|
|
||||||
|
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
||||||
|
|
||||||
function dummyTopology() {
|
function dummyTopology() {
|
||||||
const l1Mixnode = new WasmMixNode(
|
const l1Mixnode = new WasmMixNode(
|
||||||
1,
|
1,
|
||||||
'n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47',
|
"n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47",
|
||||||
'178.79.143.65',
|
"178.79.143.65",
|
||||||
1789,
|
1789,
|
||||||
'4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz',
|
"4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz",
|
||||||
'8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG',
|
"8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG",
|
||||||
1,
|
1,
|
||||||
'1.10.0',
|
"1.10.0"
|
||||||
);
|
);
|
||||||
const l2Mixnode = new WasmMixNode(
|
const l2Mixnode = new WasmMixNode(
|
||||||
2,
|
2,
|
||||||
'n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70',
|
"n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70",
|
||||||
'109.74.197.180',
|
"109.74.197.180",
|
||||||
1789,
|
1789,
|
||||||
'7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK',
|
"7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK",
|
||||||
'GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN',
|
"GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN",
|
||||||
2,
|
2,
|
||||||
'1.10.0',
|
"1.10.0"
|
||||||
);
|
);
|
||||||
const l3Mixnode = new WasmMixNode(
|
const l3Mixnode = new WasmMixNode(
|
||||||
3,
|
3,
|
||||||
'n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77',
|
"n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77",
|
||||||
'176.58.101.80',
|
"176.58.101.80",
|
||||||
1789,
|
1789,
|
||||||
'FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R',
|
"FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R",
|
||||||
'DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD',
|
"DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD",
|
||||||
3,
|
3,
|
||||||
'1.10.0',
|
"1.10.0"
|
||||||
);
|
);
|
||||||
|
|
||||||
const gateway = new WasmGateway(
|
const gateway = new WasmGateway(
|
||||||
'n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts',
|
"n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts",
|
||||||
'85.159.212.96',
|
"85.159.212.96",
|
||||||
1789,
|
1789,
|
||||||
9000,
|
9000,
|
||||||
'336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9',
|
"336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9",
|
||||||
'BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL',
|
"BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL",
|
||||||
'1.10.1',
|
"1.10.1"
|
||||||
);
|
);
|
||||||
|
|
||||||
const mixnodes = new Map();
|
const mixnodes = new Map();
|
||||||
mixnodes.set(1, [l1Mixnode]);
|
mixnodes.set(1, [l1Mixnode]);
|
||||||
mixnodes.set(2, [l2Mixnode]);
|
mixnodes.set(2, [l2Mixnode]);
|
||||||
mixnodes.set(3, [l3Mixnode]);
|
mixnodes.set(3, [l3Mixnode]);
|
||||||
|
|
||||||
|
const gateways = [gateway];
|
||||||
|
|
||||||
const gateways = [gateway];
|
return new WasmNymTopology(mixnodes, gateways);
|
||||||
|
|
||||||
return new WasmNymTopology(mixnodes, gateways)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printAndDisplayTestResult(result) {
|
function printAndDisplayTestResult(result) {
|
||||||
result.log_details();
|
result.log_details();
|
||||||
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
kind: 'DisplayTesterResults',
|
kind: "DisplayTesterResults",
|
||||||
args: {
|
args: {
|
||||||
score: result.score(),
|
score: result.score(),
|
||||||
sentPackets: result.sent_packets,
|
sentPackets: result.sent_packets,
|
||||||
receivedPackets: result.received_packets,
|
receivedPackets: result.received_packets,
|
||||||
receivedAcks: result.received_acks,
|
receivedAcks: result.received_acks,
|
||||||
duplicatePackets: result.duplicate_packets,
|
duplicatePackets: result.duplicate_packets,
|
||||||
duplicateAcks: result.duplicate_acks,
|
duplicateAcks: result.duplicate_acks,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function testWithTester() {
|
async function testWithTester() {
|
||||||
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
// A) construct with hardcoded topology
|
||||||
|
const topology = dummyTopology();
|
||||||
|
const nodeTester = await new NymNodeTester(topology, preferredGateway);
|
||||||
|
|
||||||
// A) construct with hardcoded topology
|
// B) first get topology directly from nym-api
|
||||||
const topology = dummyTopology()
|
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||||
const nodeTester = await new NymNodeTester(topology, preferredGateway);
|
// const topology = await current_network_topology(validator)
|
||||||
|
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
|
||||||
|
//
|
||||||
|
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
|
||||||
|
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||||
|
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
|
||||||
|
|
||||||
// B) first get topology directly from nym-api
|
// B) first get topology directly from nym-api
|
||||||
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||||
// const topology = await current_network_topology(validator)
|
// const topology = await current_network_topology(validator)
|
||||||
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
|
// const nodeTester = await new NymNodeTester(topology, undefined, preferredGateway);
|
||||||
//
|
//
|
||||||
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
|
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
|
||||||
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||||
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
|
// const nodeTester = await NymNodeTester.new_with_api(validator, undefined, preferredGateway)
|
||||||
|
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
|
||||||
|
// const topology = dummyTopology()
|
||||||
|
// const nodeTester = await new NymNodeTester(topology);
|
||||||
|
|
||||||
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
|
self.onmessage = async (event) => {
|
||||||
// const topology = dummyTopology()
|
if (event.data && event.data.kind) {
|
||||||
// const nodeTester = await new NymNodeTester(topology);
|
switch (event.data.kind) {
|
||||||
|
case "TestPacket": {
|
||||||
|
const { mixnodeIdentity } = event.data.args;
|
||||||
|
console.log("starting node test...");
|
||||||
|
|
||||||
self.onmessage = async event => {
|
let result = await nodeTester.test_node(mixnodeIdentity);
|
||||||
if (event.data && event.data.kind) {
|
printAndDisplayTestResult(result);
|
||||||
switch (event.data.kind) {
|
|
||||||
case 'TestPacket': {
|
|
||||||
const {mixnodeIdentity} = event.data.args;
|
|
||||||
console.log("starting node test...");
|
|
||||||
|
|
||||||
let result = await nodeTester.test_node(mixnodeIdentity);
|
|
||||||
printAndDisplayTestResult(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testerReconnection() {
|
||||||
|
const validator = "https://qwerty-validator-api.qa.nymte.ch/api";
|
||||||
|
const nodeTester = await NymNodeTester.new_with_api(validator);
|
||||||
|
|
||||||
|
self.onmessage = async (event) => {
|
||||||
|
if (event.data && event.data.kind) {
|
||||||
|
switch (event.data.kind) {
|
||||||
|
case "TestPacket": {
|
||||||
|
const { mixnodeIdentity } = event.data.args;
|
||||||
|
console.log("starting node test...");
|
||||||
|
|
||||||
|
let result1 = await nodeTester.test_node(mixnodeIdentity);
|
||||||
|
console.log("sleeping for 5s");
|
||||||
|
await new Promise((r) => setTimeout(r, 5000));
|
||||||
|
await nodeTester.disconnect_from_gateway();
|
||||||
|
|
||||||
|
console.log("sleeping for 5s");
|
||||||
|
await new Promise((r) => setTimeout(r, 5000));
|
||||||
|
|
||||||
|
await nodeTester.reconnect_to_gateway();
|
||||||
|
let result2 = await nodeTester.test_node(mixnodeIdentity);
|
||||||
|
|
||||||
|
printAndDisplayTestResult(result1);
|
||||||
|
printAndDisplayTestResult(result2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function testWithNymClient() {
|
async function testWithNymClient() {
|
||||||
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
const topology = dummyTopology();
|
||||||
const topology = dummyTopology()
|
|
||||||
|
|
||||||
let received = 0
|
let received = 0;
|
||||||
|
|
||||||
const onMessageHandler = (message) => {
|
const onMessageHandler = (message) => {
|
||||||
received += 1;
|
received += 1;
|
||||||
self.postMessage({
|
|
||||||
kind: 'ReceiveMessage',
|
|
||||||
args: {
|
|
||||||
message,
|
|
||||||
senderTag: undefined,
|
|
||||||
isTestPacket: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// it's really up to the user to create proper callback here...
|
|
||||||
console.log(`received ${received} packets so far`)
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Instantiating WASM client...');
|
|
||||||
|
|
||||||
let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, preferredGateway)
|
|
||||||
console.log('Web worker creating WASM client...');
|
|
||||||
let local_client = await clientBuilder.start_client();
|
|
||||||
console.log('WASM client running!');
|
|
||||||
|
|
||||||
const selfAddress = local_client.self_address();
|
|
||||||
|
|
||||||
// set the global (I guess we don't have to anymore?)
|
|
||||||
client = local_client;
|
|
||||||
|
|
||||||
console.log(`Client address is ${selfAddress}`);
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
kind: 'Ready',
|
kind: "ReceiveMessage",
|
||||||
args: {
|
args: {
|
||||||
selfAddress,
|
message,
|
||||||
},
|
senderTag: undefined,
|
||||||
|
isTestPacket: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set callback to handle messages passed to the worker.
|
// it's really up to the user to create proper callback here...
|
||||||
self.onmessage = async event => {
|
console.log(`received ${received} packets so far`);
|
||||||
console.log(event)
|
};
|
||||||
if (event.data && event.data.kind) {
|
|
||||||
switch (event.data.kind) {
|
console.log("Instantiating WASM client...");
|
||||||
case 'SendMessage': {
|
|
||||||
const {message, recipient} = event.data.args;
|
let clientBuilder = NymClientBuilder.new_tester(
|
||||||
let uint8Array = new TextEncoder().encode(message);
|
topology,
|
||||||
await client.send_regular_message(uint8Array, recipient);
|
onMessageHandler,
|
||||||
break;
|
preferredGateway
|
||||||
}
|
);
|
||||||
case 'TestPacket': {
|
|
||||||
const {mixnodeIdentity} = event.data.args;
|
console.log("Web worker creating WASM client...");
|
||||||
const req = await client.try_construct_test_packet_request(mixnodeIdentity);
|
let local_client = await clientBuilder.start_client();
|
||||||
await client.change_hardcoded_topology(req.injectable_topology());
|
console.log("WASM client running!");
|
||||||
await client.try_send_test_packets(req);
|
|
||||||
break;
|
const selfAddress = local_client.self_address();
|
||||||
}
|
|
||||||
}
|
// set the global (I guess we don't have to anymore?)
|
||||||
|
client = local_client;
|
||||||
|
|
||||||
|
console.log(`Client address is ${selfAddress}`);
|
||||||
|
self.postMessage({
|
||||||
|
kind: "Ready",
|
||||||
|
args: {
|
||||||
|
selfAddress,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set callback to handle messages passed to the worker.
|
||||||
|
self.onmessage = async (event) => {
|
||||||
|
console.log(event);
|
||||||
|
if (event.data && event.data.kind) {
|
||||||
|
switch (event.data.kind) {
|
||||||
|
case "SendMessage": {
|
||||||
|
const { message, recipient } = event.data.args;
|
||||||
|
let uint8Array = new TextEncoder().encode(message);
|
||||||
|
await client.send_regular_message(uint8Array, recipient);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
case "TestPacket": {
|
||||||
|
const { mixnodeIdentity } = event.data.args;
|
||||||
|
const req = await client.try_construct_test_packet_request(
|
||||||
|
mixnodeIdentity
|
||||||
|
);
|
||||||
|
await client.change_hardcoded_topology(req.injectable_topology());
|
||||||
|
await client.try_send_test_packets(req);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function normalNymClientUsage() {
|
async function normalNymClientUsage() {
|
||||||
self.postMessage({kind: 'DisableMagicTestButton'});
|
self.postMessage({ kind: "DisableMagicTestButton" });
|
||||||
|
|
||||||
// only really useful if you want to adjust some settings like traffic rate
|
// only really useful if you want to adjust some settings like traffic rate
|
||||||
// (if not needed you can just pass a null)
|
// (if not needed you can just pass a null)
|
||||||
const debug = default_debug();
|
const debug = default_debug();
|
||||||
|
|
||||||
debug.disable_main_poisson_packet_distribution = true;
|
debug.disable_main_poisson_packet_distribution = true;
|
||||||
debug.disable_loop_cover_traffic_stream = true;
|
debug.disable_loop_cover_traffic_stream = true;
|
||||||
debug.use_extended_packet_size = false;
|
debug.use_extended_packet_size = false;
|
||||||
// debug.average_packet_delay_ms = BigInt(10);
|
// debug.average_packet_delay_ms = BigInt(10);
|
||||||
// debug.average_ack_delay_ms = BigInt(10);
|
// debug.average_ack_delay_ms = BigInt(10);
|
||||||
// debug.ack_wait_addition_ms = BigInt(3000);
|
// debug.ack_wait_addition_ms = BigInt(3000);
|
||||||
// debug.ack_wait_multiplier = 10;
|
// debug.ack_wait_multiplier = 10;
|
||||||
|
|
||||||
debug.topology_refresh_rate_ms = BigInt(60000)
|
debug.topology_refresh_rate_ms = BigInt(60000);
|
||||||
|
|
||||||
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
||||||
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
const validator = "https://qwerty-validator-api.qa.nymte.ch/api";
|
||||||
|
|
||||||
const config = new Config('my-awesome-wasm-client', validator, debug);
|
const config = new Config("my-awesome-wasm-client", validator, debug);
|
||||||
|
|
||||||
const onMessageHandler = (message) => {
|
const onMessageHandler = (message) => {
|
||||||
console.log(message);
|
console.log(message);
|
||||||
self.postMessage({
|
|
||||||
kind: 'ReceiveMessage',
|
|
||||||
args: {
|
|
||||||
message,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Instantiating WASM client...');
|
|
||||||
|
|
||||||
let localClient = await new NymClient(config, onMessageHandler)
|
|
||||||
console.log('WASM client running!');
|
|
||||||
|
|
||||||
const selfAddress = localClient.self_address();
|
|
||||||
|
|
||||||
// set the global (I guess we don't have to anymore?)
|
|
||||||
client = localClient;
|
|
||||||
|
|
||||||
console.log(`Client address is ${selfAddress}`);
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
kind: 'Ready',
|
kind: "ReceiveMessage",
|
||||||
args: {
|
args: {
|
||||||
selfAddress,
|
message,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Set callback to handle messages passed to the worker.
|
console.log("Instantiating WASM client...");
|
||||||
self.onmessage = async event => {
|
|
||||||
console.log(event)
|
let localClient = await new NymClient(config, onMessageHandler);
|
||||||
if (event.data && event.data.kind) {
|
console.log("WASM client running!");
|
||||||
switch (event.data.kind) {
|
|
||||||
case 'SendMessage': {
|
const selfAddress = localClient.self_address();
|
||||||
const {message, recipient} = event.data.args;
|
|
||||||
let uint8Array = new TextEncoder().encode(message);
|
// set the global (I guess we don't have to anymore?)
|
||||||
await client.send_regular_message(uint8Array, recipient);
|
client = localClient;
|
||||||
break;
|
|
||||||
}
|
console.log(`Client address is ${selfAddress}`);
|
||||||
}
|
self.postMessage({
|
||||||
|
kind: "Ready",
|
||||||
|
args: {
|
||||||
|
selfAddress,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set callback to handle messages passed to the worker.
|
||||||
|
self.onmessage = async (event) => {
|
||||||
|
console.log(event);
|
||||||
|
if (event.data && event.data.kind) {
|
||||||
|
switch (event.data.kind) {
|
||||||
|
case "SendMessage": {
|
||||||
|
const { message, recipient } = event.data.args;
|
||||||
|
let uint8Array = new TextEncoder().encode(message);
|
||||||
|
await client.send_regular_message(uint8Array, recipient);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function messWithStorage() {
|
async function messWithStorage() {
|
||||||
self.onmessage = async event => {
|
self.onmessage = async (event) => {
|
||||||
if (event.data && event.data.kind) {
|
if (event.data && event.data.kind) {
|
||||||
switch (event.data.kind) {
|
switch (event.data.kind) {
|
||||||
case 'TestPacket': {
|
case "TestPacket": {
|
||||||
const { mixnodeIdentity } = event.data.args;
|
const { mixnodeIdentity } = event.data.args;
|
||||||
console.log("button clicked...", mixnodeIdentity);
|
console.log("button clicked...", mixnodeIdentity);
|
||||||
|
|
||||||
let id1 = "one";
|
let id1 = "one";
|
||||||
let id2 = "two";
|
let id2 = "two";
|
||||||
|
|
||||||
console.log("making store1 NO-ENC");
|
console.log("making store1 NO-ENC");
|
||||||
let _storage1 = await ClientStorage.new_unencrypted(id1);
|
let _storage1 = await ClientStorage.new_unencrypted(id1);
|
||||||
|
|
||||||
console.log("making store2 ENC")
|
console.log("making store2 ENC");
|
||||||
let _storage2 = await new ClientStorage(id2, "my-secret-password");
|
let _storage2 = await new ClientStorage(id2, "my-secret-password");
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// console.log("attempting to use store1 WITH PASSWORD")
|
// console.log("attempting to use store1 WITH PASSWORD")
|
||||||
// let _storage1_alt = await new ClientStorage(id1, "password");
|
// let _storage1_alt = await new ClientStorage(id1, "password");
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// console.log("attempting to use store2 WITHOUT PASSWORD")
|
// console.log("attempting to use store2 WITHOUT PASSWORD")
|
||||||
// let _storage2_alt = await ClientStorage.new_unencrypted(id2);
|
// let _storage2_alt = await ClientStorage.new_unencrypted(id2);
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// console.log("attempting to use store2 with WRONG PASSWORD")
|
// console.log("attempting to use store2 with WRONG PASSWORD")
|
||||||
// let _storage2_bad = await new ClientStorage(id2, "bad-password")
|
// let _storage2_bad = await new ClientStorage(id2, "bad-password")
|
||||||
|
|
||||||
|
//
|
||||||
//
|
// console.log("read1: ", await storage1.read());
|
||||||
// console.log("read1: ", await storage1.read());
|
// console.log("read2: ", await storage2.read());
|
||||||
// console.log("read2: ", await storage2.read());
|
//
|
||||||
//
|
// console.log("store1: ", await storage1.store("FOOMP"));
|
||||||
// console.log("store1: ", await storage1.store("FOOMP"));
|
//
|
||||||
//
|
// console.log("read1: ", await storage1.read());
|
||||||
// console.log("read1: ", await storage1.read());
|
// console.log("read2: ", await storage2.read());
|
||||||
// console.log("read2: ", await storage2.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// load WASM package
|
// load WASM package
|
||||||
await wasm_bindgen('nym_client_wasm_bg.wasm');
|
await wasm_bindgen("nym_client_wasm_bg.wasm");
|
||||||
console.log('Loaded WASM');
|
console.log("Loaded WASM");
|
||||||
|
|
||||||
// sets up better stack traces in case of in-rust panics
|
// sets up better stack traces in case of in-rust panics
|
||||||
set_panic_hook();
|
set_panic_hook();
|
||||||
|
|
||||||
// run test on simplified and dedicated tester:
|
// show reconnection capabilities
|
||||||
// await testWithTester()
|
// await testerReconnection()
|
||||||
|
|
||||||
// hook-up the whole client for testing
|
// run test on simplified and dedicated tester:
|
||||||
// await testWithNymClient()
|
await testWithTester();
|
||||||
|
|
||||||
// 'Normal' client setup (to send 'normal' messages)
|
// 'Normal' client setup (to send 'normal' messages)
|
||||||
await normalNymClientUsage()
|
// await normalNymClientUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's get started!
|
// Let's get started!
|
||||||
main();
|
main();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// due to expansion of #[wasm_bindgen] macro on `Debug` Config struct
|
// due to expansion of #[wasm_bindgen] macro on `Debug` Config struct
|
||||||
#![allow(clippy::drop_non_drop)]
|
#![allow(clippy::drop_non_drop)]
|
||||||
// another issue due to #[wasm_bindgen] and `Copy` trait
|
// another issue due to #[wasm_bindgen] and `Copy` trait
|
||||||
#![allow(clippy::drop_copy)]
|
#![allow(dropping_copy_types)]
|
||||||
|
|
||||||
use nym_client_core::config::{
|
use nym_client_core::config::{
|
||||||
Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig,
|
Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig,
|
||||||
@@ -246,6 +246,7 @@ impl From<TopologyWasm> for ConfigTopology {
|
|||||||
topology.topology_resolution_timeout_ms,
|
topology.topology_resolution_timeout_ms,
|
||||||
),
|
),
|
||||||
disable_refreshing: topology.disable_refreshing,
|
disable_refreshing: topology.disable_refreshing,
|
||||||
|
topology_structure: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::storage::errors::ClientStorageError;
|
use crate::storage::error::ClientStorageError;
|
||||||
use crate::topology::WasmTopologyError;
|
use crate::topology::WasmTopologyError;
|
||||||
use js_sys::Promise;
|
use js_sys::Promise;
|
||||||
use nym_client_core::config::GatewayEndpointConfig;
|
use nym_client_core::config::GatewayEndpointConfig;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::config::Config;
|
use crate::client::config::Config;
|
||||||
use crate::storage::errors::ClientStorageError;
|
use crate::storage::error::ClientStorageError;
|
||||||
use js_sys::Promise;
|
use js_sys::Promise;
|
||||||
use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails;
|
use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails;
|
||||||
use nym_crypto::asymmetric::{encryption, identity};
|
use nym_crypto::asymmetric::{encryption, identity};
|
||||||
@@ -15,7 +15,7 @@ use wasm_utils::storage::{IdbVersionChangeEvent, WasmStorage};
|
|||||||
use wasm_utils::PromisableResult;
|
use wasm_utils::PromisableResult;
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
pub(crate) mod errors;
|
pub(crate) mod error;
|
||||||
pub(crate) mod traits;
|
pub(crate) mod traits;
|
||||||
|
|
||||||
const STORAGE_NAME_PREFIX: &str = "wasm-client-storage";
|
const STORAGE_NAME_PREFIX: &str = "wasm-client-storage";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::storage::errors::ClientStorageError;
|
use crate::storage::error::ClientStorageError;
|
||||||
use crate::storage::ClientStorage;
|
use crate::storage::ClientStorage;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use nym_client_core::client::base_client::storage::gateway_details::{
|
use nym_client_core::client::base_client::storage::gateway_details::{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use std::collections::HashSet;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::sync::MutexGuard as AsyncMutexGuard;
|
use tokio::sync::MutexGuard as AsyncMutexGuard;
|
||||||
use wasm_utils::{console_error, console_log, console_warn};
|
use wasm_utils::{console_error, console_log, console_warn};
|
||||||
|
use wasmtimer::tokio::sleep;
|
||||||
|
|
||||||
pub(crate) struct EphemeralTestReceiver<'a> {
|
pub(crate) struct EphemeralTestReceiver<'a> {
|
||||||
sent_packets: u32,
|
sent_packets: u32,
|
||||||
@@ -90,7 +91,7 @@ impl<'a> EphemeralTestReceiver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn perform_test(mut self) -> NodeTestResult {
|
pub(crate) async fn perform_test(mut self) -> NodeTestResult {
|
||||||
let mut timeout_fut = wasm_timer::Delay::new(self.timeout_duration);
|
let mut timeout_fut = sleep(self.timeout_duration);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
// due to expansion of #[wasm_bindgen] macro on NodeTestResult
|
// due to expansion of #[wasm_bindgen] macro on NodeTestResult
|
||||||
#![allow(clippy::drop_non_drop)]
|
#![allow(clippy::drop_non_drop)]
|
||||||
|
|
||||||
|
use crate::error::WasmClientError;
|
||||||
|
use crate::tester::LockedGatewayClient;
|
||||||
|
use js_sys::Promise;
|
||||||
use nym_node_tester_utils::processor::Received;
|
use nym_node_tester_utils::processor::Received;
|
||||||
use nym_node_tester_utils::receiver::ReceivedReceiver;
|
use nym_node_tester_utils::receiver::ReceivedReceiver;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -12,6 +15,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
|
use tokio::sync::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
use wasm_bindgen_futures::future_to_promise;
|
||||||
use wasm_utils::{console_log, console_warn};
|
use wasm_utils::{console_log, console_warn};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -107,3 +111,37 @@ impl Drop for TestMarker {
|
|||||||
self.value.store(false, Ordering::SeqCst)
|
self.value.store(false, Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) trait GatewayReconnection {
|
||||||
|
fn disconnect_from_gateway(&self) -> Promise;
|
||||||
|
|
||||||
|
fn reconnect_to_gateway(&self) -> Promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GatewayReconnection for LockedGatewayClient {
|
||||||
|
fn disconnect_from_gateway(&self) -> Promise {
|
||||||
|
let this = self.clone();
|
||||||
|
|
||||||
|
future_to_promise(async move {
|
||||||
|
let mut guard = this.lock().await;
|
||||||
|
guard
|
||||||
|
.disconnect()
|
||||||
|
.await
|
||||||
|
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
|
||||||
|
Ok(JsValue::undefined())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reconnect_to_gateway(&self) -> Promise {
|
||||||
|
let this = self.clone();
|
||||||
|
|
||||||
|
future_to_promise(async move {
|
||||||
|
let mut guard = this.lock().await;
|
||||||
|
guard
|
||||||
|
.try_reconnect()
|
||||||
|
.await
|
||||||
|
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
|
||||||
|
Ok(JsValue::undefined())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::helpers::{current_network_topology_async, setup_from_topology};
|
|||||||
use crate::storage::ClientStorage;
|
use crate::storage::ClientStorage;
|
||||||
use crate::tester::ephemeral_receiver::EphemeralTestReceiver;
|
use crate::tester::ephemeral_receiver::EphemeralTestReceiver;
|
||||||
use crate::tester::helpers::{
|
use crate::tester::helpers::{
|
||||||
NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
|
GatewayReconnection, NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
|
||||||
};
|
};
|
||||||
use crate::topology::WasmNymTopology;
|
use crate::topology::WasmNymTopology;
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
@@ -73,6 +73,7 @@ pub struct NymNodeTester {
|
|||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct NymNodeTesterBuilder {
|
pub struct NymNodeTesterBuilder {
|
||||||
gateway: Option<IdentityKey>,
|
gateway: Option<IdentityKey>,
|
||||||
|
id: Option<String>,
|
||||||
|
|
||||||
base_topology: NymTopology,
|
base_topology: NymTopology,
|
||||||
|
|
||||||
@@ -94,9 +95,11 @@ impl NymNodeTesterBuilder {
|
|||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
base_topology: WasmNymTopology,
|
base_topology: WasmNymTopology,
|
||||||
|
id: Option<String>,
|
||||||
gateway: Option<IdentityKey>,
|
gateway: Option<IdentityKey>,
|
||||||
) -> NymNodeTesterBuilder {
|
) -> NymNodeTesterBuilder {
|
||||||
NymNodeTesterBuilder {
|
NymNodeTesterBuilder {
|
||||||
|
id,
|
||||||
gateway,
|
gateway,
|
||||||
base_topology: base_topology.into(),
|
base_topology: base_topology.into(),
|
||||||
bandwidth_controller: None,
|
bandwidth_controller: None,
|
||||||
@@ -105,15 +108,20 @@ impl NymNodeTesterBuilder {
|
|||||||
|
|
||||||
async fn _new_with_api(
|
async fn _new_with_api(
|
||||||
api_url: String,
|
api_url: String,
|
||||||
|
id: Option<String>,
|
||||||
gateway: Option<IdentityKey>,
|
gateway: Option<IdentityKey>,
|
||||||
) -> Result<Self, WasmClientError> {
|
) -> Result<Self, WasmClientError> {
|
||||||
let topology = current_network_topology_async(api_url).await?;
|
let topology = current_network_topology_async(api_url).await?;
|
||||||
Ok(NymNodeTesterBuilder::new(topology, gateway))
|
Ok(NymNodeTesterBuilder::new(topology, id, gateway))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_api(gateway: Option<IdentityKey>, api_url: String) -> Promise {
|
pub fn new_with_api(
|
||||||
|
api_url: String,
|
||||||
|
id: Option<String>,
|
||||||
|
gateway: Option<IdentityKey>,
|
||||||
|
) -> Promise {
|
||||||
future_to_promise(async move {
|
future_to_promise(async move {
|
||||||
Self::_new_with_api(api_url, gateway)
|
Self::_new_with_api(api_url, id, gateway)
|
||||||
.await
|
.await
|
||||||
.into_promise_result()
|
.into_promise_result()
|
||||||
})
|
})
|
||||||
@@ -133,7 +141,13 @@ impl NymNodeTesterBuilder {
|
|||||||
async fn _setup_client(mut self) -> Result<NymNodeTester, WasmClientError> {
|
async fn _setup_client(mut self) -> Result<NymNodeTester, WasmClientError> {
|
||||||
let task_manager = TaskManager::default();
|
let task_manager = TaskManager::default();
|
||||||
|
|
||||||
let client_store = ClientStorage::new_async(NODE_TESTER_ID, None).await?;
|
let storage_id = if let Some(client_id) = &self.id {
|
||||||
|
format!("{NODE_TESTER_ID}-{client_id}")
|
||||||
|
} else {
|
||||||
|
NODE_TESTER_ID.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
let client_store = ClientStorage::new_async(&storage_id, None).await?;
|
||||||
|
|
||||||
let init_details = self.gateway_info(&client_store).await?;
|
let init_details = self.gateway_info(&client_store).await?;
|
||||||
let gateway_endpoint = init_details.gateway_details;
|
let gateway_endpoint = init_details.gateway_details;
|
||||||
@@ -234,29 +248,46 @@ async fn test_mixnode(
|
|||||||
impl NymNodeTester {
|
impl NymNodeTester {
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
#[allow(clippy::new_ret_no_self)]
|
#[allow(clippy::new_ret_no_self)]
|
||||||
pub fn new(topology: WasmNymTopology, gateway: Option<IdentityKey>) -> Promise {
|
pub fn new(
|
||||||
|
topology: WasmNymTopology,
|
||||||
|
id: Option<String>,
|
||||||
|
gateway: Option<IdentityKey>,
|
||||||
|
) -> Promise {
|
||||||
console_log!("constructing node tester!");
|
console_log!("constructing node tester!");
|
||||||
NymNodeTesterBuilder::new(topology, gateway).setup_client()
|
NymNodeTesterBuilder::new(topology, id, gateway).setup_client()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn _new_with_api(
|
async fn _new_with_api(
|
||||||
api_url: String,
|
api_url: String,
|
||||||
|
id: Option<String>,
|
||||||
gateway: Option<IdentityKey>,
|
gateway: Option<IdentityKey>,
|
||||||
) -> Result<Self, WasmClientError> {
|
) -> Result<Self, WasmClientError> {
|
||||||
NymNodeTesterBuilder::_new_with_api(api_url, gateway)
|
NymNodeTesterBuilder::_new_with_api(api_url, id, gateway)
|
||||||
.await?
|
.await?
|
||||||
._setup_client()
|
._setup_client()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_api(api_url: String, gateway: Option<IdentityKey>) -> Promise {
|
pub fn new_with_api(
|
||||||
|
api_url: String,
|
||||||
|
id: Option<String>,
|
||||||
|
gateway: Option<IdentityKey>,
|
||||||
|
) -> Promise {
|
||||||
future_to_promise(async move {
|
future_to_promise(async move {
|
||||||
Self::_new_with_api(api_url, gateway)
|
Self::_new_with_api(api_url, id, gateway)
|
||||||
.await
|
.await
|
||||||
.into_promise_result()
|
.into_promise_result()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn disconnect_from_gateway(&self) -> Promise {
|
||||||
|
self.gateway_client.disconnect_from_gateway()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reconnect_to_gateway(&self) -> Promise {
|
||||||
|
self.gateway_client.reconnect_to_gateway()
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_test_packets(
|
fn prepare_test_packets(
|
||||||
&self,
|
&self,
|
||||||
mixnode_identity: String,
|
mixnode_identity: String,
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ impl AsyncFileWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Some(filters) = &self.filters else {
|
let Some(filters) = &self.filters else {
|
||||||
return true
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
for filter in filters {
|
for filter in filters {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric"
|
|||||||
nym-network-defaults = { path = "../network-defaults" }
|
nym-network-defaults = { path = "../network-defaults" }
|
||||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||||
|
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
|
||||||
path = "../client-libs/validator-client"
|
path = "../client-libs/validator-client"
|
||||||
features = ["nyxd-client"]
|
features = ["signing"]
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use nym_crypto::asymmetric::{encryption, identity};
|
|||||||
use nym_network_defaults::VOUCHER_INFO;
|
use nym_network_defaults::VOUCHER_INFO;
|
||||||
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
|
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
|
||||||
use nym_validator_client::nyxd::traits::DkgQueryClient;
|
use nym_validator_client::nyxd::traits::DkgQueryClient;
|
||||||
use nym_validator_client::nyxd::tx::Hash;
|
|
||||||
use nym_validator_client::nyxd::Coin;
|
use nym_validator_client::nyxd::Coin;
|
||||||
|
use nym_validator_client::nyxd::Hash;
|
||||||
use nym_validator_client::CoconutApiClient;
|
use nym_validator_client::CoconutApiClient;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use state::{KeyPair, State};
|
use state::{KeyPair, State};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-bin-common"
|
name = "nym-bin-common"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
description = "Common code for nym binaries"
|
description = "Common code for nym binaries"
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
authors = { workspace = true }
|
authors = { workspace = true }
|
||||||
|
|||||||
@@ -5,9 +5,13 @@
|
|||||||
// and be used by our smart contracts
|
// and be used by our smart contracts
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BinaryBuildInformation {
|
pub struct BinaryBuildInformation {
|
||||||
|
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
|
||||||
|
pub binary_name: &'static str,
|
||||||
|
|
||||||
// VERGEN_BUILD_TIMESTAMP
|
// VERGEN_BUILD_TIMESTAMP
|
||||||
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
|
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
|
||||||
pub build_timestamp: &'static str,
|
pub build_timestamp: &'static str,
|
||||||
@@ -43,8 +47,9 @@ pub struct BinaryBuildInformation {
|
|||||||
|
|
||||||
impl BinaryBuildInformation {
|
impl BinaryBuildInformation {
|
||||||
// explicitly require the build_version to be passed as it's binary specific
|
// explicitly require the build_version to be passed as it's binary specific
|
||||||
pub const fn new(build_version: &'static str) -> Self {
|
pub const fn new(binary_name: &'static str, build_version: &'static str) -> Self {
|
||||||
BinaryBuildInformation {
|
BinaryBuildInformation {
|
||||||
|
binary_name,
|
||||||
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
|
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
|
||||||
build_version,
|
build_version,
|
||||||
commit_sha: env!("VERGEN_GIT_SHA"),
|
commit_sha: env!("VERGEN_GIT_SHA"),
|
||||||
@@ -58,6 +63,7 @@ impl BinaryBuildInformation {
|
|||||||
|
|
||||||
pub fn to_owned(&self) -> BinaryBuildInformationOwned {
|
pub fn to_owned(&self) -> BinaryBuildInformationOwned {
|
||||||
BinaryBuildInformationOwned {
|
BinaryBuildInformationOwned {
|
||||||
|
binary_name: self.binary_name.to_owned(),
|
||||||
build_timestamp: self.build_timestamp.to_owned(),
|
build_timestamp: self.build_timestamp.to_owned(),
|
||||||
build_version: self.build_version.to_owned(),
|
build_version: self.build_version.to_owned(),
|
||||||
commit_sha: self.commit_sha.to_owned(),
|
commit_sha: self.commit_sha.to_owned(),
|
||||||
@@ -70,39 +76,15 @@ impl BinaryBuildInformation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_print(&self) -> String {
|
pub fn pretty_print(&self) -> String {
|
||||||
format!(
|
self.to_owned().to_string()
|
||||||
r#"
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
{:<20}{}
|
|
||||||
"#,
|
|
||||||
"Build Timestamp:",
|
|
||||||
self.build_timestamp,
|
|
||||||
"Build Version:",
|
|
||||||
self.build_version,
|
|
||||||
"Commit SHA:",
|
|
||||||
self.commit_sha,
|
|
||||||
"Commit Date:",
|
|
||||||
self.commit_timestamp,
|
|
||||||
"Commit Branch:",
|
|
||||||
self.commit_branch,
|
|
||||||
"rustc Version:",
|
|
||||||
self.rustc_version,
|
|
||||||
"rustc Channel:",
|
|
||||||
self.rustc_channel,
|
|
||||||
"cargo Profile:",
|
|
||||||
self.cargo_profile,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct BinaryBuildInformationOwned {
|
pub struct BinaryBuildInformationOwned {
|
||||||
|
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
|
||||||
|
pub binary_name: String,
|
||||||
|
|
||||||
// VERGEN_BUILD_TIMESTAMP
|
// VERGEN_BUILD_TIMESTAMP
|
||||||
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
|
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
|
||||||
pub build_timestamp: String,
|
pub build_timestamp: String,
|
||||||
@@ -135,3 +117,62 @@ pub struct BinaryBuildInformationOwned {
|
|||||||
/// Provides the cargo profile that was used for the build, for example `debug`.
|
/// Provides the cargo profile that was used for the build, for example `debug`.
|
||||||
pub cargo_profile: String,
|
pub cargo_profile: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for BinaryBuildInformationOwned {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
r#"
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
{:<20}{}
|
||||||
|
"#,
|
||||||
|
"Binary Name:",
|
||||||
|
self.binary_name,
|
||||||
|
"Build Timestamp:",
|
||||||
|
self.build_timestamp,
|
||||||
|
"Build Version:",
|
||||||
|
self.build_version,
|
||||||
|
"Commit SHA:",
|
||||||
|
self.commit_sha,
|
||||||
|
"Commit Date:",
|
||||||
|
self.commit_timestamp,
|
||||||
|
"Commit Branch:",
|
||||||
|
self.commit_branch,
|
||||||
|
"rustc Version:",
|
||||||
|
self.rustc_version,
|
||||||
|
"rustc Channel:",
|
||||||
|
self.rustc_channel,
|
||||||
|
"cargo Profile:",
|
||||||
|
self.cargo_profile,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// since this macro will get expanded at the callsite, it will pull in correct binary version
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! bin_info {
|
||||||
|
() => {
|
||||||
|
$crate::build_information::BinaryBuildInformation::new(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! bin_info_owned {
|
||||||
|
() => {
|
||||||
|
$crate::build_information::BinaryBuildInformation::new(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
)
|
||||||
|
.to_owned()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-core"
|
name = "nym-client-core"
|
||||||
version = "1.1.14"
|
version = "1.1.15"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.66"
|
rust-version = "1.66"
|
||||||
@@ -10,27 +10,29 @@ rust-version = "1.66"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
base64 = "0.21.2"
|
base64 = "0.21.2"
|
||||||
dirs = "4.0"
|
|
||||||
dashmap = "5.4.0"
|
dashmap = "5.4.0"
|
||||||
|
dirs = "4.0"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
humantime-serde = "1.0"
|
humantime-serde = "1.0"
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||||
|
reqwest = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
thiserror = "1.0.34"
|
thiserror = "1.0.34"
|
||||||
url = { version ="2.2", features = ["serde"] }
|
|
||||||
tungstenite = { version = "0.13.0", default-features = false }
|
|
||||||
tokio = { version = "1.24.1", features = ["macros"]}
|
|
||||||
time = "0.3.17"
|
time = "0.3.17"
|
||||||
|
tokio = { version = "1.24.1", features = ["macros"]}
|
||||||
|
tungstenite = { version = "0.13.0", default-features = false }
|
||||||
|
url = { version ="2.2", features = ["serde"] }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
|
|
||||||
# internal
|
# internal
|
||||||
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
||||||
nym-config = { path = "../config" }
|
nym-config = { path = "../config" }
|
||||||
nym-crypto = { path = "../crypto" }
|
nym-crypto = { path = "../crypto" }
|
||||||
|
nym-explorer-api-requests = { path = "../../explorer-api/explorer-api-requests" }
|
||||||
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
||||||
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
|
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
|
||||||
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
|
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
|
||||||
@@ -45,7 +47,7 @@ nym-network-defaults = { path = "../network-defaults" }
|
|||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
|
||||||
path = "../client-libs/validator-client"
|
path = "../client-libs/validator-client"
|
||||||
features = ["nyxd-client"]
|
features = ["signing", "http-client"]
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
@@ -69,9 +71,9 @@ version = "0.4"
|
|||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
|
||||||
version = "0.2.83"
|
version = "0.2.83"
|
||||||
|
|
||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
|
||||||
git = "https://github.com/mmsinclair/wasm-timer"
|
workspace = true
|
||||||
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
|
features = ["tokio"]
|
||||||
|
|
||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::received_buffer::ReceivedBufferMessage;
|
use super::received_buffer::ReceivedBufferMessage;
|
||||||
|
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
|
||||||
use crate::client::base_client::storage::MixnetClientStorage;
|
use crate::client::base_client::storage::MixnetClientStorage;
|
||||||
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
||||||
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
|
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
|
||||||
@@ -339,14 +340,20 @@ where
|
|||||||
|
|
||||||
fn setup_topology_provider(
|
fn setup_topology_provider(
|
||||||
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||||
|
provider_from_config: config::TopologyStructure,
|
||||||
nym_api_urls: Vec<Url>,
|
nym_api_urls: Vec<Url>,
|
||||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||||
// if no custom provider was ... provided ..., create one using nym-api
|
// if no custom provider was ... provided ..., create one using nym-api
|
||||||
custom_provider.unwrap_or_else(|| {
|
custom_provider.unwrap_or_else(|| match provider_from_config {
|
||||||
Box::new(NymApiTopologyProvider::new(
|
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new(
|
||||||
nym_api_urls,
|
nym_api_urls,
|
||||||
env!("CARGO_PKG_VERSION").to_string(),
|
env!("CARGO_PKG_VERSION").to_string(),
|
||||||
))
|
)),
|
||||||
|
config::TopologyStructure::GeoAware(group) => Box::new(GeoAwareTopologyProvider::new(
|
||||||
|
nym_api_urls,
|
||||||
|
env!("CARGO_PKG_VERSION").to_string(),
|
||||||
|
group,
|
||||||
|
)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,8 +528,10 @@ where
|
|||||||
|
|
||||||
let topology_provider = Self::setup_topology_provider(
|
let topology_provider = Self::setup_topology_provider(
|
||||||
self.custom_topology_provider.take(),
|
self.custom_topology_provider.take(),
|
||||||
|
self.config.debug.topology.topology_structure,
|
||||||
self.config.get_nym_api_endpoints(),
|
self.config.get_nym_api_endpoints(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Self::start_topology_refresher(
|
Self::start_topology_refresher(
|
||||||
topology_provider,
|
topology_provider,
|
||||||
self.config.debug.topology,
|
self.config.debug.topology,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use log::*;
|
|||||||
use nym_sphinx::acknowledgements::AckKey;
|
use nym_sphinx::acknowledgements::AckKey;
|
||||||
use nym_sphinx::addressing::clients::Recipient;
|
use nym_sphinx::addressing::clients::Recipient;
|
||||||
use nym_sphinx::cover::generate_loop_cover_packet;
|
use nym_sphinx::cover::generate_loop_cover_packet;
|
||||||
use nym_sphinx::params::PacketSize;
|
use nym_sphinx::params::{PacketSize, PacketType};
|
||||||
use nym_sphinx::utils::sample_poisson_duration;
|
use nym_sphinx::utils::sample_poisson_duration;
|
||||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
@@ -19,10 +19,10 @@ use std::time::Duration;
|
|||||||
use tokio::sync::mpsc::error::TrySendError;
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time;
|
use tokio::time::{sleep, Sleep};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_timer;
|
use wasmtimer::tokio::{sleep, Sleep};
|
||||||
|
|
||||||
pub struct LoopCoverTrafficStream<R>
|
pub struct LoopCoverTrafficStream<R>
|
||||||
where
|
where
|
||||||
@@ -39,11 +39,7 @@ where
|
|||||||
|
|
||||||
/// Internal state, determined by `average_message_sending_delay`,
|
/// Internal state, determined by `average_message_sending_delay`,
|
||||||
/// used to keep track of when a next packet should be sent out.
|
/// used to keep track of when a next packet should be sent out.
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
next_delay: Pin<Box<Sleep>>,
|
||||||
next_delay: Pin<Box<time::Sleep>>,
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
next_delay: Pin<Box<wasm_timer::Delay>>,
|
|
||||||
|
|
||||||
/// Channel used for sending prepared nym packets to `MixTrafficController` that sends them
|
/// Channel used for sending prepared nym packets to `MixTrafficController` that sends them
|
||||||
/// out to the network without any further delays.
|
/// out to the network without any further delays.
|
||||||
@@ -63,6 +59,8 @@ where
|
|||||||
|
|
||||||
/// Optional secondary predefined packet size used for the loop cover messages.
|
/// Optional secondary predefined packet size used for the loop cover messages.
|
||||||
secondary_packet_size: Option<PacketSize>,
|
secondary_packet_size: Option<PacketSize>,
|
||||||
|
|
||||||
|
packet_type: PacketType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Stream for LoopCoverTrafficStream<R>
|
impl<R> Stream for LoopCoverTrafficStream<R>
|
||||||
@@ -88,17 +86,9 @@ where
|
|||||||
|
|
||||||
// The next interval value is `next_poisson_delay` after the one that just
|
// The next interval value is `next_poisson_delay` after the one that just
|
||||||
// yielded.
|
// yielded.
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let now = self.next_delay.deadline();
|
||||||
{
|
let next = now + next_poisson_delay;
|
||||||
let now = self.next_delay.deadline();
|
self.next_delay.as_mut().reset(next);
|
||||||
let next = now + next_poisson_delay;
|
|
||||||
self.next_delay.as_mut().reset(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
{
|
|
||||||
self.next_delay.as_mut().reset(next_poisson_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
Poll::Ready(Some(()))
|
Poll::Ready(Some(()))
|
||||||
}
|
}
|
||||||
@@ -118,11 +108,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let rng = OsRng;
|
let rng = OsRng;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let next_delay = Box::pin(sleep(Default::default()));
|
||||||
let next_delay = Box::pin(time::sleep(Default::default()));
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let next_delay = Box::pin(wasm_timer::Delay::new(Default::default()));
|
|
||||||
|
|
||||||
LoopCoverTrafficStream {
|
LoopCoverTrafficStream {
|
||||||
ack_key,
|
ack_key,
|
||||||
@@ -135,22 +121,18 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
topology_access,
|
topology_access,
|
||||||
primary_packet_size: traffic_config.primary_packet_size,
|
primary_packet_size: traffic_config.primary_packet_size,
|
||||||
secondary_packet_size: traffic_config.secondary_packet_size,
|
secondary_packet_size: traffic_config.secondary_packet_size,
|
||||||
|
packet_type: traffic_config.packet_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_next_delay(&mut self, amount: Duration) {
|
fn set_next_delay(&mut self, amount: Duration) {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let next_delay = Box::pin(sleep(amount));
|
||||||
let next_delay = Box::pin(time::sleep(amount));
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let next_delay = Box::pin(wasm_timer::Delay::new(amount));
|
|
||||||
|
|
||||||
self.next_delay = next_delay;
|
self.next_delay = next_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loop_cover_message_size(&mut self) -> PacketSize {
|
fn loop_cover_message_size(&mut self) -> PacketSize {
|
||||||
let Some(secondary_packet_size) = self.secondary_packet_size else {
|
let Some(secondary_packet_size) = self.secondary_packet_size else {
|
||||||
return self.primary_packet_size
|
return self.primary_packet_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
let use_primary = self
|
let use_primary = self
|
||||||
@@ -194,7 +176,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
self.average_ack_delay,
|
self.average_ack_delay,
|
||||||
self.cover_traffic.loop_cover_traffic_average_delay,
|
self.cover_traffic.loop_cover_traffic_average_delay,
|
||||||
cover_traffic_packet_size,
|
cover_traffic_packet_size,
|
||||||
nym_sphinx::params::PacketType::Mix,
|
self.packet_type,
|
||||||
)
|
)
|
||||||
.expect("Somehow failed to generate a loop cover message with a valid topology");
|
.expect("Somehow failed to generate a loop cover message with a valid topology");
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,12 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use wasm_timer;
|
|
||||||
|
|
||||||
pub use wasm_timer::*;
|
pub use wasmtimer::{std::Instant, tokio::*};
|
||||||
pub type IntervalStream = gloo_timers::future::IntervalStream;
|
pub type IntervalStream = gloo_timers::future::IntervalStream;
|
||||||
|
|
||||||
pub(crate) fn get_time_now() -> Instant {
|
pub(crate) fn get_time_now() -> Instant {
|
||||||
wasm_timer::Instant::now()
|
Instant::now()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
|
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver};
|
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver};
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ where
|
|||||||
// if secondary packet was never set, then it's obvious we have to use the primary packet
|
// if secondary packet was never set, then it's obvious we have to use the primary packet
|
||||||
let Some(secondary_packet) = self.config.secondary_packet_size else {
|
let Some(secondary_packet) = self.config.secondary_packet_size else {
|
||||||
trace!("only primary packet size is available");
|
trace!("only primary packet size is available");
|
||||||
return self.config.primary_packet_size
|
return self.config.primary_packet_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
let primary_count =
|
let primary_count =
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ use std::sync::Arc;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time;
|
use tokio::time::{sleep, Sleep};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_timer;
|
use wasmtimer::tokio::{sleep, Sleep};
|
||||||
|
|
||||||
mod sending_delay_controller;
|
mod sending_delay_controller;
|
||||||
|
|
||||||
@@ -82,11 +83,7 @@ where
|
|||||||
|
|
||||||
/// Internal state, determined by `average_message_sending_delay`,
|
/// Internal state, determined by `average_message_sending_delay`,
|
||||||
/// used to keep track of when a next packet should be sent out.
|
/// used to keep track of when a next packet should be sent out.
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
next_delay: Option<Pin<Box<Sleep>>>,
|
||||||
next_delay: Option<Pin<Box<time::Sleep>>>,
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
next_delay: Option<Pin<Box<wasm_timer::Delay>>>,
|
|
||||||
|
|
||||||
// To make sure we don't overload the mix_tx channel, we limit the rate we are pushing
|
// To make sure we don't overload the mix_tx channel, we limit the rate we are pushing
|
||||||
// messages.
|
// messages.
|
||||||
@@ -200,7 +197,7 @@ where
|
|||||||
|
|
||||||
fn loop_cover_message_size(&mut self) -> PacketSize {
|
fn loop_cover_message_size(&mut self) -> PacketSize {
|
||||||
let Some(secondary_packet_size) = self.config.traffic.secondary_packet_size else {
|
let Some(secondary_packet_size) = self.config.traffic.secondary_packet_size else {
|
||||||
return self.config.traffic.primary_packet_size
|
return self.config.traffic.primary_packet_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
let use_primary = self
|
let use_primary = self
|
||||||
@@ -373,17 +370,9 @@ where
|
|||||||
|
|
||||||
// The next interval value is `next_poisson_delay` after the one that just
|
// The next interval value is `next_poisson_delay` after the one that just
|
||||||
// yielded.
|
// yielded.
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let now = next_delay.deadline();
|
||||||
{
|
let next = now + next_poisson_delay;
|
||||||
let now = next_delay.deadline();
|
next_delay.as_mut().reset(next);
|
||||||
let next = now + next_poisson_delay;
|
|
||||||
next_delay.as_mut().reset(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
{
|
|
||||||
next_delay.as_mut().reset(next_poisson_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
// On every iteration we get new messages from upstream. Given that these come bunched
|
// On every iteration we get new messages from upstream. Given that these come bunched
|
||||||
// in `Vec`, this ensures that on average we will fetch messages faster than we can
|
// in `Vec`, this ensures that on average we will fetch messages faster than we can
|
||||||
@@ -421,12 +410,7 @@ where
|
|||||||
self.config.traffic.message_sending_average_delay,
|
self.config.traffic.message_sending_average_delay,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let next_delay = Box::pin(sleep(sampled));
|
||||||
let next_delay = Box::pin(time::sleep(sampled));
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let next_delay = Box::pin(wasm_timer::Delay::new(sampled));
|
|
||||||
|
|
||||||
self.next_delay = Some(next_delay);
|
self.next_delay = Some(next_delay);
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
|
|||||||
@@ -727,7 +727,11 @@ where
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else {
|
let Some(last_received) = self
|
||||||
|
.full_reply_storage
|
||||||
|
.surbs_storage_ref()
|
||||||
|
.surbs_last_received_at(pending_reply_target)
|
||||||
|
else {
|
||||||
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size());
|
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size());
|
||||||
to_remove.push(*pending_reply_target);
|
to_remove.push(*pending_reply_target);
|
||||||
continue;
|
continue;
|
||||||
@@ -811,7 +815,8 @@ where
|
|||||||
|
|
||||||
// this should never ever happen (famous last words, eh?), but in case it DOES happen eventually
|
// this should never ever happen (famous last words, eh?), but in case it DOES happen eventually
|
||||||
// purge that malformed data
|
// purge that malformed data
|
||||||
let Ok(sent_at) = OffsetDateTime::from_unix_timestamp(reply_key.sent_at_timestamp) else {
|
let Ok(sent_at) = OffsetDateTime::from_unix_timestamp(reply_key.sent_at_timestamp)
|
||||||
|
else {
|
||||||
error!("somehow our stored timestamp ({}) for one of our reply key is corrupted!. Going to remove all the entry", reply_key.sent_at_timestamp);
|
error!("somehow our stored timestamp ({}) for one of our reply key is corrupted!. Going to remove all the entry", reply_key.sent_at_timestamp);
|
||||||
to_remove_keys.push(*digest);
|
to_remove_keys.push(*digest);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -0,0 +1,319 @@
|
|||||||
|
use std::{collections::HashMap, fmt};
|
||||||
|
|
||||||
|
use log::{debug, error, info};
|
||||||
|
use nym_explorer_api_requests::PrettyDetailedMixNodeBond;
|
||||||
|
use nym_topology::{
|
||||||
|
nym_topology_from_detailed,
|
||||||
|
provider_trait::{async_trait, TopologyProvider},
|
||||||
|
NymTopology,
|
||||||
|
};
|
||||||
|
use nym_validator_client::client::MixId;
|
||||||
|
use rand::{prelude::SliceRandom, thread_rng};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
const MIN_NODES_PER_LAYER: usize = 1;
|
||||||
|
const EXPLORER_API_MIXNODES_URL: &str = "https://explorer.nymtech.net/api/v1/mix-nodes";
|
||||||
|
|
||||||
|
// TODO: create a explorer-api-client
|
||||||
|
async fn fetch_mixnodes_from_explorer_api() -> Option<Vec<PrettyDetailedMixNodeBond>> {
|
||||||
|
reqwest::get(EXPLORER_API_MIXNODES_URL)
|
||||||
|
.await
|
||||||
|
.ok()?
|
||||||
|
.json::<Vec<PrettyDetailedMixNodeBond>>()
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
|
pub enum CountryGroup {
|
||||||
|
Europe,
|
||||||
|
NorthAmerica,
|
||||||
|
SouthAmerica,
|
||||||
|
Oceania,
|
||||||
|
Asia,
|
||||||
|
Africa,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountryGroup {
|
||||||
|
// We map contry codes into group, which initially are continent codes to a first approximation,
|
||||||
|
// but we do it manually to reserve the right to tweak this distribution for our purposes.
|
||||||
|
fn new(country_code: &str) -> Self {
|
||||||
|
let country_code = country_code.to_uppercase();
|
||||||
|
use CountryGroup::*;
|
||||||
|
match country_code.as_ref() {
|
||||||
|
// Europe
|
||||||
|
"AT" => Europe,
|
||||||
|
"BG" => Europe,
|
||||||
|
"CH" => Europe,
|
||||||
|
"CY" => Europe,
|
||||||
|
"CZ" => Europe,
|
||||||
|
"DE" => Europe,
|
||||||
|
"DK" => Europe,
|
||||||
|
"ES" => Europe,
|
||||||
|
"FI" => Europe,
|
||||||
|
"FR" => Europe,
|
||||||
|
"GB" => Europe,
|
||||||
|
"GR" => Europe,
|
||||||
|
"IE" => Europe,
|
||||||
|
"IT" => Europe,
|
||||||
|
"LT" => Europe,
|
||||||
|
"LU" => Europe,
|
||||||
|
"LV" => Europe,
|
||||||
|
"MD" => Europe,
|
||||||
|
"MT" => Europe,
|
||||||
|
"NL" => Europe,
|
||||||
|
"NO" => Europe,
|
||||||
|
"PL" => Europe,
|
||||||
|
"RO" => Europe,
|
||||||
|
"SE" => Europe,
|
||||||
|
"SK" => Europe,
|
||||||
|
"TR" => Europe,
|
||||||
|
"UA" => Europe,
|
||||||
|
|
||||||
|
// North America
|
||||||
|
"CA" => NorthAmerica,
|
||||||
|
"MX" => NorthAmerica,
|
||||||
|
"US" => NorthAmerica,
|
||||||
|
|
||||||
|
// South America
|
||||||
|
"AR" => SouthAmerica,
|
||||||
|
"BR" => SouthAmerica,
|
||||||
|
"CL" => SouthAmerica,
|
||||||
|
"CO" => SouthAmerica,
|
||||||
|
"CR" => SouthAmerica,
|
||||||
|
"GT" => SouthAmerica,
|
||||||
|
|
||||||
|
// Oceania
|
||||||
|
"AU" => Oceania,
|
||||||
|
|
||||||
|
// Asia
|
||||||
|
"AM" => Asia,
|
||||||
|
"BH" => Asia,
|
||||||
|
"CN" => Asia,
|
||||||
|
"GE" => Asia,
|
||||||
|
"HK" => Asia,
|
||||||
|
"ID" => Asia,
|
||||||
|
"IL" => Asia,
|
||||||
|
"IN" => Asia,
|
||||||
|
"JP" => Asia,
|
||||||
|
"KH" => Asia,
|
||||||
|
"KR" => Asia,
|
||||||
|
"KZ" => Asia,
|
||||||
|
"MY" => Asia,
|
||||||
|
"RU" => Asia,
|
||||||
|
"SG" => Asia,
|
||||||
|
"TH" => Asia,
|
||||||
|
"VN" => Asia,
|
||||||
|
|
||||||
|
// Africa
|
||||||
|
"SC" => Africa,
|
||||||
|
"UG" => Africa,
|
||||||
|
"ZA" => Africa,
|
||||||
|
|
||||||
|
// And group level codes work too
|
||||||
|
"EU" => Europe,
|
||||||
|
"NA" => NorthAmerica,
|
||||||
|
"SA" => SouthAmerica,
|
||||||
|
"OC" => Oceania,
|
||||||
|
"AS" => Asia,
|
||||||
|
"AF" => Africa,
|
||||||
|
|
||||||
|
// And some aliases
|
||||||
|
"EUROPE" => Europe,
|
||||||
|
"NORTHAMERICA" => NorthAmerica,
|
||||||
|
"SOUTHAMERICA" => SouthAmerica,
|
||||||
|
"OCEANIA" => Oceania,
|
||||||
|
"ASIA" => Asia,
|
||||||
|
"AFRICA" => Africa,
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
info!("Unknown country code: {}", country_code);
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CountryGroup {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
use CountryGroup::*;
|
||||||
|
match self {
|
||||||
|
Europe => write!(f, "EU"),
|
||||||
|
NorthAmerica => write!(f, "NA"),
|
||||||
|
SouthAmerica => write!(f, "SA"),
|
||||||
|
Oceania => write!(f, "OC"),
|
||||||
|
Asia => write!(f, "AS"),
|
||||||
|
Africa => write!(f, "AF"),
|
||||||
|
Unknown => write!(f, "Unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for CountryGroup {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let group = CountryGroup::new(s);
|
||||||
|
if group == CountryGroup::Unknown {
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
Ok(group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountryGroup {
|
||||||
|
#[allow(unused)]
|
||||||
|
fn known(self) -> Option<CountryGroup> {
|
||||||
|
use CountryGroup::*;
|
||||||
|
match self {
|
||||||
|
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
|
||||||
|
Unknown => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_mixnodes_by_country_code(
|
||||||
|
mixnodes: Vec<PrettyDetailedMixNodeBond>,
|
||||||
|
) -> HashMap<CountryGroup, Vec<MixId>> {
|
||||||
|
mixnodes
|
||||||
|
.into_iter()
|
||||||
|
.fold(HashMap::<CountryGroup, Vec<MixId>>::new(), |mut acc, m| {
|
||||||
|
if let Some(ref location) = m.location {
|
||||||
|
let country_code = location.two_letter_iso_country_code.clone();
|
||||||
|
let group_code = CountryGroup::new(country_code.as_str());
|
||||||
|
let mixnodes = acc.entry(group_code).or_insert_with(Vec::new);
|
||||||
|
mixnodes.push(m.mix_id);
|
||||||
|
}
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<MixId>>) {
|
||||||
|
let mixnode_distribution = mixnodes
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| format!("{}: {}", k, v.len()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
debug!("Mixnode distribution - {}", mixnode_distribution);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
|
||||||
|
let mixes = topology.mixes();
|
||||||
|
if mixes.keys().len() < 3 {
|
||||||
|
error!("Layer is missing in topology!");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
for (layer, mixnodes) in mixes {
|
||||||
|
debug!("Layer {:?} has {} mixnodes", layer, mixnodes.len());
|
||||||
|
if mixnodes.len() < MIN_NODES_PER_LAYER {
|
||||||
|
error!(
|
||||||
|
"There are only {} mixnodes in layer {:?}",
|
||||||
|
mixnodes.len(),
|
||||||
|
layer
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GeoAwareTopologyProvider {
|
||||||
|
validator_client: nym_validator_client::client::NymApiClient,
|
||||||
|
filter_on: CountryGroup,
|
||||||
|
client_version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GeoAwareTopologyProvider {
|
||||||
|
pub fn new(
|
||||||
|
mut nym_api_urls: Vec<Url>,
|
||||||
|
client_version: String,
|
||||||
|
filter_on: CountryGroup,
|
||||||
|
) -> GeoAwareTopologyProvider {
|
||||||
|
log::info!(
|
||||||
|
"Creating geo-aware topology provider with filter on {:?}",
|
||||||
|
filter_on
|
||||||
|
);
|
||||||
|
nym_api_urls.shuffle(&mut thread_rng());
|
||||||
|
|
||||||
|
GeoAwareTopologyProvider {
|
||||||
|
validator_client: nym_validator_client::client::NymApiClient::new(
|
||||||
|
nym_api_urls[0].clone(),
|
||||||
|
),
|
||||||
|
filter_on,
|
||||||
|
client_version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_topology(&self) -> Option<NymTopology> {
|
||||||
|
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
|
||||||
|
Err(err) => {
|
||||||
|
error!("failed to get network mixnodes - {err}");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(mixes) => mixes,
|
||||||
|
};
|
||||||
|
|
||||||
|
let gateways = match self.validator_client.get_cached_gateways().await {
|
||||||
|
Err(err) => {
|
||||||
|
error!("failed to get network gateways - {err}");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(gateways) => gateways,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Also fetch mixnodes cached by explorer-api, with the purpose of getting their
|
||||||
|
// geolocation.
|
||||||
|
debug!("Fetching mixnodes from explorer-api...");
|
||||||
|
let Some(mixnodes_from_explorer_api) = fetch_mixnodes_from_explorer_api().await else {
|
||||||
|
error!("failed to get mixnodes from explorer-api");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Partition mixnodes_from_explorer_api according to the value of
|
||||||
|
// two_letter_iso_country_code.
|
||||||
|
// NOTE: we construct the full distribution here, but only use the one we're interested in.
|
||||||
|
// The reason we this instead of a straight filter is that this opens up the possibility to
|
||||||
|
// complement a small grouping with mixnodes from adjecent countries.
|
||||||
|
let mixnode_distribution = group_mixnodes_by_country_code(mixnodes_from_explorer_api);
|
||||||
|
log_mixnode_distribution(&mixnode_distribution);
|
||||||
|
|
||||||
|
let Some(filtered_mixnode_ids) = mixnode_distribution.get(&self.filter_on) else {
|
||||||
|
error!("no mixnodes found for: {}", self.filter_on);
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mixnodes = mixnodes
|
||||||
|
.into_iter()
|
||||||
|
.filter(|m| filtered_mixnode_ids.contains(&m.mix_id()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let topology = nym_topology_from_detailed(mixnodes, gateways)
|
||||||
|
.filter_system_version(&self.client_version);
|
||||||
|
|
||||||
|
// TODO: return real error type
|
||||||
|
check_layer_integrity(topology.clone()).ok()?;
|
||||||
|
|
||||||
|
Some(topology)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
#[async_trait]
|
||||||
|
impl TopologyProvider for GeoAwareTopologyProvider {
|
||||||
|
// this will be manually refreshed on a timer specified inside mixnet client config
|
||||||
|
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||||
|
self.get_topology().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl TopologyProvider for GeoAwareTopologyProvider {
|
||||||
|
// this will be manually refreshed on a timer specified inside mixnet client config
|
||||||
|
async fn get_new_topology(&mut self) -> Option<NymTopology> {
|
||||||
|
self.get_topology().await
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ use nym_topology::NymTopologyError;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
mod accessor;
|
mod accessor;
|
||||||
|
pub mod geo_aware_provider;
|
||||||
pub(crate) mod nym_api_provider;
|
pub(crate) mod nym_api_provider;
|
||||||
|
|
||||||
// TODO: move it to config later
|
// TODO: move it to config later
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ impl<T> TransmissionBuffer<T> {
|
|||||||
|
|
||||||
while items.len() < n {
|
while items.len() < n {
|
||||||
let Some(next) = self.pop_next_message_at_random(rng) else {
|
let Some(next) = self.pop_next_message_at_random(rng) else {
|
||||||
break
|
break;
|
||||||
};
|
};
|
||||||
items.push(next)
|
items.push(next)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::error::ClientCoreError;
|
use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
@@ -137,14 +137,55 @@ impl Config {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_no_cover_traffic(&mut self) {
|
||||||
|
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
|
||||||
|
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
|
||||||
|
if disabled {
|
||||||
|
self.set_no_cover_traffic_with_keepalive()
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
|
||||||
|
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||||
|
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
|
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
|
||||||
self.debug.topology.disable_refreshing = disable_topology_refresh;
|
self.debug.topology.disable_refreshing = disable_topology_refresh;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_no_cover_traffic(&mut self) {
|
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
|
||||||
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
|
self.set_topology_structure(topology_structure);
|
||||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
|
||||||
|
self.debug.topology.topology_structure = topology_structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
||||||
|
if no_per_hop_delays {
|
||||||
|
self.set_no_per_hop_delays()
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_no_per_hop_delays(&mut self) {
|
||||||
|
self.debug.traffic.average_packet_delay = Duration::ZERO;
|
||||||
|
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
|
||||||
|
self.set_secondary_packet_size(secondary_packet_size);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
|
||||||
|
self.debug.traffic.secondary_packet_size = secondary_packet_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_custom_version(&mut self, version: &str) {
|
pub fn set_custom_version(&mut self, version: &str) {
|
||||||
@@ -282,7 +323,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default, deny_unknown_fields)]
|
||||||
pub struct Traffic {
|
pub struct Traffic {
|
||||||
/// The parameter of Poisson distribution determining how long, on average,
|
/// The parameter of Poisson distribution determining how long, on average,
|
||||||
/// sent packet is going to be delayed at any given mix node.
|
/// sent packet is going to be delayed at any given mix node.
|
||||||
@@ -434,6 +475,16 @@ pub struct Topology {
|
|||||||
/// the first valid instance.
|
/// the first valid instance.
|
||||||
/// Supersedes `topology_refresh_rate_ms`.
|
/// Supersedes `topology_refresh_rate_ms`.
|
||||||
pub disable_refreshing: bool,
|
pub disable_refreshing: bool,
|
||||||
|
|
||||||
|
/// Specifies the mixnode topology to be used for sending packets.
|
||||||
|
pub topology_structure: TopologyStructure,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum TopologyStructure {
|
||||||
|
#[default]
|
||||||
|
NymApi,
|
||||||
|
GeoAware(CountryGroup),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Topology {
|
impl Default for Topology {
|
||||||
@@ -442,6 +493,7 @@ impl Default for Topology {
|
|||||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||||
disable_refreshing: false,
|
disable_refreshing: false,
|
||||||
|
topology_structure: TopologyStructure::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ impl From<TopologyV1_1_20_2> for Topology {
|
|||||||
topology_refresh_rate: value.topology_refresh_rate,
|
topology_refresh_rate: value.topology_refresh_rate,
|
||||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||||
disable_refreshing: value.disable_refreshing,
|
disable_refreshing: value.disable_refreshing,
|
||||||
|
topology_structure: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,17 +27,22 @@ use tokio_tungstenite::connect_async;
|
|||||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
|
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient;
|
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_timer::Instant;
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
use wasm_utils::websocket::JSWebsocket;
|
use wasm_utils::websocket::JSWebsocket;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasmtimer::std::Instant;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasmtimer::tokio::sleep;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
type WsConn = JSWebsocket;
|
type WsConn = JSWebsocket;
|
||||||
|
|
||||||
|
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
|
||||||
const MEASUREMENTS: usize = 3;
|
const MEASUREMENTS: usize = 3;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -124,15 +129,9 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
|
|||||||
Ok::<(), ClientCoreError>(())
|
Ok::<(), ClientCoreError>(())
|
||||||
};
|
};
|
||||||
|
|
||||||
// thanks to wasm we can't use tokio::time::timeout : (
|
let timeout = sleep(PING_TIMEOUT);
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let timeout = tokio::time::sleep(PING_TIMEOUT);
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
tokio::pin!(timeout);
|
tokio::pin!(timeout);
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let mut timeout = wasm_timer::Delay::new(PING_TIMEOUT);
|
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = &mut timeout => {
|
_ = &mut timeout => {
|
||||||
warn!("timed out while trying to perform measurement...")
|
warn!("timed out while trying to perform measurement...")
|
||||||
@@ -158,23 +157,29 @@ pub(super) async fn choose_gateway_by_latency<R: Rng>(
|
|||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
gateways: &[gateway::Node],
|
gateways: &[gateway::Node],
|
||||||
) -> Result<gateway::Node, ClientCoreError> {
|
) -> Result<gateway::Node, ClientCoreError> {
|
||||||
info!("choosing gateway by latency...");
|
info!(
|
||||||
|
"choosing gateway by latency, pinging {} gateways ...",
|
||||||
|
gateways.len()
|
||||||
|
);
|
||||||
|
|
||||||
let mut gateways_with_latency = Vec::new();
|
let gateways_with_latency = Arc::new(tokio::sync::Mutex::new(Vec::new()));
|
||||||
for gateway in gateways {
|
futures::stream::iter(gateways)
|
||||||
let id = *gateway.identity();
|
.for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async {
|
||||||
trace!("measuring latency to {id}...");
|
let id = *gateway.identity();
|
||||||
let with_latency = match measure_latency(gateway).await {
|
trace!("measuring latency to {id}...");
|
||||||
Ok(res) => res,
|
match measure_latency(gateway).await {
|
||||||
Err(err) => {
|
Ok(with_latency) => {
|
||||||
warn!("failed to measure {id}: {err}");
|
debug!("{id}: {:?}", with_latency.latency);
|
||||||
continue;
|
gateways_with_latency.lock().await.push(with_latency);
|
||||||
}
|
}
|
||||||
};
|
Err(err) => {
|
||||||
debug!("{id}: {:?}", with_latency.latency);
|
warn!("failed to measure {id}: {err}");
|
||||||
gateways_with_latency.push(with_latency)
|
}
|
||||||
}
|
};
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let gateways_with_latency = gateways_with_latency.lock().await;
|
||||||
let chosen = gateways_with_latency
|
let chosen = gateways_with_latency
|
||||||
.choose_weighted(rng, |item| 1. / item.latency.as_secs_f32())
|
.choose_weighted(rng, |item| 1. / item.latency.as_secs_f32())
|
||||||
.expect("invalid selection weight!");
|
.expect("invalid selection weight!");
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ path = "../../wasm-utils"
|
|||||||
features = ["websocket"]
|
features = ["websocket"]
|
||||||
|
|
||||||
# only import it in wasm. Prefer proper tokio timer in non-wasm
|
# only import it in wasm. Prefer proper tokio timer in non-wasm
|
||||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
|
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
|
||||||
git = "https://github.com/mmsinclair/wasm-timer"
|
workspace = true
|
||||||
rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
|
features = ["tokio"]
|
||||||
|
|
||||||
# this is due to tungstenite using `rand` 0.8 and associated changes in `getrandom` crate
|
# this is due to tungstenite using `rand` 0.8 and associated changes in `getrandom` crate
|
||||||
# which now does not support wasm32-unknown-unknown target by default.
|
# which now does not support wasm32-unknown-unknown target by default.
|
||||||
|
|||||||
@@ -31,14 +31,16 @@ use tungstenite::protocol::Message;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use nym_validator_client::nyxd::traits::DkgQueryClient;
|
use nym_validator_client::nyxd::traits::DkgQueryClient;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use tokio::time::sleep;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio_tungstenite::connect_async;
|
use tokio_tungstenite::connect_async;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
|
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_timer;
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
use wasm_utils::websocket::JSWebsocket;
|
use wasm_utils::websocket::JSWebsocket;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasmtimer::tokio::sleep;
|
||||||
|
|
||||||
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
|
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
|
||||||
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
|
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
|
||||||
@@ -198,15 +200,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
tokio::time::sleep(self.reconnection_backoff).await;
|
sleep(self.reconnection_backoff).await;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
if let Err(err) = wasm_timer::Delay::new(self.reconnection_backoff).await {
|
|
||||||
error!(
|
|
||||||
"the timer has gone away while in reconnection backoff! - {}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// final attempt (done separately to be able to return a proper error)
|
// final attempt (done separately to be able to return a proper error)
|
||||||
@@ -235,16 +229,9 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
_ => return Err(GatewayClientError::ConnectionInInvalidState),
|
_ => return Err(GatewayClientError::ConnectionInInvalidState),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
let timeout = sleep(self.response_timeout_duration);
|
||||||
let timeout = tokio::time::sleep(self.response_timeout_duration);
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
tokio::pin!(timeout);
|
tokio::pin!(timeout);
|
||||||
|
|
||||||
// technically the `wasm_timer` also works outside wasm, but unless required,
|
|
||||||
// I really prefer to just stick to tokio
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let mut timeout = wasm_timer::Delay::new(self.response_timeout_duration);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = self.shutdown.recv() => {
|
_ = self.shutdown.recv() => {
|
||||||
@@ -724,7 +711,7 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
|
pub async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
|
||||||
if !self.connection.is_established() {
|
if !self.connection.is_established() {
|
||||||
self.establish_connection().await?;
|
self.establish_connection().await?;
|
||||||
}
|
}
|
||||||
@@ -738,6 +725,12 @@ impl<C, St> GatewayClient<C, St> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn disconnect(&mut self) -> Result<(), GatewayClientError> {
|
||||||
|
self.recover_socket_connection().await?;
|
||||||
|
self.connection = SocketState::NotConnected;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
|
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
|
||||||
where
|
where
|
||||||
C: DkgQueryClient + Send + Sync,
|
C: DkgQueryClient + Send + Sync,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user