Compare commits
477 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6dbb3fbd3f | |||
| 95b6ac50be | |||
| 5f2247ab83 | |||
| 842bcfa782 | |||
| c2938e0672 | |||
| 278516ad11 | |||
| ce241339bf | |||
| 8d7428923a | |||
| 4a1a4b6415 | |||
| 65a45bc0a8 | |||
| 5932974108 | |||
| ce34e45afc | |||
| afcefa9432 | |||
| d346fdcff9 | |||
| a05a7e261a | |||
| ab9c892f8a | |||
| ca7bfef865 | |||
| f8c9397afd | |||
| 0c215efdb2 | |||
| e1efcda3dd | |||
| 59056a22c5 | |||
| 13841e813b | |||
| da775af00a | |||
| bd99474f26 | |||
| 9c70244157 | |||
| 736edcbe00 | |||
| 40e215473e | |||
| 6746514317 | |||
| 50a332eb2b | |||
| 08f1b176db | |||
| 00e2319be3 | |||
| ecd566432b | |||
| b6dc81304c | |||
| 6337cd9966 | |||
| b41b8f94a4 | |||
| 52ced9d3ad | |||
| 5eb2249ad5 | |||
| 008fc045b7 | |||
| 38cc3b9e38 | |||
| 989285e009 | |||
| c6e438600f | |||
| 1dab01ca33 | |||
| 53e0432934 | |||
| a1f2d33397 | |||
| 49aa79b5df | |||
| 6f3b5fad15 | |||
| 0efa909374 | |||
| 43b102782e | |||
| d6e6bab6a6 | |||
| 1a3cdc3128 | |||
| 39f75907e5 | |||
| 029c2698d7 | |||
| 60548770ba | |||
| 39cfc2057b | |||
| 4fbae2d5bd | |||
| 9feee4c174 | |||
| bca6b45273 | |||
| d9733a97ae | |||
| e66dc01966 | |||
| 2b4aca0194 | |||
| 06aa09afcd | |||
| ddc09bbb2e | |||
| 3003be5e68 | |||
| cb2ce87ab7 | |||
| 2ad65fc455 | |||
| cb292b38c0 | |||
| b710f796f9 | |||
| fb5a9a7a3e | |||
| 071720c1cc | |||
| 6679944689 | |||
| bec7814756 | |||
| 592b3b3bb1 | |||
| c2ff786f41 | |||
| 63dd26ca1b | |||
| 07b6114adf | |||
| 07155b4fe5 | |||
| 8b635a44b8 | |||
| 568862a571 | |||
| f24d6e224d | |||
| f9a154b36c | |||
| 72d994880b | |||
| fe02bc4631 | |||
| 1fb8e1bbaf | |||
| 96aa355db3 | |||
| 8dfb9c8173 | |||
| 382d3e130e | |||
| a8246621e1 | |||
| 7868725fed | |||
| d30667d8e4 | |||
| 66b6a8aeef | |||
| 3483a9e7f9 | |||
| 893b28c51c | |||
| 93165ad699 | |||
| 2ebb498589 | |||
| 47ffdfe496 | |||
| 51bced8766 | |||
| d4286aeb76 | |||
| 929a780315 | |||
| c7cdd1e1b4 | |||
| 8575a72a22 | |||
| 9d03bec14b | |||
| ce93e5f677 | |||
| 7c826ef881 | |||
| ac666b7a1d | |||
| 83a9b993a1 | |||
| 4b691d19a0 | |||
| fe4fcc7fdf | |||
| a6e40443a4 | |||
| 0a583bd48a | |||
| 96ccce1049 | |||
| 89d0ff5624 | |||
| 2391d11758 | |||
| 902c674ff1 | |||
| 160328a08e | |||
| 9fea869bbc | |||
| c66d7ed489 | |||
| 0e86761a13 | |||
| 19d603ba1a | |||
| b30f680549 | |||
| 55463da0da | |||
| 518daeaf20 | |||
| f6ec12db94 | |||
| 379dd1f02b | |||
| 38804279e8 | |||
| 3907cd17fe | |||
| 1e921186ad | |||
| 67c69cbec9 | |||
| abc5dd8b92 | |||
| c791de426a | |||
| 4c5d4ac4a4 | |||
| 48c1fcaf93 | |||
| 31594c7a79 | |||
| 8ec3c04a39 | |||
| d653ecde1e | |||
| ba7fecde6f | |||
| 5b9b4743dc | |||
| 5f9b384efa | |||
| d69526fad9 | |||
| e10a4e8fca | |||
| 9016878868 | |||
| 835a915f25 | |||
| 1ca6e4a002 | |||
| f9c73183db | |||
| d296100ffa | |||
| 06669fe114 | |||
| 8022fc7e31 | |||
| 2b915fd0aa | |||
| 4e45c54d17 | |||
| 9c16e5ebfa | |||
| 0113141efd | |||
| 614d096929 | |||
| fe7df3a909 | |||
| b14f6ab159 | |||
| e6040b0ecc | |||
| 60e6d23fd8 | |||
| 5dc57d2a3e | |||
| fd619cad51 | |||
| 953c0915d1 | |||
| acb1aa8df0 | |||
| d30038c570 | |||
| b9ef848523 | |||
| e3813b4868 | |||
| b7bc713cd4 | |||
| b966f962c8 | |||
| 61a0e5bbfb | |||
| 698cdc524d | |||
| 448aba0917 | |||
| b813e1fee0 | |||
| 23de430f93 | |||
| 9462bc726d | |||
| 3d2eaeeabb | |||
| a732a676e0 | |||
| d6a8fcda9c | |||
| 3628cd92c9 | |||
| 8d26acbc7e | |||
| 07b971fe92 | |||
| 2a539dc3cc | |||
| 562eb639a2 | |||
| 91dd830a5e | |||
| 18837220f4 | |||
| 3fb9737db4 | |||
| 4d0b5b34ec | |||
| 6af0dbd1da | |||
| 2004148710 | |||
| 1e805be5ad | |||
| 7a25e600b3 | |||
| 1fd7d54715 | |||
| 0575f01f9b | |||
| 43a6e62050 | |||
| 39fb131d95 | |||
| 9533c2440a | |||
| aab2be1fbd | |||
| 448dcbeaa8 | |||
| 29b07b4904 | |||
| cceb7a40bd | |||
| fb4b32359d | |||
| 7ca92cc487 | |||
| 15d612eff6 | |||
| 021c2d14f2 | |||
| 3b85927a90 | |||
| b386388b82 | |||
| 7941b7099f | |||
| 6604d927c5 | |||
| 4fedf05b64 | |||
| fa00f85a31 | |||
| abf5a2d307 | |||
| 8e0000cb0b | |||
| cc27911671 | |||
| b598f1d1db | |||
| d4f10c1d68 | |||
| 1d7ff40d02 | |||
| 72703b36e1 | |||
| ecf7a40010 | |||
| 272e9187d2 | |||
| 69a1f3773c | |||
| 15c97b1cae | |||
| 2660ef59f7 | |||
| 12a06d9dfe | |||
| 6399cd24c8 | |||
| f30b5162e8 | |||
| 229329ae4c | |||
| a3bb5e466d | |||
| 65d893a70b | |||
| e0944e5238 | |||
| b451d4b709 | |||
| 1507e48158 | |||
| 6e7a7ed4a6 | |||
| af4801ac47 | |||
| b748c55d4e | |||
| 84e5bfc286 | |||
| 96bd9ecf49 | |||
| 092851976f | |||
| 9da1f82cca | |||
| 8c60927fe2 | |||
| ec5ef1db56 | |||
| 5dee6dd44f | |||
| aa6f5ad664 | |||
| 201b5cc56f | |||
| 510553a697 | |||
| b81967c9f5 | |||
| fadff7888b | |||
| 24854f9254 | |||
| 8ea7726e81 | |||
| ea32a897b2 | |||
| 5d7a14c5ab | |||
| cad68b8d6c | |||
| 1d125ed97f | |||
| 36d4ec5a72 | |||
| 44981b8621 | |||
| bd68797432 | |||
| 636759789c | |||
| c03a859223 | |||
| b269cdae31 | |||
| 2177a396b9 | |||
| 4c50dd64f4 | |||
| be9d3a48bb | |||
| 37d890c634 | |||
| 6287583f4b | |||
| c7760c6c10 | |||
| 2c0058c477 | |||
| 02fb2e56ca | |||
| 8b2c72eb91 | |||
| 805eb31728 | |||
| 22d4c89e48 | |||
| 28d5ac92b3 | |||
| a2e678587c | |||
| 0ac7bb5f03 | |||
| 7f45cbd5df | |||
| 8ce709bbb4 | |||
| 46db139f79 | |||
| 069c5bf332 | |||
| 54a4653e7d | |||
| ea1f689c71 | |||
| 3d60299b22 | |||
| 4d9dfac812 | |||
| 0012294dc0 | |||
| 5b5063676f | |||
| 833556020d | |||
| 0cdb68bcf3 | |||
| aa00eb70d5 | |||
| a882d10848 | |||
| c03a58ae9a | |||
| 2caf79fba0 | |||
| eda1822653 | |||
| 0f1ff5ffd2 | |||
| 9512fc34f0 | |||
| 75348922fc | |||
| 938eb2d0f0 | |||
| ede51fa589 | |||
| 7e0711ce12 | |||
| 822f40239f | |||
| 31149e6ba1 | |||
| ba233b6016 | |||
| 3d17ab6a4b | |||
| 492f1dd199 | |||
| 172399f792 | |||
| 22407c2911 | |||
| bdace0f9cb | |||
| 15bbba590b | |||
| a72264c685 | |||
| 2612cca708 | |||
| fc16d1c839 | |||
| f22bb282ab | |||
| d907b6b81a | |||
| 1903938035 | |||
| bb646c4f6a | |||
| 99e64a7bc1 | |||
| 7b960fa8a4 | |||
| 4c65ef3a2f | |||
| a4d84ffb1b | |||
| c495762a42 | |||
| 8d60a3ef6e | |||
| e24f8aa219 | |||
| de864fe828 | |||
| 8bc8671678 | |||
| c37d6b9296 | |||
| a4d1d2c354 | |||
| 0a59e21d97 | |||
| 911a3d0c04 | |||
| 163d4ff5fb | |||
| 2b84b5472b | |||
| c4ad3b8f05 | |||
| fe33df723b | |||
| 3a0e499199 | |||
| ce23662270 | |||
| c6e41ca3f3 | |||
| 9f0971f8a9 | |||
| 538616af54 | |||
| 6333042826 | |||
| b6d9ca2056 | |||
| 844d612808 | |||
| 9becf5457f | |||
| 3d07f1eeb9 | |||
| 0747e12273 | |||
| 5f4d56c1d8 | |||
| 390e58f603 | |||
| 6cf16d9c8f | |||
| 1368ab133e | |||
| ff1d92b576 | |||
| 1703a0a6f5 | |||
| 344eb92396 | |||
| 8a77287eaa | |||
| 9bfda6a254 | |||
| 147be7afd9 | |||
| 0a2ce7fa6d | |||
| 72f24c2c9d | |||
| f5b5d139ac | |||
| 2da6fdc2e8 | |||
| f7574924a8 | |||
| 5d07115706 | |||
| 9e994dfd55 | |||
| 59bc7cb53d | |||
| 655ff9bffb | |||
| a03cb1ef9f | |||
| 60f965ec52 | |||
| 8d26e48a5b | |||
| 94527ab594 | |||
| e312a28aad | |||
| e84a0c4438 | |||
| 6f1a0d987d | |||
| 48ceb9d1ce | |||
| e82e8b8bc3 | |||
| 3caa4c15ca | |||
| 741131f376 | |||
| ae6f161cd6 | |||
| b940c87d64 | |||
| fe6c685ab1 | |||
| c64c36022f | |||
| e52fe65985 | |||
| fea64d4d4f | |||
| 6ff02bc2a1 | |||
| 8b166f12f8 | |||
| ecdbe034fa | |||
| 3e46c8630d | |||
| 93e962524a | |||
| 5b6c1c032c | |||
| 135f1a6e7f | |||
| c61f89144e | |||
| 67fe368e65 | |||
| 522229459b | |||
| e3d8b71ea2 | |||
| 4f98fde362 | |||
| aa75e54419 | |||
| 5190a541a6 | |||
| 3a39fff006 | |||
| 0e302b83ab | |||
| 0d0637fe19 | |||
| 1f0c0090dc | |||
| 4f960330b1 | |||
| a273980aa0 | |||
| 13a55f00d8 | |||
| 4feec780d4 | |||
| 35c044c340 | |||
| ac5539a0fa | |||
| 9c569cbb62 | |||
| 72485cacd3 | |||
| 56d36d2c46 | |||
| 8fb54dd4e7 | |||
| 44d59ff8c2 | |||
| a8caf19f8c | |||
| 53b44fb9c6 | |||
| c0959e853e | |||
| 144df00782 | |||
| be4708cc84 | |||
| d5cddec03c | |||
| 7c26cab4e6 | |||
| f0bcf8c36f | |||
| ac2f0a172e | |||
| 898070bc87 | |||
| cc707660aa | |||
| 31624cf4e4 | |||
| e6a69170a4 | |||
| bc5e19514e | |||
| 5c76b8483e | |||
| a9526c216f | |||
| 903af16a6b | |||
| 0de79b6953 | |||
| fd2fafb52a | |||
| fadb5b4ff9 | |||
| 955583d0f0 | |||
| 3924c53d09 | |||
| c0025ee9c6 | |||
| 7dd0516b63 | |||
| d3cd3c9157 | |||
| 83680473e0 | |||
| 7f9a9f7a0a | |||
| e7ccb38502 | |||
| 1f4c19d396 | |||
| 64842f40d7 | |||
| 2ec18721fc | |||
| 2ef1ac452f | |||
| 6b3700aefe | |||
| e2e06df4e6 | |||
| 835d4f46f6 | |||
| d71ef635e2 | |||
| 6e3773a095 | |||
| 17a30be842 | |||
| d785d621ec | |||
| 904caca9de | |||
| 050d370396 | |||
| 29340ed00c | |||
| 2b062b3e5b | |||
| b405adb9e5 | |||
| 5c3c0ac39e | |||
| 1cc06ef349 | |||
| 2bef1603ab | |||
| 11a458a43d | |||
| 55775b6e7b | |||
| bb959544af | |||
| f7853c5531 | |||
| e6d2626fd7 | |||
| 08a2bc5c8d | |||
| 6d09e6fa7c | |||
| b1f4ae434a | |||
| 1647c368fb | |||
| 1fbf37e0ec | |||
| 1acdb0c519 | |||
| bc8efda08f | |||
| cecd0b2b0a | |||
| 62fa2ae5e4 | |||
| db2ce8070c | |||
| 70138ff54a | |||
| 30e93c33bb | |||
| ec4955f814 | |||
| e013517348 | |||
| 2041b03046 | |||
| 0b6adf59ce | |||
| d95df4b286 | |||
| 4f109169af | |||
| 0cef1abbb2 | |||
| 1871c6b2e3 | |||
| 75ad2a113f | |||
| 1d1496aa49 | |||
| a48e06fe51 | |||
| 614b99a36e | |||
| d8cb6199e0 | |||
| e2302466cc |
@@ -15,8 +15,8 @@
|
|||||||
* @futurechimp @mmsinclair
|
* @futurechimp @mmsinclair
|
||||||
|
|
||||||
# Rust rules:
|
# Rust rules:
|
||||||
*.rs @durch @futurechimp @jstuczyn @neacsu
|
*.rs @durch @futurechimp @jstuczyn @neacsu @octol
|
||||||
Cargo.* @durch @futurechimp @jstuczyn @neacsu
|
Cargo.* @durch @futurechimp @jstuczyn @neacsu @octol
|
||||||
|
|
||||||
# JS rules:
|
# JS rules:
|
||||||
*.js @mmsinclair @fmtabbara @Aid19801
|
*.js @mmsinclair @fmtabbara @Aid19801
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
name: CI for ts-packages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'ts-packages/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: custom-runner-linux
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install rsync
|
||||||
|
run: sudo apt-get install rsync
|
||||||
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '16'
|
||||||
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
|
- name: Build
|
||||||
|
run: yarn && yarn build && yarn build:ci
|
||||||
|
- name: Deploy branch to CI www (storybook)
|
||||||
|
continue-on-error: true
|
||||||
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
|
ARGS: "-rltgoDzvO --delete"
|
||||||
|
SOURCE: "ts-packages/dist/storybook/"
|
||||||
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ts-${{ env.GITHUB_REF_SLUG }}
|
||||||
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
|
- name: Deploy branch to CI www (example)
|
||||||
|
continue-on-error: true
|
||||||
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
|
ARGS: "-rltgoDzvO --delete"
|
||||||
|
SOURCE: "ts-packages/dist/example/"
|
||||||
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ts-${{ env.GITHUB_REF_SLUG }}-example
|
||||||
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
|
- name: Keybase - Node Install
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files
|
||||||
|
- name: Keybase - Send Notification
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: 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##*/}"
|
||||||
|
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
|
||||||
|
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
|
||||||
|
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
|
||||||
|
KEYBASE_NYM_CHANNEL: "ci-ts-packages"
|
||||||
|
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||||
|
uses: docker://keybaseio/client:stable-node
|
||||||
|
with:
|
||||||
|
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||||
@@ -9,28 +9,14 @@ on:
|
|||||||
- 'explorer/**'
|
- 'explorer/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
matrix_prep:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
||||||
steps:
|
|
||||||
# creates the matrix strategy from build_matrix_includes.json
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- id: set-matrix
|
|
||||||
uses: JoshuaTheMiller/conditional-build-matrix@main
|
|
||||||
with:
|
|
||||||
inputFile: '.github/workflows/build_matrix_includes.json'
|
|
||||||
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
|
|
||||||
build:
|
build:
|
||||||
needs: matrix_prep
|
runs-on: [ self-hosted, custom-linux-exoscale ]
|
||||||
strategy:
|
# Enable sccache via environment variable
|
||||||
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
|
env:
|
||||||
runs-on: ${{ matrix.os }}
|
RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
|
||||||
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.os == 'windows-latest' }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install Dependencies (Linux)
|
||||||
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||||
if: matrix.os == 'ubuntu-latest'
|
|
||||||
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@@ -39,7 +25,7 @@ jobs:
|
|||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: ${{ matrix.rust }}
|
toolchain: stable
|
||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|
||||||
@@ -47,13 +33,13 @@ jobs:
|
|||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --all
|
args: --workspace
|
||||||
|
|
||||||
- name: Run all tests
|
- name: Run all tests
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --all
|
args: --workspace --all-features
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
@@ -63,40 +49,30 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions-rs/clippy-check@v1
|
- uses: actions-rs/clippy-check@v1
|
||||||
name: Clippy checks
|
name: Clippy checks
|
||||||
# if: matrix.os == 'ubuntu-latest' && matrix.rust == 'stable'
|
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
args: --all-features
|
args: --all-features
|
||||||
|
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
if: ${{ matrix.rust != 'nightly' }}
|
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: -- -D warnings
|
args: --workspace -- -D warnings
|
||||||
|
|
||||||
# COCONUT stuff
|
|
||||||
- name: Reclaim some disk space (because Windows is being annoying)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
if: ${{ matrix.os == 'windows-latest' }}
|
|
||||||
with:
|
|
||||||
command: clean
|
|
||||||
|
|
||||||
- name: Build all binaries with coconut enabled
|
- name: Build all binaries with coconut enabled
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --all --features=coconut
|
args: --workspace --features=coconut
|
||||||
|
|
||||||
- name: Run all tests with coconut enabled
|
- name: Run all tests with coconut enabled
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --all --features=coconut
|
args: --workspace --features=coconut
|
||||||
|
|
||||||
- name: Run clippy with coconut enabled
|
- name: Run clippy with coconut enabled
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
if: ${{ matrix.rust != 'nightly' }}
|
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --features=coconut -- -D warnings
|
args: --features=coconut -- -D warnings
|
||||||
|
|||||||
@@ -10,41 +10,10 @@
|
|||||||
"rust":"stable",
|
"rust":"stable",
|
||||||
"runOnEvent":"pull_request"
|
"runOnEvent":"pull_request"
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"os":"macos-latest",
|
"os":"macos-latest",
|
||||||
"rust":"stable",
|
"rust":"stable",
|
||||||
"runOnEvent":"pull_request"
|
"runOnEvent":"pull_request"
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"os":"ubuntu-latest",
|
|
||||||
"rust":"beta",
|
|
||||||
"runOnEvent":"pull_request"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"os":"windows-latest",
|
|
||||||
"rust":"beta",
|
|
||||||
"runOnEvent":"pull_request"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"os":"macos-latest",
|
|
||||||
"rust":"beta",
|
|
||||||
"runOnEvent":"pull_request"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"os":"ubuntu-latest",
|
|
||||||
"rust":"nightly",
|
|
||||||
"runOnEvent":"pull_request"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"os":"windows-latest",
|
|
||||||
"rust":"nightly",
|
|
||||||
"runOnEvent":"pull_request"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"os":"macos-latest",
|
|
||||||
"rust":"nightly",
|
|
||||||
"runOnEvent":"pull_request"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
RUSTFLAGS: '-C link-arg=-s'
|
RUSTFLAGS: '-C link-arg=-s'
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --manifest-path contracts/Cargo.toml --all --target wasm32-unknown-unknown
|
args: --manifest-path contracts/Cargo.toml --workspace --target wasm32-unknown-unknown
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
@@ -61,4 +61,4 @@ jobs:
|
|||||||
if: ${{ matrix.rust != 'nightly' }}
|
if: ${{ matrix.rust != 'nightly' }}
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --manifest-path contracts/Cargo.toml --all -- -D warnings
|
args: --manifest-path contracts/Cargo.toml --workspace -- -D warnings
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '16'
|
||||||
- run: npm install
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
- name: Run ESLint
|
- name: Run ESLint
|
||||||
# GitHub should automatically annotate the PR
|
# GitHub should automatically annotate the PR
|
||||||
run: npm run lint
|
run: yarn && yarn lint
|
||||||
@@ -19,14 +19,17 @@ jobs:
|
|||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '16'
|
||||||
- run: npm install
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
- name: Build shared packages
|
||||||
|
run: cd .. && yarn && yarn build
|
||||||
- name: Set environment from the example
|
- name: Set environment from the example
|
||||||
run: cp .env.prod .env
|
run: cp .env.prod .env
|
||||||
- run: npm run test
|
# - run: yarn test
|
||||||
continue-on-error: true
|
# continue-on-error: true
|
||||||
- run: npm run build
|
- run: yarn && yarn build
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- name: Deploy branch to CI www
|
- name: Deploy branch to CI www
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -41,9 +44,10 @@ jobs:
|
|||||||
EXCLUDE: "/dist/, /node_modules/"
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
- name: Keybase - Node Install
|
- name: Keybase - Node Install
|
||||||
run: npm install
|
run: npm install
|
||||||
working-directory: .github/workflows/support-files/messages
|
working-directory: .github/workflows/support-files
|
||||||
- name: Keybase - Send Notification
|
- name: Keybase - Send Notification
|
||||||
env:
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: network-explorer
|
||||||
NYM_PROJECT_NAME: "Network Explorer"
|
NYM_PROJECT_NAME: "Network Explorer"
|
||||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||||
NYM_CI_WWW_LOCATION: "network-explorer-${{ env.GITHUB_REF_SLUG }}"
|
NYM_CI_WWW_LOCATION: "network-explorer-${{ env.GITHUB_REF_SLUG }}"
|
||||||
@@ -56,4 +60,4 @@ jobs:
|
|||||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||||
uses: docker://keybaseio/client:stable-node
|
uses: docker://keybaseio/client:stable-node
|
||||||
with:
|
with:
|
||||||
args: .github/workflows/support-files/messages/entry_point_notifications.sh
|
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
name: Nightly builds
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '14 4 * * *'
|
||||||
|
jobs:
|
||||||
|
matrix_prep:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
# creates the matrix strategy from nightly_build_matrix_includes.json
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- id: set-matrix
|
||||||
|
uses: JoshuaTheMiller/conditional-build-matrix@main
|
||||||
|
with:
|
||||||
|
inputFile: '.github/workflows/nightly_build_matrix_includes.json'
|
||||||
|
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
|
||||||
|
build:
|
||||||
|
needs: matrix_prep
|
||||||
|
strategy:
|
||||||
|
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.rust == 'stable' }}
|
||||||
|
steps:
|
||||||
|
- name: Install Dependencies (Linux)
|
||||||
|
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install rust toolchain
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: ${{ matrix.rust }}
|
||||||
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
|
||||||
|
- name: Build all binaries
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --workspace
|
||||||
|
|
||||||
|
- name: Run all tests
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --workspace
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: fmt
|
||||||
|
args: --all -- --check
|
||||||
|
|
||||||
|
- name: Reclaim some disk space (because Windows is being annoying)
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
if: ${{ matrix.os == 'windows-latest' }}
|
||||||
|
with:
|
||||||
|
command: clean
|
||||||
|
|
||||||
|
- uses: actions-rs/clippy-check@v1
|
||||||
|
name: Clippy checks
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
args: --all-features
|
||||||
|
|
||||||
|
- name: Run clippy
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
if: ${{ matrix.rust != 'nightly' }}
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
|
|
||||||
|
# COCONUT stuff
|
||||||
|
- name: Build all binaries with coconut enabled
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --workspace --features=coconut
|
||||||
|
|
||||||
|
- name: Run all tests with coconut enabled
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --workspace --features=coconut
|
||||||
|
|
||||||
|
- name: Run clippy with coconut enabled
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
if: ${{ matrix.rust != 'nightly' }}
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --workspace --all-targets --features=coconut -- -D warnings
|
||||||
|
notification:
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Collect jobs status
|
||||||
|
uses: technote-space/workflow-conclusion-action@v2
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Keybase - Node Install
|
||||||
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files
|
||||||
|
- name: Keybase - Send Notification
|
||||||
|
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: nightly
|
||||||
|
NYM_PROJECT_NAME: "Nym nightly build"
|
||||||
|
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||||
|
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||||
|
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
|
||||||
|
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
|
||||||
|
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
|
||||||
|
KEYBASE_NYM_CHANNEL: "ci-nightly"
|
||||||
|
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
|
||||||
|
uses: docker://keybaseio/client:stable-node
|
||||||
|
with:
|
||||||
|
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"os":"ubuntu-latest",
|
||||||
|
"rust":"stable",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"os":"windows-latest",
|
||||||
|
"rust":"stable",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"os":"macos-latest",
|
||||||
|
"rust":"stable",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"os":"ubuntu-latest",
|
||||||
|
"rust":"beta",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"os":"windows-latest",
|
||||||
|
"rust":"beta",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"os":"macos-latest",
|
||||||
|
"rust":"beta",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"os":"ubuntu-latest",
|
||||||
|
"rust":"nightly",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"os":"windows-latest",
|
||||||
|
"rust":"nightly",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"os":"macos-latest",
|
||||||
|
"rust":"nightly",
|
||||||
|
"runOnEvent":"schedule"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
name: Publish Nym binaries
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-nym:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: [ubuntu-latest]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Check the release tag starts with `nym-binaries-`
|
||||||
|
if: startsWith(github.ref, 'refs/tags/nym-binaries-') == false
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('Release tag did not start with nym-binaries-...')
|
||||||
|
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Build all binaries
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --workspace --release
|
||||||
|
|
||||||
|
- name: Upload to release based on tag name
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
target/release/nym-client
|
||||||
|
target/release/nym-gateway
|
||||||
|
target/release/nym-mixnode
|
||||||
|
target/release/nym-socks5-client
|
||||||
|
target/release/nym-validator-api
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
name: Publish Nym Wallet (MacOS)
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: nym-wallet
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-tauri:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: [macos-latest]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Check the release tag starts with `nym-wallet-`
|
||||||
|
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('Release tag did not start with nym-wallet-...')
|
||||||
|
|
||||||
|
- name: Node v16
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 16.x
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
- name: Install the Apple developer certificate for code signing
|
||||||
|
env:
|
||||||
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
# create variables
|
||||||
|
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||||
|
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||||
|
|
||||||
|
# import certificate and provisioning profile from secrets
|
||||||
|
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
|
||||||
|
|
||||||
|
# create temporary keychain
|
||||||
|
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||||
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
|
||||||
|
# import certificate to keychain
|
||||||
|
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||||
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||||
|
|
||||||
|
- name: Install app dependencies and build it
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||||
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
|
run: yarn && yarn build
|
||||||
|
|
||||||
|
- name: Upload to release based on tag name
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: nym-wallet/target/release/bundle/dmg/*.dmg
|
||||||
|
|
||||||
|
- name: Clean up keychain
|
||||||
|
if: ${{ always() }}
|
||||||
|
run: |
|
||||||
|
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
name: Publish Nym Wallet (Ubuntu)
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: nym-wallet
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-tauri:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: [ubuntu-latest]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Tauri dependencies
|
||||||
|
run: >
|
||||||
|
sudo apt-get update &&
|
||||||
|
sudo apt-get install -y webkit2gtk-4.0
|
||||||
|
- name: Check the release tag starts with `nym-wallet-`
|
||||||
|
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('Release tag did not start with nym-wallet-...')
|
||||||
|
|
||||||
|
- name: Node v16
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 16.x
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
- name: Install app dependencies and build it
|
||||||
|
run: yarn && yarn build
|
||||||
|
|
||||||
|
- name: Upload to release based on tag name
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: nym-wallet/target/release/bundle/appimage/*.AppImage
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
name: Publish Nym Wallet (Windows 10)
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: nym-wallet
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-tauri:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: [windows10]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- name: Clean up first
|
||||||
|
continue-on-error: true
|
||||||
|
working-directory: .
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
del /s /q /A:H nym
|
||||||
|
rmdir /s /q nym
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Check the release tag starts with `nym-wallet-`
|
||||||
|
if: startsWith(github.ref, 'refs/tags/nym-wallet-') == false
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('Release tag did not start with nym-wallet-...')
|
||||||
|
|
||||||
|
- name: Import signing certificate
|
||||||
|
env:
|
||||||
|
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
|
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
New-Item -ItemType directory -Path certificate
|
||||||
|
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
||||||
|
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
||||||
|
Remove-Item -path certificate -include tempCert.txt
|
||||||
|
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||||
|
|
||||||
|
- name: Node v16
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 16.x
|
||||||
|
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Install app dependencies
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
- name: Build and sign it
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
|
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||||
|
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- name: Upload to release based on tag name
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: nym-wallet/target/release/bundle/msi/*.msi
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
name: Publish Nym Wallet
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- nym-wallet-*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Run a one-line script
|
|
||||||
run: echo Hello, world!
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
name: Generate TS types
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- "explorer/**"
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- "explorer/**"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
nym-wallet-types:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
steps:
|
|
||||||
- name: Prepare
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y libpango1.0-dev libatk1.0-dev libgdk-pixbuf2.0-dev libsoup2.4-dev librust-gdk-dev libwebkit2gtk-4.0-dev
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
- name: Generate TS
|
|
||||||
run: cd nym-wallet/src-tauri && cargo test
|
|
||||||
- uses: EndBug/add-and-commit@v7.2.1 # https://github.com/marketplace/actions/add-commit
|
|
||||||
with:
|
|
||||||
add: '["nym-wallet"]'
|
|
||||||
message: "[ci skip] Generate TS types"
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
KEYBASE_NYM_CHANNEL=
|
||||||
|
KEYBASE_NYMBOT_USERNAME=
|
||||||
|
KEYBASE_NYMBOT_PAPERKEY=
|
||||||
|
|
||||||
|
NYM_NOTIFICATION_KIND=nightly
|
||||||
|
NYM_PROJECT_NAME=Nightly Build
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
# Custom GitHub Actions mock env vars
|
||||||
|
IS_SUCCESS=true
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
# GitHub Actions context mock env vars
|
||||||
|
GITHUB_SHA=abcdef
|
||||||
|
GITHUB_RUN_ID=123456
|
||||||
|
GITHUB_REPOSITORY=nymtech/nym
|
||||||
|
GITHUB_SERVER_URL=https://github.com
|
||||||
|
GIT_BRANCH_NAME=feature/testing-support-files
|
||||||
|
GIT_BRANCH=feature/testing-support-files
|
||||||
|
GIT_COMMIT_MESSAGE=This is the commit message
|
||||||
|
GITHUB_ACTOR=octocat
|
||||||
|
|
||||||
|
# add a Personal Access Token (PAT) generated from GitHub here for use in testing
|
||||||
|
GITHUB_TOKEN=
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
# Network Explorer
|
||||||
|
NYM_CI_WWW_LOCATION=some-branch
|
||||||
|
NYM_CI_WWW_BASE=example.com
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
# Nightly builds
|
||||||
|
WORKFLOW_CONCLUSION=success
|
||||||
|
|
||||||
|
SHOW_DEBUG=true
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# don't commit the lock file to avoid cross-platform issues
|
||||||
|
package-lock.json
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
16
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# GitHub Actions Support Files
|
||||||
|
|
||||||
|
This is a collection of scripts and files to support GitHub Actions.
|
||||||
|
|
||||||
|
## Sending Notifications
|
||||||
|
|
||||||
|
These scripts send CI notifications to Keybase by creating messages from templates and env vars passed from GitHub Actions.
|
||||||
|
|
||||||
|
### Adding notifications to a GitHub Action
|
||||||
|
|
||||||
|
```
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
...
|
||||||
|
- name: Notifications - Node Install
|
||||||
|
run: npm install
|
||||||
|
working-directory: .github/workflows/support-files/notifications
|
||||||
|
- name: Notifications - Send
|
||||||
|
env:
|
||||||
|
NYM_NOTIFICATION_KIND: "my-component"
|
||||||
|
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||||
|
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
|
||||||
|
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
|
||||||
|
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
|
||||||
|
KEYBASE_NYM_CHANNEL: "ci-network-explorer"
|
||||||
|
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||||
|
uses: docker://keybaseio/client:stable-node
|
||||||
|
with:
|
||||||
|
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Notifications are run by adding the snippet above to a GitHub Action, and:
|
||||||
|
|
||||||
|
1. Installing node packages needed at run time
|
||||||
|
2. Set the env vars as required:
|
||||||
|
- `NYM_NOTIFICATION_KIND` matches the directory in `.github/workflows/support-files/${NYM_NOTIFICATION_KIND}` to provide the templates and extra scripting in `index.js`
|
||||||
|
- Keybase credentials, channel and other env vars for the status of the build and repo
|
||||||
|
3. Replacing the default entry point shell script on the `keybaseio/client:stable-node` docker image to run `.github/workflows/support-files/notifications/entry_point.sh`
|
||||||
|
|
||||||
|
### Running locally
|
||||||
|
|
||||||
|
You will need:
|
||||||
|
- Node 16 LTS
|
||||||
|
- npm
|
||||||
|
|
||||||
|
Copy `.github/workflows/support-files/.env.example` to `.github/workflows/support-files/.env` and valid Keybase credentials.
|
||||||
|
|
||||||
|
Then run `npm install` to get dependencies.
|
||||||
|
|
||||||
|
Start development mode for the notification type you want either by passing the value as an env var called `NYM_NOTIFICATION_KIND` or set the `.env` file values correctly.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd .github/workflows/support-files
|
||||||
|
npm install
|
||||||
|
cp .env.example .env
|
||||||
|
vi .env
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
require('./notifications/send_message');
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
.idea
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
const Bot = require('keybase-bot');
|
|
||||||
const Handlebars = require('handlebars');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const data = { env: process.env };
|
|
||||||
// const data = { ...PASTE TEST DATA HERE ... }; // -- DEV: uncomment to set test data
|
|
||||||
|
|
||||||
// validation of environment
|
|
||||||
if(!(process.env.NYM_PROJECT_NAME || data.env.NYM_PROJECT_NAME)) {
|
|
||||||
throw new Error('Please set env var NYM_PROJECT_NAME with the project name for displaying in notification messages');
|
|
||||||
}
|
|
||||||
const keybaseChannel = process.env.KEYBASE_NYM_CHANNEL || data.env.KEYBASE_NYM_CHANNEL;
|
|
||||||
if(!keybaseChannel) {
|
|
||||||
throw new Error('Please set env var KEYBASE_NYM_CHANNEL with the channel name for the notification message');
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract the git branch name
|
|
||||||
const GIT_BRANCH_NAME = (process.env.GITHUB_REF || data.env.GITHUB_REF).split('/').slice(2).join('/');
|
|
||||||
|
|
||||||
data.env.GIT_BRANCH_NAME = GIT_BRANCH_NAME;
|
|
||||||
const source = fs
|
|
||||||
.readFileSync(process.env.IS_SUCCESS === 'true' ? 'success' : 'failure')
|
|
||||||
.toString();
|
|
||||||
const template = Handlebars.compile(source);
|
|
||||||
const result = template(data);
|
|
||||||
|
|
||||||
// -- DEV: uncomment to show what is available in the handlebars template / show the result
|
|
||||||
// console.dir({ data }, { depth: null });
|
|
||||||
// console.log(result);
|
|
||||||
|
|
||||||
const bot = new Bot();
|
|
||||||
try {
|
|
||||||
const username = process.env.KEYBASE_NYMBOT_USERNAME;
|
|
||||||
const paperkey = process.env.KEYBASE_NYMBOT_PAPERKEY;
|
|
||||||
|
|
||||||
if(!username) {
|
|
||||||
throw new Error('Username is not defined. Please set env var KEYBASE_NYMBOT_USERNAME');
|
|
||||||
}
|
|
||||||
if(!paperkey) {
|
|
||||||
throw new Error('Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Initialising keybase with user "${username}" and key: "${'*'.repeat(paperkey.length)}"...`);
|
|
||||||
await bot.init(username, paperkey, { verbose: false });
|
|
||||||
|
|
||||||
const channel = {
|
|
||||||
name: 'nymtech_bot',
|
|
||||||
membersType: 'team',
|
|
||||||
topicName: keybaseChannel,
|
|
||||||
topic_type: 'CHAT',
|
|
||||||
};
|
|
||||||
const message = {
|
|
||||||
body: result,
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(`Sending to ${channel.name}#${channel.topicName}...`);
|
|
||||||
await bot.chat.send(channel, message);
|
|
||||||
|
|
||||||
console.log('Message sent!');
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
process.exitCode = -1;
|
|
||||||
} finally {
|
|
||||||
await bot.deinit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
const Handlebars = require('handlebars');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
async function addToContextAndValidate(context) {
|
||||||
|
if (!context.env.NYM_CI_WWW_LOCATION) {
|
||||||
|
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
|
||||||
|
}
|
||||||
|
if (!context.env.NYM_CI_WWW_BASE) {
|
||||||
|
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMessageBody(context) {
|
||||||
|
const source = fs
|
||||||
|
.readFileSync(
|
||||||
|
context.env.IS_SUCCESS === 'true'
|
||||||
|
? path.resolve(__dirname, 'templates', 'success')
|
||||||
|
: path.resolve(__dirname, 'templates', 'failure'),
|
||||||
|
)
|
||||||
|
.toString();
|
||||||
|
const template = Handlebars.compile(source);
|
||||||
|
return template(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addToContextAndValidate,
|
||||||
|
getMessageBody,
|
||||||
|
};
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||||
|
|
||||||
Commit message:
|
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
|
||||||
```
|
```
|
||||||
{{ env.GIT_COMMIT_MESSAGE }}
|
{{ env.GIT_COMMIT_MESSAGE }}
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
const Handlebars = require('handlebars');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { Octokit, App } = require('octokit');
|
||||||
|
|
||||||
|
async function addToContextAndValidate(context) {
|
||||||
|
if (!context.env.WORKFLOW_CONCLUSION) {
|
||||||
|
throw new Error('Please ensure the env var WORKFLOW_CONCLUSION is set');
|
||||||
|
}
|
||||||
|
if (!context.env.GITHUB_TOKEN) {
|
||||||
|
throw new Error('Please ensure the env var GITHUB_TOKEN is set');
|
||||||
|
}
|
||||||
|
if (!context.env.GITHUB_RUN_ID) {
|
||||||
|
throw new Error('Please ensure the env var GITHUB_RUN_ID is set');
|
||||||
|
}
|
||||||
|
if (!context.env.GITHUB_REPOSITORY) {
|
||||||
|
throw new Error('Please ensure the env var GITHUB_REPOSITORY is set');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMessageBody(context) {
|
||||||
|
const source = fs
|
||||||
|
.readFileSync(
|
||||||
|
context.env.WORKFLOW_CONCLUSION === 'success'
|
||||||
|
? path.resolve(__dirname, 'templates', 'success')
|
||||||
|
: path.resolve(__dirname, 'templates', 'failure'),
|
||||||
|
)
|
||||||
|
.toString();
|
||||||
|
const template = Handlebars.compile(source);
|
||||||
|
|
||||||
|
// get job details from GitHub API
|
||||||
|
const octokit = new Octokit({ auth: context.env.GITHUB_TOKEN });
|
||||||
|
const [owner, repo] = context.env.GITHUB_REPOSITORY.split('/');
|
||||||
|
const {
|
||||||
|
data: { jobs },
|
||||||
|
} = await octokit.rest.actions.listJobsForWorkflowRun({
|
||||||
|
run_id: context.env.GITHUB_RUN_ID,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
});
|
||||||
|
|
||||||
|
// uncomment this to see what is available for each job
|
||||||
|
if(process.env.SHOW_DEBUG) {
|
||||||
|
console.dir(jobs, { depth: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
a sample of the response is:
|
||||||
|
|
||||||
|
{
|
||||||
|
total_count: 10,
|
||||||
|
jobs: [
|
||||||
|
{
|
||||||
|
id: 5182940024,
|
||||||
|
run_id: 1840752095,
|
||||||
|
run_url: 'https://api.github.com/repos/nymtech/nym/actions/runs/1840752095',
|
||||||
|
run_attempt: 1,
|
||||||
|
node_id: 'CR_kwDODdjOis8AAAABNO1jeA',
|
||||||
|
head_sha: 'aa00eb70d57751bfa556bd3602df87c7473367fc',
|
||||||
|
url: 'https://api.github.com/repos/nymtech/nym/actions/jobs/5182940024',
|
||||||
|
html_url: 'https://github.com/nymtech/nym/runs/5182940024?check_suite_focus=true',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'success',
|
||||||
|
started_at: '2022-02-14T11:28:34Z',
|
||||||
|
completed_at: '2022-02-14T11:28:38Z',
|
||||||
|
name: 'matrix_prep',
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
name: 'Set up job',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'success',
|
||||||
|
number: 1,
|
||||||
|
started_at: '2022-02-14T13:28:34.000+02:00',
|
||||||
|
completed_at: '2022-02-14T13:28:36.000+02:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Run actions/checkout@v2',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'success',
|
||||||
|
number: 2,
|
||||||
|
started_at: '2022-02-14T13:28:36.000+02:00',
|
||||||
|
completed_at: '2022-02-14T13:28:37.000+02:00'
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
check_run_url: 'https://api.github.com/repos/nymtech/nym/check-runs/5182940024',
|
||||||
|
labels: [ 'ubuntu-latest' ],
|
||||||
|
runner_id: 1,
|
||||||
|
runner_name: 'Hosted Agent',
|
||||||
|
runner_group_id: 2,
|
||||||
|
runner_group_name: 'GitHub Actions'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5182943473,
|
||||||
|
run_id: 1840752095,
|
||||||
|
run_url: 'https://api.github.com/repos/nymtech/nym/actions/runs/1840752095',
|
||||||
|
run_attempt: 1,
|
||||||
|
node_id: 'CR_kwDODdjOis8AAAABNO1w8Q',
|
||||||
|
head_sha: 'aa00eb70d57751bfa556bd3602df87c7473367fc',
|
||||||
|
url: 'https://api.github.com/repos/nymtech/nym/actions/jobs/5182943473',
|
||||||
|
html_url: 'https://github.com/nymtech/nym/runs/5182943473?check_suite_focus=true',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'failure',
|
||||||
|
started_at: '2022-02-14T11:29:04Z',
|
||||||
|
completed_at: '2022-02-14T11:55:45Z',
|
||||||
|
name: 'build (macos-latest, stable, schedule)',
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
name: 'Set up job',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'success',
|
||||||
|
number: 1,
|
||||||
|
started_at: '2022-02-14T13:29:04.000+02:00',
|
||||||
|
completed_at: '2022-02-14T13:29:26.000+02:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Install Dependencies (Linux)',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'skipped',
|
||||||
|
number: 2,
|
||||||
|
started_at: '2022-02-14T13:29:26.000+02:00',
|
||||||
|
completed_at: '2022-02-14T13:29:26.000+02:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Keybase - Send Notification',
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: 'failure',
|
||||||
|
number: 15,
|
||||||
|
started_at: '2022-02-14T13:55:44.000+02:00',
|
||||||
|
completed_at: '2022-02-14T13:55:44.000+02:00'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
check_run_url: 'https://api.github.com/repos/nymtech/nym/check-runs/5182943473',
|
||||||
|
labels: [ 'macos-latest' ],
|
||||||
|
runner_id: 4,
|
||||||
|
runner_name: 'GitHub Actions 4',
|
||||||
|
runner_group_id: 2,
|
||||||
|
runner_group_name: 'GitHub Actions'
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const jobResults = jobs
|
||||||
|
.map((job) => {
|
||||||
|
const icon = job.conclusion === 'success' ? '🟩' : '🟥';
|
||||||
|
|
||||||
|
// each job is converted into formatted markdown text
|
||||||
|
return `${icon} ${job.conclusion}: ${job.name} - ${job.html_url}`;
|
||||||
|
})
|
||||||
|
// and join with newlines for display in the template
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
return template({ ...context, jobResults });
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addToContextAndValidate,
|
||||||
|
getMessageBody,
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||||
|
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||||
|
> 🔴 **FAILURE** :cry:
|
||||||
|
> `when` {{ timestamp }}
|
||||||
|
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||||
|
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||||
|
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||||
|
|
||||||
|
{{ jobResults }}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||||
|
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||||
|
> ✅ **SUCCESS**
|
||||||
|
> `when` {{ timestamp }}
|
||||||
|
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||||
|
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||||
|
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||||
|
|
||||||
|
{{ jobResults }}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
|
||||||
|
const Bot = require('keybase-bot');
|
||||||
|
|
||||||
|
let context = {
|
||||||
|
kinds: ['ts-packages', 'network-explorer', 'nightly'],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that all required env and context vars are available
|
||||||
|
*/
|
||||||
|
function validateContext() {
|
||||||
|
if (!context.env.NYM_NOTIFICATION_KIND) {
|
||||||
|
throw new Error(
|
||||||
|
'Please set env var NYM_NOTIFICATION_KIND with the project kind that matches a directory in ".github/workflows/support-files"',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!context.kinds.includes(context.env.NYM_NOTIFICATION_KIND)) {
|
||||||
|
throw new Error(`Env var NYM_NOTIFICATION_KIND is not in ${context.kinds}`);
|
||||||
|
}
|
||||||
|
if (!context.env.NYM_PROJECT_NAME) {
|
||||||
|
throw new Error(
|
||||||
|
'Please set env var NYM_PROJECT_NAME with the project name for displaying in notification messages',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!context.env.KEYBASE_NYM_CHANNEL) {
|
||||||
|
throw new Error(
|
||||||
|
'Please set env var KEYBASE_NYM_CHANNEL with the channel name for the notification message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!context.env.KEYBASE_NYMBOT_USERNAME) {
|
||||||
|
throw new Error(
|
||||||
|
'Username is not defined. Please set env var KEYBASE_NYMBOT_USERNAME',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!context.env.KEYBASE_NYMBOT_PAPERKEY) {
|
||||||
|
throw new Error(
|
||||||
|
'Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a context that will be available in the templates for rendering notifications
|
||||||
|
*/
|
||||||
|
function createTemplateContext() {
|
||||||
|
const options = { dateStyle: 'full', timeStyle: 'long' };
|
||||||
|
context.timestamp = new Date().toLocaleString(undefined, options);
|
||||||
|
|
||||||
|
// add environment to template context and validate
|
||||||
|
context.env = process.env;
|
||||||
|
try {
|
||||||
|
validateContext();
|
||||||
|
} catch (e) {
|
||||||
|
if(process.env.SHOW_DEBUG) {
|
||||||
|
// recursively print the context for easy debugging and rethrow the error
|
||||||
|
console.dir({ context }, { depth: null });
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.kind = context.env.NYM_NOTIFICATION_KIND;
|
||||||
|
|
||||||
|
context.keybase = {
|
||||||
|
channel: context.env.KEYBASE_NYM_CHANNEL,
|
||||||
|
username: context.env.KEYBASE_NYMBOT_USERNAME,
|
||||||
|
paperkey: context.env.KEYBASE_NYMBOT_PAPERKEY,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!context.env.GIT_BRANCH_NAME) {
|
||||||
|
context.env.GIT_BRANCH_NAME = context.env.GITHUB_REF.split('/')
|
||||||
|
.slice(2)
|
||||||
|
.join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
context.status = process.env.IS_SUCCESS === 'true' ? 'success' : 'failure';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendKeybaseMessage(messageBody) {
|
||||||
|
const bot = new Bot();
|
||||||
|
try {
|
||||||
|
console.log(
|
||||||
|
`Initialising keybase with user "${
|
||||||
|
context.keybase.username
|
||||||
|
}" and key: "${'*'.repeat(context.keybase.paperkey.length)}"...`,
|
||||||
|
);
|
||||||
|
await bot.init(context.keybase.username, context.keybase.paperkey, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: 'nymtech_bot',
|
||||||
|
membersType: 'team',
|
||||||
|
topicName: context.keybase.channel,
|
||||||
|
topic_type: 'CHAT',
|
||||||
|
};
|
||||||
|
const message = {
|
||||||
|
body: messageBody,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(`Sending to ${channel.name}#${channel.topicName}...`);
|
||||||
|
await bot.chat.send(channel, message);
|
||||||
|
|
||||||
|
console.log('Message sent!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
process.exitCode = -1;
|
||||||
|
} finally {
|
||||||
|
await bot.deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the `kind` set in the context to process the context and generate a notification message
|
||||||
|
* @returns {Promise<string>} A string notification message body
|
||||||
|
*/
|
||||||
|
async function processKindScript() {
|
||||||
|
const script = require(`../${context.kind}`);
|
||||||
|
if (!script.addToContextAndValidate) {
|
||||||
|
throw new Error(
|
||||||
|
`"./${context.kind}/index.js" does not export a method called "async addToContextAndValidate(context)"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!script.getMessageBody) {
|
||||||
|
throw new Error(
|
||||||
|
`"./${context.kind}/index.js" does not export a method called "async getMessageBody(context)"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the script to modify and validate the context
|
||||||
|
await script.addToContextAndValidate(context);
|
||||||
|
|
||||||
|
// let the script create a message body and return the result as a string for sending
|
||||||
|
return await script.getMessageBody(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main function, as async so that await syntax is available
|
||||||
|
*/
|
||||||
|
async function main() {
|
||||||
|
createTemplateContext();
|
||||||
|
console.log(`Sending notification for kind "${context.kind}"...`);
|
||||||
|
const messageBody = await processKindScript();
|
||||||
|
if(process.env.SHOW_DEBUG) {
|
||||||
|
console.log('-----------------------------------------');
|
||||||
|
console.log(messageBody);
|
||||||
|
console.log('-----------------------------------------');
|
||||||
|
}
|
||||||
|
await sendKeybaseMessage(messageBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
// call main function and let NodeJS handle the promise
|
||||||
|
main();
|
||||||
@@ -4,11 +4,14 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier --write send_message.js"
|
"dev": "node dev.js",
|
||||||
|
"format": "prettier --write **/*.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dotenv": "^16.0.0",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
"keybase-bot": "^3.6.1"
|
"keybase-bot": "^3.6.1",
|
||||||
|
"octokit": "^1.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "2.3.2"
|
"prettier": "2.3.2"
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
const Handlebars = require('handlebars');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
async function addToContextAndValidate(context) {
|
||||||
|
if (!context.env.NYM_CI_WWW_LOCATION) {
|
||||||
|
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
|
||||||
|
}
|
||||||
|
if (!context.env.NYM_CI_WWW_BASE) {
|
||||||
|
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMessageBody(context) {
|
||||||
|
const source = fs
|
||||||
|
.readFileSync(
|
||||||
|
context.env.IS_SUCCESS === 'true'
|
||||||
|
? path.resolve(__dirname, 'templates', 'success')
|
||||||
|
: path.resolve(__dirname, 'templates', 'failure'),
|
||||||
|
)
|
||||||
|
.toString();
|
||||||
|
const template = Handlebars.compile(source);
|
||||||
|
return template(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addToContextAndValidate,
|
||||||
|
getMessageBody,
|
||||||
|
};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||||
|
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||||
|
> 🔴 **FAILURE** :cry:
|
||||||
|
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||||
|
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||||
|
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||||
|
|
||||||
|
Commit message:
|
||||||
|
```
|
||||||
|
{{ env.GIT_COMMIT_MESSAGE }}
|
||||||
|
```
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||||
|
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||||
|
> ✅ **SUCCESS**
|
||||||
|
|
||||||
|
> ➡️➡️➡️➡️➡️ **View output:**
|
||||||
|
> `storybook`: https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}
|
||||||
|
> `example`: https://{{ env.NYM_CI_WWW_LOCATION }}-example.{{ env.NYM_CI_WWW_BASE }}
|
||||||
|
|
||||||
|
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||||
|
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||||
|
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||||
|
|
||||||
|
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
|
||||||
|
```
|
||||||
|
{{ env.GIT_COMMIT_MESSAGE }}
|
||||||
|
```
|
||||||
@@ -19,30 +19,27 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|
||||||
# token credentials (non-coconut) don't work for wasm right now
|
- uses: actions-rs/cargo@v1
|
||||||
# - uses: actions-rs/cargo@v1
|
with:
|
||||||
# with:
|
command: build
|
||||||
# command: build
|
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --features=coconut
|
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --features=coconut
|
||||||
|
|
||||||
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
|
- uses: actions-rs/cargo@v1
|
||||||
# - uses: actions-rs/cargo@v1
|
with:
|
||||||
# with:
|
command: test
|
||||||
# command: test
|
args: --manifest-path clients/webassembly/Cargo.toml
|
||||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: fmt
|
command: fmt
|
||||||
args: --manifest-path clients/webassembly/Cargo.toml -- --check
|
args: --manifest-path clients/webassembly/Cargo.toml -- --check
|
||||||
|
|
||||||
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
|
- uses: actions-rs/cargo@v1
|
||||||
# - uses: actions-rs/cargo@v1
|
with:
|
||||||
# with:
|
command: clippy
|
||||||
# command: clippy
|
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
|
||||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
|
|
||||||
|
|||||||
@@ -35,4 +35,6 @@ contracts/mixnet/Justfile
|
|||||||
contracts/mixnet/Makefile
|
contracts/mixnet/Makefile
|
||||||
validator-config
|
validator-config
|
||||||
*.patch
|
*.patch
|
||||||
validator-api-config.toml
|
validator-api-config.toml
|
||||||
|
dist
|
||||||
|
storybook-static
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainnet":[{
|
||||||
|
"nymd_url":"https://rpc.nyx.nodes.guru/",
|
||||||
|
"api_url":"https://api.nyx.nodes.guru/"
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -11,13 +11,13 @@ panic = "abort"
|
|||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"clients/client-core",
|
"clients/client-core",
|
||||||
"clients/native",
|
"clients/native",
|
||||||
"clients/native/websocket-requests",
|
"clients/native/websocket-requests",
|
||||||
"clients/socks5",
|
"clients/socks5",
|
||||||
"clients/tauri-client/src-tauri",
|
# "clients/tauri-client/src-tauri",
|
||||||
"clients/webassembly",
|
|
||||||
"common/client-libs/gateway-client",
|
"common/client-libs/gateway-client",
|
||||||
"common/client-libs/mixnet-client",
|
"common/client-libs/mixnet-client",
|
||||||
"common/client-libs/validator-client",
|
"common/client-libs/validator-client",
|
||||||
@@ -26,7 +26,9 @@ members = [
|
|||||||
"common/credentials",
|
"common/credentials",
|
||||||
"common/crypto",
|
"common/crypto",
|
||||||
"common/bandwidth-claim-contract",
|
"common/bandwidth-claim-contract",
|
||||||
"common/mixnet-contract",
|
"common/cosmwasm-smart-contracts/contracts-common",
|
||||||
|
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||||
|
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||||
"common/mixnode-common",
|
"common/mixnode-common",
|
||||||
"common/network-defaults",
|
"common/network-defaults",
|
||||||
"common/nonexhaustive-delayqueue",
|
"common/nonexhaustive-delayqueue",
|
||||||
@@ -52,12 +54,12 @@ members = [
|
|||||||
"mixnode",
|
"mixnode",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"validator-api",
|
"validator-api",
|
||||||
|
"validator-api/validator-api-requests",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
"clients/native",
|
"clients/native",
|
||||||
"clients/socks5",
|
"clients/socks5",
|
||||||
# "clients/webassembly",
|
|
||||||
"gateway",
|
"gateway",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"mixnode",
|
"mixnode",
|
||||||
@@ -65,4 +67,4 @@ default-members = [
|
|||||||
"explorer-api",
|
"explorer-api",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = ["explorer", "contracts", "tokenomics-py"]
|
exclude = ["explorer", "contracts", "tokenomics-py", "clients/webassembly"]
|
||||||
|
|||||||
@@ -1,25 +1,47 @@
|
|||||||
all: clippy test fmt
|
test: build clippy-all cargo-test wasm fmt
|
||||||
clippy: clippy-main clippy-contracts clippy-wallet
|
no-clippy: build cargo-test wasm fmt
|
||||||
test: test-main test-contracts test-wallet
|
happy: fmt clippy-happy test
|
||||||
|
clippy-all: clippy-all-main clippy-all-contracts clippy-all-wallet
|
||||||
|
clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet
|
||||||
|
cargo-test: test-main test-contracts test-wallet
|
||||||
|
build: build-contracts build-wallet build-main
|
||||||
fmt: fmt-main fmt-contracts fmt-wallet
|
fmt: fmt-main fmt-contracts fmt-wallet
|
||||||
|
|
||||||
clippy-main:
|
clippy-happy-main:
|
||||||
cargo clippy
|
cargo clippy
|
||||||
|
|
||||||
clippy-contracts:
|
clippy-happy-contracts:
|
||||||
cargo clippy --manifest-path contracts/Cargo.toml
|
cargo clippy --manifest-path contracts/Cargo.toml --target wasm32-unknown-unknown
|
||||||
|
|
||||||
clippy-wallet:
|
clippy-happy-wallet:
|
||||||
cargo clippy --manifest-path nym-wallet/Cargo.toml
|
cargo clippy --manifest-path nym-wallet/Cargo.toml
|
||||||
|
|
||||||
|
clippy-all-main:
|
||||||
|
cargo clippy --workspace --all-features -- -D warnings
|
||||||
|
|
||||||
|
clippy-all-contracts:
|
||||||
|
cargo clippy --workspace --manifest-path contracts/Cargo.toml --all-features --target wasm32-unknown-unknown -- -D warnings
|
||||||
|
|
||||||
|
clippy-all-wallet:
|
||||||
|
cargo clippy --workspace --manifest-path nym-wallet/Cargo.toml --all-features -- -D warnings
|
||||||
|
|
||||||
test-main:
|
test-main:
|
||||||
cargo test
|
cargo test --all-features --workspace
|
||||||
|
|
||||||
test-contracts:
|
test-contracts:
|
||||||
cargo test --manifest-path contracts/Cargo.toml
|
cargo test --manifest-path contracts/Cargo.toml --all-features
|
||||||
|
|
||||||
test-wallet:
|
test-wallet:
|
||||||
cargo test --manifest-path nym-wallet/Cargo.toml
|
cargo test --manifest-path nym-wallet/Cargo.toml --all-features
|
||||||
|
|
||||||
|
build-main:
|
||||||
|
cargo build --workspace
|
||||||
|
|
||||||
|
build-contracts:
|
||||||
|
cargo build --manifest-path contracts/Cargo.toml --workspace
|
||||||
|
|
||||||
|
build-wallet:
|
||||||
|
cargo build --manifest-path nym-wallet/Cargo.toml --workspace
|
||||||
|
|
||||||
fmt-main:
|
fmt-main:
|
||||||
cargo fmt --all
|
cargo fmt --all
|
||||||
@@ -29,3 +51,6 @@ fmt-contracts:
|
|||||||
|
|
||||||
fmt-wallet:
|
fmt-wallet:
|
||||||
cargo fmt --manifest-path nym-wallet/Cargo.toml --all
|
cargo fmt --manifest-path nym-wallet/Cargo.toml --all
|
||||||
|
|
||||||
|
wasm:
|
||||||
|
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
|
||||||
|
|||||||
@@ -21,12 +21,15 @@ 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/0.11.0/overview/index/).
|
Platform build instructions are available on [our docs site](https://nymtech.net/docs/stable/run-nym-nodes/build-nym).
|
||||||
|
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/stable/nym-apps/wallet#for-developers).
|
||||||
|
|
||||||
### Developing
|
### Developing
|
||||||
|
|
||||||
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
|
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
|
||||||
|
|
||||||
|
For Typescript components, please see [ts-packages](./ts-packages).
|
||||||
|
|
||||||
### Developer chat
|
### Developer chat
|
||||||
|
|
||||||
You can chat to us in [Keybase](https://keybase.io). Download their chat app, then click **Teams -> Join a team**. Type **nymtech.friends** into the team name and hit **continue**. For general chat, hang out in the **#general** channel. Our development takes places in the **#dev** channel. Node operators should be in the **#node-operators** channel.
|
You can chat to us in [Keybase](https://keybase.io). Download their chat app, then click **Teams -> Join a team**. Type **nymtech.friends** into the team name and hit **continue**. For general chat, hang out in the **#general** channel. Our development takes places in the **#dev** channel. Node operators should be in the **#node-operators** channel.
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Shared assets
|
||||||
|
|
||||||
|
This directory contains asset files shared by many projects in this repo.
|
||||||
|
|
||||||
|
You will find:
|
||||||
|
|
||||||
|
- favicons
|
||||||
|
- logos
|
||||||
|
- shared fonts
|
||||||
|
- shared icon SVGs
|
||||||
|
|
||||||
|
See [ts-packages/react-webpack-with-theme-example](../ts-packages/react-webpack-with-theme-example) for examples of usage.
|
||||||
|
After Width: | Height: | Size: 545 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<svg width="64" height="64" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M40 78.5C61.263 78.5 78.5 61.263 78.5 40C78.5 18.737 61.263 1.5 40 1.5C18.737 1.5 1.5 18.737 1.5 40C1.5 61.263 18.737 78.5 40 78.5Z" fill="#070B15" stroke="url(#paint0_linear_0_1)" stroke-width="3"/>
|
||||||
|
<path d="M31.4894 27.56L41.8623 56H48.5106H56V24H48.5106V52.4L38.1777 24H31.4894H24V56H31.4894V27.56Z" fill="white"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_0_1" x1="0.839161" y1="80" x2="80" y2="80" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.09375" stop-color="#FB6E4E"/>
|
||||||
|
<stop offset="1" stop-color="#F51473"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 672 B |
@@ -0,0 +1,6 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
src: url('./OpenSans-VariableFont_wdth,wght.ttf') format('truetype-variations'),
|
||||||
|
url('./OpenSans-Italic-VariableFont_wdth,wght.ttf') format('truetype-variations');
|
||||||
|
font-weight: 100 1000;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<svg width="64" height="64" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M40 78.5C61.263 78.5 78.5 61.263 78.5 40C78.5 18.737 61.263 1.5 40 1.5C18.737 1.5 1.5 18.737 1.5 40C1.5 61.263 18.737 78.5 40 78.5Z" fill="#070B15" stroke="url(#paint0_linear_0_1)" stroke-width="3"/>
|
||||||
|
<path d="M31.4894 27.56L41.8623 56H48.5106H56V24H48.5106V52.4L38.1777 24H31.4894H24V56H31.4894V27.56Z" fill="white"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_0_1" x1="0.839161" y1="80" x2="80" y2="80" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.09375" stop-color="#FB6E4E"/>
|
||||||
|
<stop offset="1" stop-color="#F51473"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 714 B |
@@ -0,0 +1,13 @@
|
|||||||
|
<svg width="300" height="300" viewBox="0 0 296 296" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M148 296C229.738 296 296 229.738 296 148C296 66.2619 229.738 0 148 0C66.2619 0 0 66.2619 0 148C0 229.738 66.2619 296 148 296Z" fill="url(#paint0_linear_113_1244)"/>
|
||||||
|
<path d="M148 285.875C224.147 285.875 285.875 224.146 285.875 148C285.875 71.8536 224.147 10.1248 148 10.1248C71.8538 10.1248 10.125 71.8536 10.125 148C10.125 224.146 71.8538 285.875 148 285.875Z" fill="#121725"/>
|
||||||
|
<path d="M88.8829 120.143H88.7169V120.281V168.637L68.3289 120.226L68.3012 120.143H68.1905H56.6272H43.653H43.5146V120.281V175.719V175.857H43.653H56.6272H56.7655V175.719V127.28L77.2365 175.774L77.2642 175.857H77.3748H88.8829H101.829H101.968V175.719V120.281V120.143H101.829H88.8829Z" fill="white"/>
|
||||||
|
<path d="M252.347 120.143H227.616H227.477L227.45 120.253L214.78 168.858L202.082 120.253L202.054 120.143H201.944H177.157H176.991V120.281V175.719V175.857H177.157H190.104H190.242V175.719V127.667L202.774 175.747L202.801 175.857H202.94H226.564H226.675L226.703 175.747L239.234 127.667V175.719V175.857H239.373H252.347H252.485V175.719V120.281V120.143H252.347Z" fill="white"/>
|
||||||
|
<path d="M155.663 120.143H155.58L155.552 120.198L139.812 147.557L123.988 120.198L123.96 120.143H123.877H108.911H108.635L108.773 120.364L133.145 162.579V175.719V175.857H133.283H146.257H146.396V175.719V162.579L170.767 120.364L170.905 120.143H170.629H155.663Z" fill="white"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_113_1244" x1="0" y1="148" x2="296" y2="148" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.09375" stop-color="#FB6E4E"/>
|
||||||
|
<stop offset="1" stop-color="#FC1D60"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="210" height="56" viewBox="0 0 210 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M45.8829 0.142822H45.7169V0.28114V48.637L25.3289 0.225818L25.3012 0.142822H25.1905H13.6272H0.652966H0.514648V0.28114V55.7189V55.8572H0.652966H13.6272H13.7655V55.7189V7.28002L34.2365 55.7742L34.2642 55.8572H34.3748H45.8829H58.8294H58.9677V55.7189V0.28114V0.142822H58.8294H45.8829Z"/>
|
||||||
|
<path d="M209.347 0.142822H184.616H184.477L184.45 0.253483L171.78 48.8583L159.082 0.253483L159.054 0.142822H158.944H134.157H133.991V0.28114V55.7189V55.8572H134.157H147.104H147.242V55.7189V7.66731L159.774 55.7466L159.801 55.8572H159.94H183.564H183.675L183.703 55.7466L196.234 7.66731V55.7189V55.8572H196.373H209.347H209.485V55.7189V0.28114V0.142822H209.347Z"/>
|
||||||
|
<path d="M112.663 0.142822H112.58L112.552 0.198153L96.8116 27.5574L80.988 0.198153L80.9604 0.142822H80.8774H65.9114H65.6348L65.7731 0.364136L90.1447 42.5787V55.7189V55.8572H90.283H103.257H103.396V55.7189V42.5787L127.767 0.364136L127.905 0.142822H127.629H112.663Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M170.7 29.3001C131.7 -9.7999 68.3001 -9.7999 29.3001 29.3001C-9.7999 68.4001 -9.7999 131.7 29.3001 170.7C68.4001 209.8 131.7 209.8 170.7 170.7C209.8 131.7 209.8 68.3001 170.7 29.3001ZM162.1 162.1C127.8 196.4 72.1001 196.4 37.8001 162.1C3.5001 127.8 3.5001 72.1001 37.8001 37.8001C72.1001 3.5001 127.8 3.5001 162.1 37.8001C196.5 72.2001 196.5 127.8 162.1 162.1Z" fill="white"/>
|
||||||
|
<path d="M162.1 37.9C127.8 3.60005 72.1002 3.60005 37.8002 37.9C3.50019 72.2 3.50019 127.9 37.8002 162.2C72.1002 196.5 127.8 196.5 162.1 162.2C196.5 127.8 196.5 72.2 162.1 37.9ZM63.0002 170.7C56.8002 167.4 51.1002 163.2 46.1002 158.4V41.7C51.3002 36.7 57.2002 32.5 63.6002 29.1L137 140.9V29.3C143.2 32.6 148.9 36.8 153.9 41.6V158.3C148.7 163.3 142.8 167.5 136.4 170.9L63.0002 59.1V170.7Z" fill="#070B15"/>
|
||||||
|
<path d="M154 158.3V41.7C148.9 36.9 143.2 32.7 137.1 29.4V140.9L63.5 29C57.1 32.4 51.2 36.6 46 41.6V158.3C51.1 163.1 56.8 167.3 62.9 170.6V59.1L136.5 171C142.9 167.6 148.8 163.3 154 158.3Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M170.7 29.3001C131.7 -9.7999 68.3001 -9.7999 29.3001 29.3001C-9.7999 68.4001 -9.7999 131.7 29.3001 170.7C68.4001 209.8 131.7 209.8 170.7 170.7C209.8 131.7 209.8 68.3001 170.7 29.3001ZM162.1 162.1C127.8 196.4 72.1001 196.4 37.8001 162.1C3.5001 127.8 3.5001 72.1001 37.8001 37.8001C72.1001 3.5001 127.8 3.5001 162.1 37.8001C196.5 72.2001 196.5 127.8 162.1 162.1Z" fill="#141521"/>
|
||||||
|
<path d="M162.1 37.9C127.8 3.60005 72.1002 3.60005 37.8002 37.9C3.50019 72.2 3.50019 127.9 37.8002 162.2C72.1002 196.5 127.8 196.5 162.1 162.2C196.5 127.8 196.5 72.2 162.1 37.9ZM63.0002 170.7C56.8002 167.4 51.1002 163.2 46.1002 158.4V41.7C51.3002 36.7 57.2002 32.5 63.6002 29.1L137 140.9V29.3C143.2 32.6 148.9 36.8 153.9 41.6V158.3C148.7 163.3 142.8 167.5 136.4 170.9L63.0002 59.1V170.7Z" fill="white"/>
|
||||||
|
<path d="M154 158.3V41.7C148.9 36.9 143.2 32.7 137.1 29.4V140.9L63.5 29C57.1 32.4 51.2 36.6 46 41.6V158.3C51.1 163.1 56.8 167.3 62.9 170.6V59.1L136.5 171C142.9 167.6 148.8 163.3 154 158.3Z" fill="#141521"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "client-core"
|
name = "client-core"
|
||||||
version = "0.12.0"
|
version = "1.0.0-rc.1"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use nymsphinx::utils::sample_poisson_duration;
|
|||||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tokio::time;
|
use tokio::time;
|
||||||
|
|
||||||
@@ -165,8 +164,8 @@ impl LoopCoverTrafficStream<OsRng> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
pub fn start(mut self) -> JoinHandle<()> {
|
||||||
handle.spawn(async move {
|
tokio::spawn(async move {
|
||||||
self.run().await;
|
self.run().await;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ impl KeyManager {
|
|||||||
))?;
|
))?;
|
||||||
|
|
||||||
let gateway_shared_key: SharedKeys =
|
let gateway_shared_key: SharedKeys =
|
||||||
pemstore::load_key(&client_pathfinder.gateway_shared_key().to_owned())?;
|
pemstore::load_key(client_pathfinder.gateway_shared_key())?;
|
||||||
|
|
||||||
let ack_key: AckKey = pemstore::load_key(&client_pathfinder.ack_key().to_owned())?;
|
let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?;
|
||||||
|
|
||||||
// TODO: ack key is never stored so it is generated now. But perhaps it should be stored
|
// TODO: ack key is never stored so it is generated now. But perhaps it should be stored
|
||||||
// after all for consistency sake?
|
// after all for consistency sake?
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use futures::StreamExt;
|
|||||||
use gateway_client::GatewayClient;
|
use gateway_client::GatewayClient;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nymsphinx::forwarding::packet::MixPacket;
|
use nymsphinx::forwarding::packet::MixPacket;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
pub type BatchMixMessageSender = mpsc::UnboundedSender<Vec<MixPacket>>;
|
pub type BatchMixMessageSender = mpsc::UnboundedSender<Vec<MixPacket>>;
|
||||||
@@ -72,8 +71,8 @@ impl MixTrafficController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
pub fn start(mut self) -> JoinHandle<()> {
|
||||||
handle.spawn(async move {
|
tokio::spawn(async move {
|
||||||
self.run().await;
|
self.run().await;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ use nymsphinx::addressing::clients::Recipient;
|
|||||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
mod acknowledgement_control;
|
mod acknowledgement_control;
|
||||||
@@ -170,10 +169,8 @@ impl RealMessagesController<OsRng> {
|
|||||||
self.ack_control = Some(ack_control_fut.await.unwrap());
|
self.ack_control = Some(ack_control_fut.await.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// &Handle is only passed for consistency sake with other client modules, but I think
|
pub fn start(mut self) -> JoinHandle<Self> {
|
||||||
// when we get to refactoring, we should apply gateway approach and make it implicit
|
tokio::spawn(async move {
|
||||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<Self> {
|
|
||||||
handle.spawn(async move {
|
|
||||||
self.run().await;
|
self.run().await;
|
||||||
self
|
self
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorith
|
|||||||
use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
// Buffer Requests to say "hey, send any reconstructed messages to this channel"
|
// Buffer Requests to say "hey, send any reconstructed messages to this channel"
|
||||||
@@ -291,8 +290,8 @@ impl RequestReceiver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
fn start(mut self) -> JoinHandle<()> {
|
||||||
handle.spawn(async move {
|
tokio::spawn(async move {
|
||||||
while let Some(request) = self.query_receiver.next().await {
|
while let Some(request) = self.query_receiver.next().await {
|
||||||
match request {
|
match request {
|
||||||
ReceivedBufferMessage::ReceiverAnnounce(sender) => {
|
ReceivedBufferMessage::ReceiverAnnounce(sender) => {
|
||||||
@@ -322,8 +321,8 @@ impl FragmentedMessageReceiver {
|
|||||||
mixnet_packet_receiver,
|
mixnet_packet_receiver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
fn start(mut self) -> JoinHandle<()> {
|
||||||
handle.spawn(async move {
|
tokio::spawn(async move {
|
||||||
while let Some(new_messages) = self.mixnet_packet_receiver.next().await {
|
while let Some(new_messages) = self.mixnet_packet_receiver.next().await {
|
||||||
self.received_buffer.handle_new_received(new_messages).await;
|
self.received_buffer.handle_new_received(new_messages).await;
|
||||||
}
|
}
|
||||||
@@ -355,9 +354,9 @@ impl ReceivedMessagesBufferController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self, handle: &Handle) {
|
pub fn start(self) {
|
||||||
// TODO: should we do anything with JoinHandle(s) returned by start methods?
|
// TODO: should we do anything with JoinHandle(s) returned by start methods?
|
||||||
self.fragmented_message_receiver.start(handle);
|
self.fragmented_message_receiver.start();
|
||||||
self.request_receiver.start(handle);
|
self.request_receiver.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crypto::generic_array::typenum::Unsigned;
|
||||||
use log::*;
|
use log::*;
|
||||||
use nymsphinx::anonymous_replies::{
|
use nymsphinx::anonymous_replies::{
|
||||||
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SurbEncryptionKey,
|
encryption_key::EncryptionKeyDigest, SurbEncryptionKey, SurbEncryptionKeySize,
|
||||||
SurbEncryptionKeySize,
|
|
||||||
};
|
};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ impl ReplyKeyStorage {
|
|||||||
// if this fails it means we have some database corruption and we
|
// if this fails it means we have some database corruption and we
|
||||||
// absolutely can't continue
|
// absolutely can't continue
|
||||||
|
|
||||||
if key_bytes_ref.len() != SurbEncryptionKeySize::to_usize() {
|
if key_bytes_ref.len() != SurbEncryptionKeySize::USIZE {
|
||||||
error!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
error!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
||||||
panic!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
panic!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ impl ReplyKeyStorage {
|
|||||||
) -> Result<(), ReplyKeyStorageError> {
|
) -> Result<(), ReplyKeyStorageError> {
|
||||||
let digest = encryption_key.compute_digest();
|
let digest = encryption_key.compute_digest();
|
||||||
|
|
||||||
let insertion_result = match self.db.insert(digest.to_vec(), encryption_key.to_bytes()) {
|
let insertion_result = match self.db.insert(digest, encryption_key.to_bytes()) {
|
||||||
Err(e) => Err(ReplyKeyStorageError::DbWriteError(e)),
|
Err(e) => Err(ReplyKeyStorageError::DbWriteError(e)),
|
||||||
Ok(existing_key) => {
|
Ok(existing_key) => {
|
||||||
if existing_key.is_some() {
|
if existing_key.is_some() {
|
||||||
@@ -79,7 +79,7 @@ impl ReplyKeyStorage {
|
|||||||
&self,
|
&self,
|
||||||
key_digest: EncryptionKeyDigest,
|
key_digest: EncryptionKeyDigest,
|
||||||
) -> Result<Option<SurbEncryptionKey>, ReplyKeyStorageError> {
|
) -> Result<Option<SurbEncryptionKey>, ReplyKeyStorageError> {
|
||||||
let removal_result = match self.db.remove(&key_digest.to_vec()) {
|
let removal_result = match self.db.remove(key_digest) {
|
||||||
Err(e) => Err(ReplyKeyStorageError::DbReadError(e)),
|
Err(e) => Err(ReplyKeyStorageError::DbReadError(e)),
|
||||||
Ok(existing_key) => {
|
Ok(existing_key) => {
|
||||||
Ok(existing_key.map(|existing_key| self.read_encryption_key(existing_key)))
|
Ok(existing_key.map(|existing_key| self.read_encryption_key(existing_key)))
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use std::ops::Deref;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time;
|
use std::time;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use topology::{nym_topology_from_bonds, NymTopology};
|
use topology::{nym_topology_from_bonds, NymTopology};
|
||||||
@@ -304,8 +303,8 @@ impl TopologyRefresher {
|
|||||||
self.topology_accessor.is_routable().await
|
self.topology_accessor.is_routable().await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
pub fn start(mut self) -> JoinHandle<()> {
|
||||||
handle.spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
tokio::time::sleep(self.refresh_rate).await;
|
tokio::time::sleep(self.refresh_rate).await;
|
||||||
self.refresh().await;
|
self.refresh().await;
|
||||||
|
|||||||
@@ -121,12 +121,16 @@ impl<T: NymConfig> Config<T> {
|
|||||||
self.client.testnet_mode = testnet_mode;
|
self.client.testnet_mode = testnet_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) {
|
pub fn with_gateway_endpoint<S: Into<String>>(&mut self, id: S, owner: S, listener: S) {
|
||||||
self.client.gateway_id = id.into();
|
self.client.gateway_endpoint = GatewayEndpoint {
|
||||||
|
gateway_id: id.into(),
|
||||||
|
gateway_owner: owner.into(),
|
||||||
|
gateway_listener: listener.into(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_gateway_listener<S: Into<String>>(&mut self, gateway_listener: S) {
|
pub fn with_gateway_id<S: Into<String>>(&mut self, id: S) {
|
||||||
self.client.gateway_listener = gateway_listener.into();
|
self.client.gateway_endpoint.gateway_id = id.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
@@ -198,11 +202,15 @@ impl<T: NymConfig> Config<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_gateway_id(&self) -> String {
|
pub fn get_gateway_id(&self) -> String {
|
||||||
self.client.gateway_id.clone()
|
self.client.gateway_endpoint.gateway_id.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_gateway_owner(&self) -> String {
|
||||||
|
self.client.gateway_endpoint.gateway_owner.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_gateway_listener(&self) -> String {
|
pub fn get_gateway_listener(&self) -> String {
|
||||||
self.client.gateway_listener.clone()
|
self.client.gateway_endpoint.gateway_listener.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
@@ -272,6 +280,19 @@ impl<T: NymConfig> Default for Config<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||||
|
struct GatewayEndpoint {
|
||||||
|
/// gateway_id specifies ID of the gateway to which the client should send messages.
|
||||||
|
/// If initially omitted, a random gateway will be chosen from the available topology.
|
||||||
|
gateway_id: String,
|
||||||
|
|
||||||
|
/// Address of the gateway owner to which the client should send messages.
|
||||||
|
gateway_owner: String,
|
||||||
|
|
||||||
|
/// Address of the gateway listener to which all client requests should be sent.
|
||||||
|
gateway_listener: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct Client<T> {
|
pub struct Client<T> {
|
||||||
/// Version of the client for which this configuration was created.
|
/// Version of the client for which this configuration was created.
|
||||||
@@ -313,12 +334,8 @@ pub struct Client<T> {
|
|||||||
/// sent but not received back.
|
/// sent but not received back.
|
||||||
reply_encryption_key_store_path: PathBuf,
|
reply_encryption_key_store_path: PathBuf,
|
||||||
|
|
||||||
/// gateway_id specifies ID of the gateway to which the client should send messages.
|
/// Information regarding how the client should send data to gateway.
|
||||||
/// If initially omitted, a random gateway will be chosen from the available topology.
|
gateway_endpoint: GatewayEndpoint,
|
||||||
gateway_id: String,
|
|
||||||
|
|
||||||
/// Address of the gateway listener to which all client requests should be sent.
|
|
||||||
gateway_listener: String,
|
|
||||||
|
|
||||||
/// Path to directory containing public/private keys used for bandwidth token purchase.
|
/// Path to directory containing public/private keys used for bandwidth token purchase.
|
||||||
/// Those are saved in case of emergency, to be able to reclaim bandwidth tokens.
|
/// Those are saved in case of emergency, to be able to reclaim bandwidth tokens.
|
||||||
@@ -357,8 +374,7 @@ impl<T: NymConfig> Default for Client<T> {
|
|||||||
gateway_shared_key_file: Default::default(),
|
gateway_shared_key_file: Default::default(),
|
||||||
ack_key_file: Default::default(),
|
ack_key_file: Default::default(),
|
||||||
reply_encryption_key_store_path: Default::default(),
|
reply_encryption_key_store_path: Default::default(),
|
||||||
gateway_id: "".to_string(),
|
gateway_endpoint: Default::default(),
|
||||||
gateway_listener: "".to_string(),
|
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
backup_bandwidth_token_keys_dir: Default::default(),
|
backup_bandwidth_token_keys_dir: Default::default(),
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "0.12.0"
|
version = "1.0.0-rc.1"
|
||||||
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>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
rust-version = "1.56"
|
rust-version = "1.56"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@@ -48,6 +48,7 @@ network-defaults = { path = "../../common/network-defaults" }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut"]
|
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut"]
|
||||||
|
eth = []
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1.0" # for the "textsend" example
|
serde_json = "1.0" # for the "textsend" example
|
||||||
|
|||||||
@@ -18,14 +18,12 @@
|
|||||||
"author": "Dave Hrycyszyn",
|
"author": "Dave Hrycyszyn",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^10.2.6",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"webpack": "^5.70.0",
|
||||||
"webpack": "^4.42.1",
|
"webpack-cli": "^4.9.2",
|
||||||
"webpack-cli": "^3.3.11",
|
"webpack-dev-server": "^4.7.4"
|
||||||
"webpack-dev-server": "^3.11.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.5",
|
"html-webpack-plugin": "^5.5.0"
|
||||||
"html-webpack-plugin": "^4.2.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const autoprefixer = require('autoprefixer');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
mode: 'production',
|
||||||
entry: './src/index.js',
|
entry: './src/index.js',
|
||||||
output: {
|
output: {
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
@@ -18,7 +18,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
devServer: {
|
devServer: {
|
||||||
contentBase: path.join(__dirname, 'dist'),
|
static: path.join(__dirname, 'dist'),
|
||||||
compress: true,
|
compress: true,
|
||||||
port: 8888
|
port: 8888
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ async fn send_file_with_reply() {
|
|||||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||||
|
|
||||||
let recipient = get_self_address(&mut ws_stream).await;
|
let recipient = get_self_address(&mut ws_stream).await;
|
||||||
println!("our full address is: {}", recipient.to_string());
|
println!("our full address is: {}", recipient);
|
||||||
|
|
||||||
let read_data = std::fs::read("examples/dummy_file").unwrap();
|
let read_data = std::fs::read("examples/dummy_file").unwrap();
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ async fn send_file_without_reply() {
|
|||||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||||
|
|
||||||
let recipient = get_self_address(&mut ws_stream).await;
|
let recipient = get_self_address(&mut ws_stream).await;
|
||||||
println!("our full address is: {}", recipient.to_string());
|
println!("our full address is: {}", recipient);
|
||||||
|
|
||||||
let read_data = std::fs::read("examples/dummy_file").unwrap();
|
let read_data = std::fs::read("examples/dummy_file").unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ async fn send_text_with_reply() {
|
|||||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||||
|
|
||||||
let recipient = get_self_address(&mut ws_stream).await;
|
let recipient = get_self_address(&mut ws_stream).await;
|
||||||
println!("our full address is: {}", recipient.to_string());
|
println!("our full address is: {}", recipient);
|
||||||
|
|
||||||
let send_request = json!({
|
let send_request = json!({
|
||||||
"type" : "send",
|
"type" : "send",
|
||||||
@@ -76,7 +76,7 @@ async fn send_text_without_reply() {
|
|||||||
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
let (mut ws_stream, _) = connect_async(uri).await.unwrap();
|
||||||
|
|
||||||
let recipient = get_self_address(&mut ws_stream).await;
|
let recipient = get_self_address(&mut ws_stream).await;
|
||||||
println!("our full address is: {}", recipient.to_string());
|
println!("our full address is: {}", recipient);
|
||||||
|
|
||||||
let send_request = json!({
|
let send_request = json!({
|
||||||
"type" : "send",
|
"type" : "send",
|
||||||
|
|||||||
@@ -59,12 +59,6 @@ eth_endpoint = '{{ client.eth_endpoint }}'
|
|||||||
|
|
||||||
##### additional client config options #####
|
##### additional client config options #####
|
||||||
|
|
||||||
# ID of the gateway from which the client should be fetching messages.
|
|
||||||
gateway_id = '{{ client.gateway_id }}'
|
|
||||||
|
|
||||||
# Address of the gateway listener to which all client requests should be sent.
|
|
||||||
gateway_listener = '{{ client.gateway_listener }}'
|
|
||||||
|
|
||||||
# A gateway specific, optional, base58 stringified shared key used for
|
# A gateway specific, optional, base58 stringified shared key used for
|
||||||
# communication with particular gateway.
|
# communication with particular gateway.
|
||||||
gateway_shared_key_file = '{{ client.gateway_shared_key_file }}'
|
gateway_shared_key_file = '{{ client.gateway_shared_key_file }}'
|
||||||
@@ -78,6 +72,17 @@ ack_key_file = '{{ client.ack_key_file }}'
|
|||||||
# Absolute path to the home Nym Clients directory.
|
# Absolute path to the home Nym Clients directory.
|
||||||
nym_root_directory = '{{ client.nym_root_directory }}'
|
nym_root_directory = '{{ client.nym_root_directory }}'
|
||||||
|
|
||||||
|
[client.gateway_endpoint]
|
||||||
|
# ID of the gateway from which the client should be fetching messages.
|
||||||
|
gateway_id = '{{ client.gateway_endpoint.gateway_id }}'
|
||||||
|
|
||||||
|
# Address of the gateway owner to which the client should send messages.
|
||||||
|
gateway_owner = '{{ client.gateway_endpoint.gateway_owner }}'
|
||||||
|
|
||||||
|
# Address of the gateway listener to which all client requests should be sent.
|
||||||
|
gateway_listener = '{{ client.gateway_endpoint.gateway_listener }}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### socket config options #####
|
##### socket config options #####
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ use nymsphinx::addressing::clients::Recipient;
|
|||||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||||
use nymsphinx::anonymous_replies::ReplySurb;
|
use nymsphinx::anonymous_replies::ReplySurb;
|
||||||
use nymsphinx::receiver::ReconstructedMessage;
|
use nymsphinx::receiver::ReconstructedMessage;
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
|
|
||||||
use crate::client::config::{Config, SocketType};
|
use crate::client::config::{Config, SocketType};
|
||||||
use crate::websocket;
|
use crate::websocket;
|
||||||
@@ -44,11 +43,6 @@ pub struct NymClient {
|
|||||||
/// key filepaths, etc.
|
/// key filepaths, etc.
|
||||||
config: Config,
|
config: Config,
|
||||||
|
|
||||||
/// Tokio runtime used for futures execution.
|
|
||||||
// TODO: JS: Personally I think I prefer the implicit way of using it that we've done with the
|
|
||||||
// gateway.
|
|
||||||
runtime: Runtime,
|
|
||||||
|
|
||||||
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
||||||
key_manager: KeyManager,
|
key_manager: KeyManager,
|
||||||
|
|
||||||
@@ -68,7 +62,6 @@ impl NymClient {
|
|||||||
let key_manager = KeyManager::load_keys(&pathfinder).expect("failed to load stored keys");
|
let key_manager = KeyManager::load_keys(&pathfinder).expect("failed to load stored keys");
|
||||||
|
|
||||||
NymClient {
|
NymClient {
|
||||||
runtime: Runtime::new().unwrap(),
|
|
||||||
config,
|
config,
|
||||||
key_manager,
|
key_manager,
|
||||||
input_tx: None,
|
input_tx: None,
|
||||||
@@ -94,9 +87,6 @@ impl NymClient {
|
|||||||
mix_tx: BatchMixMessageSender,
|
mix_tx: BatchMixMessageSender,
|
||||||
) {
|
) {
|
||||||
info!("Starting loop cover traffic stream...");
|
info!("Starting loop cover traffic stream...");
|
||||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
|
||||||
// set in the constructor which HAS TO be called within context of a tokio runtime
|
|
||||||
let _guard = self.runtime.enter();
|
|
||||||
|
|
||||||
LoopCoverTrafficStream::new(
|
LoopCoverTrafficStream::new(
|
||||||
self.key_manager.ack_key(),
|
self.key_manager.ack_key(),
|
||||||
@@ -109,7 +99,7 @@ impl NymClient {
|
|||||||
self.as_mix_recipient(),
|
self.as_mix_recipient(),
|
||||||
topology_accessor,
|
topology_accessor,
|
||||||
)
|
)
|
||||||
.start(self.runtime.handle());
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_real_traffic_controller(
|
fn start_real_traffic_controller(
|
||||||
@@ -131,10 +121,6 @@ impl NymClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
info!("Starting real traffic stream...");
|
info!("Starting real traffic stream...");
|
||||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
|
||||||
// set in the constructor [of OutQueueControl] which HAS TO be called within context of a tokio runtime
|
|
||||||
// When refactoring this restriction should definitely be removed.
|
|
||||||
let _guard = self.runtime.enter();
|
|
||||||
|
|
||||||
RealMessagesController::new(
|
RealMessagesController::new(
|
||||||
controller_config,
|
controller_config,
|
||||||
@@ -144,7 +130,7 @@ impl NymClient {
|
|||||||
topology_accessor,
|
topology_accessor,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
)
|
)
|
||||||
.start(self.runtime.handle());
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffer controlling all messages fetched from provider
|
// buffer controlling all messages fetched from provider
|
||||||
@@ -162,10 +148,10 @@ impl NymClient {
|
|||||||
mixnet_receiver,
|
mixnet_receiver,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
)
|
)
|
||||||
.start(self.runtime.handle())
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_gateway_client(
|
async fn start_gateway_client(
|
||||||
&mut self,
|
&mut self,
|
||||||
mixnet_message_sender: MixnetMessageSender,
|
mixnet_message_sender: MixnetMessageSender,
|
||||||
ack_sender: AcknowledgementSender,
|
ack_sender: AcknowledgementSender,
|
||||||
@@ -174,6 +160,10 @@ impl NymClient {
|
|||||||
if gateway_id.is_empty() {
|
if gateway_id.is_empty() {
|
||||||
panic!("The identity of the gateway is unknown - did you run `nym-client` init?")
|
panic!("The identity of the gateway is unknown - did you run `nym-client` init?")
|
||||||
}
|
}
|
||||||
|
let gateway_owner = self.config.get_base().get_gateway_owner();
|
||||||
|
if gateway_owner.is_empty() {
|
||||||
|
panic!("The owner of the gateway is unknown - did you run `nym-client` init?")
|
||||||
|
}
|
||||||
let gateway_address = self.config.get_base().get_gateway_listener();
|
let gateway_address = self.config.get_base().get_gateway_listener();
|
||||||
if gateway_address.is_empty() {
|
if gateway_address.is_empty() {
|
||||||
panic!("The address of the gateway is unknown - did you run `nym-client` init?")
|
panic!("The address of the gateway is unknown - did you run `nym-client` init?")
|
||||||
@@ -182,47 +172,45 @@ impl NymClient {
|
|||||||
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
||||||
.expect("provided gateway id is invalid!");
|
.expect("provided gateway id is invalid!");
|
||||||
|
|
||||||
self.runtime.block_on(async {
|
#[cfg(feature = "coconut")]
|
||||||
#[cfg(feature = "coconut")]
|
let bandwidth_controller = BandwidthController::new(
|
||||||
let bandwidth_controller = BandwidthController::new(
|
self.config.get_base().get_validator_api_endpoints(),
|
||||||
self.config.get_base().get_validator_api_endpoints(),
|
*self.key_manager.identity_keypair().public_key(),
|
||||||
*self.key_manager.identity_keypair().public_key(),
|
);
|
||||||
);
|
#[cfg(not(feature = "coconut"))]
|
||||||
#[cfg(not(feature = "coconut"))]
|
let bandwidth_controller = BandwidthController::new(
|
||||||
let bandwidth_controller = BandwidthController::new(
|
self.config.get_base().get_eth_endpoint(),
|
||||||
self.config.get_base().get_eth_endpoint(),
|
self.config.get_base().get_eth_private_key(),
|
||||||
self.config.get_base().get_eth_private_key(),
|
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
)
|
||||||
)
|
.expect("Could not create bandwidth controller");
|
||||||
.expect("Could not create bandwidth controller");
|
|
||||||
|
|
||||||
let mut gateway_client = GatewayClient::new(
|
let mut gateway_client = GatewayClient::new(
|
||||||
gateway_address,
|
gateway_address,
|
||||||
self.key_manager.identity_keypair(),
|
self.key_manager.identity_keypair(),
|
||||||
gateway_identity,
|
gateway_identity,
|
||||||
Some(self.key_manager.gateway_shared_key()),
|
gateway_owner,
|
||||||
mixnet_message_sender,
|
Some(self.key_manager.gateway_shared_key()),
|
||||||
ack_sender,
|
mixnet_message_sender,
|
||||||
self.config.get_base().get_gateway_response_timeout(),
|
ack_sender,
|
||||||
Some(bandwidth_controller),
|
self.config.get_base().get_gateway_response_timeout(),
|
||||||
);
|
Some(bandwidth_controller),
|
||||||
|
);
|
||||||
|
|
||||||
if self.config.get_base().get_testnet_mode() {
|
if self.config.get_base().get_testnet_mode() {
|
||||||
gateway_client.set_testnet_mode(true)
|
gateway_client.set_testnet_mode(true)
|
||||||
}
|
}
|
||||||
|
gateway_client
|
||||||
|
.authenticate_and_start()
|
||||||
|
.await
|
||||||
|
.expect("could not authenticate and start up the gateway connection");
|
||||||
|
|
||||||
gateway_client
|
gateway_client
|
||||||
.authenticate_and_start()
|
|
||||||
.await
|
|
||||||
.expect("could not authenticate and start up the gateway connection");
|
|
||||||
|
|
||||||
gateway_client
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// future responsible for periodically polling directory server and updating
|
// future responsible for periodically polling directory server and updating
|
||||||
// the current global view of topology
|
// the current global view of topology
|
||||||
fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
async fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||||
self.config.get_base().get_validator_api_endpoints(),
|
self.config.get_base().get_validator_api_endpoints(),
|
||||||
self.config.get_base().get_topology_refresh_rate(),
|
self.config.get_base().get_topology_refresh_rate(),
|
||||||
@@ -233,13 +221,10 @@ impl NymClient {
|
|||||||
// before returning, block entire runtime to refresh the current network view so that any
|
// before returning, block entire runtime to refresh the current network view so that any
|
||||||
// components depending on topology would see a non-empty view
|
// components depending on topology would see a non-empty view
|
||||||
info!("Obtaining initial network topology");
|
info!("Obtaining initial network topology");
|
||||||
self.runtime.block_on(topology_refresher.refresh());
|
topology_refresher.refresh().await;
|
||||||
|
|
||||||
// TODO: a slightly more graceful termination here
|
// TODO: a slightly more graceful termination here
|
||||||
if !self
|
if !topology_refresher.is_topology_routable().await {
|
||||||
.runtime
|
|
||||||
.block_on(topology_refresher.is_topology_routable())
|
|
||||||
{
|
|
||||||
panic!(
|
panic!(
|
||||||
"The current network topology seem to be insufficient to route any packets through\
|
"The current network topology seem to be insufficient to route any packets through\
|
||||||
- check if enough nodes and a gateway are online"
|
- check if enough nodes and a gateway are online"
|
||||||
@@ -247,7 +232,7 @@ impl NymClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
info!("Starting topology refresher...");
|
info!("Starting topology refresher...");
|
||||||
topology_refresher.start(self.runtime.handle());
|
topology_refresher.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// controller for sending sphinx packets to mixnet (either real traffic or cover traffic)
|
// controller for sending sphinx packets to mixnet (either real traffic or cover traffic)
|
||||||
@@ -260,7 +245,7 @@ impl NymClient {
|
|||||||
gateway_client: GatewayClient,
|
gateway_client: GatewayClient,
|
||||||
) {
|
) {
|
||||||
info!("Starting mix traffic controller...");
|
info!("Starting mix traffic controller...");
|
||||||
MixTrafficController::new(mix_rx, gateway_client).start(self.runtime.handle());
|
MixTrafficController::new(mix_rx, gateway_client).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_websocket_listener(
|
fn start_websocket_listener(
|
||||||
@@ -273,8 +258,7 @@ impl NymClient {
|
|||||||
let websocket_handler =
|
let websocket_handler =
|
||||||
websocket::Handler::new(msg_input, buffer_requester, self.as_mix_recipient());
|
websocket::Handler::new(msg_input, buffer_requester, self.as_mix_recipient());
|
||||||
|
|
||||||
websocket::Listener::new(self.config.get_listening_port())
|
websocket::Listener::new(self.config.get_listening_port()).start(websocket_handler);
|
||||||
.start(self.runtime.handle(), websocket_handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EXPERIMENTAL DIRECT RUST API
|
/// EXPERIMENTAL DIRECT RUST API
|
||||||
@@ -321,9 +305,9 @@ impl NymClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
|
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
|
||||||
pub fn run_forever(&mut self) {
|
pub async fn run_forever(&mut self) {
|
||||||
self.start();
|
self.start().await;
|
||||||
if let Err(e) = self.runtime.block_on(tokio::signal::ctrl_c()) {
|
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||||
error!(
|
error!(
|
||||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||||
e
|
e
|
||||||
@@ -335,7 +319,7 @@ impl NymClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self) {
|
pub async fn start(&mut self) {
|
||||||
info!("Starting nym client");
|
info!("Starting nym client");
|
||||||
// channels for inter-component communication
|
// channels for inter-component communication
|
||||||
// TODO: make the channels be internally created by the relevant components
|
// TODO: make the channels be internally created by the relevant components
|
||||||
@@ -367,14 +351,17 @@ impl NymClient {
|
|||||||
|
|
||||||
// the components are started in very specific order. Unless you know what you are doing,
|
// the components are started in very specific order. Unless you know what you are doing,
|
||||||
// do not change that.
|
// do not change that.
|
||||||
self.start_topology_refresher(shared_topology_accessor.clone());
|
self.start_topology_refresher(shared_topology_accessor.clone())
|
||||||
|
.await;
|
||||||
self.start_received_messages_buffer_controller(
|
self.start_received_messages_buffer_controller(
|
||||||
received_buffer_request_receiver,
|
received_buffer_request_receiver,
|
||||||
mixnet_messages_receiver,
|
mixnet_messages_receiver,
|
||||||
reply_key_storage.clone(),
|
reply_key_storage.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let gateway_client = self.start_gateway_client(mixnet_messages_sender, ack_sender);
|
let gateway_client = self
|
||||||
|
.start_gateway_client(mixnet_messages_sender, ack_sender)
|
||||||
|
.await;
|
||||||
|
|
||||||
self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client);
|
self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client);
|
||||||
self.start_real_traffic_controller(
|
self.start_real_traffic_controller(
|
||||||
|
|||||||
@@ -30,7 +30,13 @@ use topology::{filter::VersionFilterable, gateway};
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::client::config::Config;
|
use crate::client::config::Config;
|
||||||
use crate::commands::{override_config, TESTNET_MODE_ARG_NAME};
|
use crate::commands::override_config;
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
use crate::commands::{
|
||||||
|
DEFAULT_ETH_ENDPOINT, DEFAULT_ETH_PRIVATE_KEY, ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME,
|
||||||
|
TESTNET_MODE_ARG_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||||
let app = App::new("init")
|
let app = App::new("init")
|
||||||
@@ -65,24 +71,29 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
|||||||
.long("fastmode")
|
.long("fastmode")
|
||||||
.hidden(true) // this will prevent this flag from being displayed in `--help`
|
.hidden(true) // this will prevent this flag from being displayed in `--help`
|
||||||
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
||||||
)
|
);
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
let app = app
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||||
.long(TESTNET_MODE_ARG_NAME)
|
.long(TESTNET_MODE_ARG_NAME)
|
||||||
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement")
|
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement. If this value is set, --eth_endpoint and --eth_private_key don't need to be set.")
|
||||||
);
|
.conflicts_with_all(&[ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME])
|
||||||
#[cfg(not(feature = "coconut"))]
|
)
|
||||||
let app = app
|
.arg(Arg::with_name(ETH_ENDPOINT_ARG_NAME)
|
||||||
.arg(Arg::with_name("eth_endpoint")
|
.long(ETH_ENDPOINT_ARG_NAME)
|
||||||
.long("eth_endpoint")
|
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.default_value_if(TESTNET_MODE_ARG_NAME, None, DEFAULT_ETH_ENDPOINT)
|
||||||
.required(true))
|
.required(true))
|
||||||
.arg(Arg::with_name("eth_private_key")
|
.arg(Arg::with_name(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.long("eth_private_key")
|
.long(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true));
|
.default_value_if(TESTNET_MODE_ARG_NAME, None, DEFAULT_ETH_PRIVATE_KEY)
|
||||||
|
.required(true)
|
||||||
|
);
|
||||||
|
|
||||||
app
|
app
|
||||||
}
|
}
|
||||||
@@ -125,6 +136,7 @@ async fn register_with_gateway(
|
|||||||
let mut gateway_client = GatewayClient::new_init(
|
let mut gateway_client = GatewayClient::new_init(
|
||||||
gateway.clients_address(),
|
gateway.clients_address(),
|
||||||
gateway.identity_key,
|
gateway.identity_key,
|
||||||
|
gateway.owner.clone(),
|
||||||
our_identity.clone(),
|
our_identity.clone(),
|
||||||
timeout,
|
timeout,
|
||||||
);
|
);
|
||||||
@@ -208,7 +220,7 @@ fn show_address(config: &Config) {
|
|||||||
println!("\nThe address of this client is: {}", client_recipient);
|
println!("\nThe address of this client is: {}", client_recipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(matches: &ArgMatches) {
|
pub async fn execute(matches: ArgMatches<'static>) {
|
||||||
println!("Initialising client...");
|
println!("Initialising client...");
|
||||||
|
|
||||||
let id = matches.value_of("id").unwrap(); // required for now
|
let id = matches.value_of("id").unwrap(); // required for now
|
||||||
@@ -226,7 +238,7 @@ pub fn execute(matches: &ArgMatches) {
|
|||||||
|
|
||||||
// TODO: ideally that should be the last thing that's being done to config.
|
// TODO: ideally that should be the last thing that's being done to config.
|
||||||
// However, we are later further overriding it with gateway id
|
// However, we are later further overriding it with gateway id
|
||||||
config = override_config(config, matches);
|
config = override_config(config, &matches);
|
||||||
if matches.is_present("fastmode") {
|
if matches.is_present("fastmode") {
|
||||||
config.get_base_mut().set_high_default_traffic_volume();
|
config.get_base_mut().set_high_default_traffic_volume();
|
||||||
}
|
}
|
||||||
@@ -239,26 +251,19 @@ pub fn execute(matches: &ArgMatches) {
|
|||||||
|
|
||||||
let chosen_gateway_id = matches.value_of("gateway");
|
let chosen_gateway_id = matches.value_of("gateway");
|
||||||
|
|
||||||
let registration_fut = async {
|
let gateway_details = gateway_details(
|
||||||
let gate_details = gateway_details(
|
config.get_base().get_validator_api_endpoints(),
|
||||||
config.get_base().get_validator_api_endpoints(),
|
chosen_gateway_id,
|
||||||
chosen_gateway_id,
|
)
|
||||||
)
|
.await;
|
||||||
.await;
|
let shared_keys =
|
||||||
config
|
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
|
||||||
.get_base_mut()
|
|
||||||
.with_gateway_id(gate_details.identity_key.to_base58_string());
|
|
||||||
let shared_keys =
|
|
||||||
register_with_gateway(&gate_details, key_manager.identity_keypair()).await;
|
|
||||||
(shared_keys, gate_details.clients_address())
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: is there perhaps a way to make it work without having to spawn entire runtime?
|
config.get_base_mut().with_gateway_endpoint(
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
gateway_details.identity_key.to_base58_string(),
|
||||||
let (shared_keys, gateway_listener) = rt.block_on(registration_fut);
|
gateway_details.owner.clone(),
|
||||||
config
|
gateway_details.clients_address(),
|
||||||
.get_base_mut()
|
);
|
||||||
.with_gateway_listener(gateway_listener);
|
|
||||||
key_manager.insert_gateway_shared_key(shared_keys);
|
key_manager.insert_gateway_shared_key(shared_keys);
|
||||||
|
|
||||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||||
|
|||||||
@@ -6,6 +6,16 @@ use clap::ArgMatches;
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub(crate) const TESTNET_MODE_ARG_NAME: &str = "testnet-mode";
|
pub(crate) const TESTNET_MODE_ARG_NAME: &str = "testnet-mode";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const ETH_ENDPOINT_ARG_NAME: &str = "eth_endpoint";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const ETH_PRIVATE_KEY_ARG_NAME: &str = "eth_private_key";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const DEFAULT_ETH_ENDPOINT: &str =
|
||||||
|
"https://rinkeby.infura.io/v3/00000000000000000000000000000000";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const DEFAULT_ETH_PRIVATE_KEY: &str =
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000001";
|
||||||
|
|
||||||
pub(crate) mod init;
|
pub(crate) mod init;
|
||||||
pub(crate) mod run;
|
pub(crate) mod run;
|
||||||
@@ -22,7 +32,7 @@ fn parse_validators(raw: &str) -> Vec<Url> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
|
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> Config {
|
||||||
if let Some(raw_validators) = matches.value_of("validators") {
|
if let Some(raw_validators) = matches.value_of("validators") {
|
||||||
config
|
config
|
||||||
.get_base_mut()
|
.get_base_mut()
|
||||||
@@ -46,15 +56,23 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
if let Some(eth_endpoint) = matches.value_of("eth_endpoint") {
|
if let Some(eth_endpoint) = matches.value_of(ETH_ENDPOINT_ARG_NAME) {
|
||||||
config.get_base_mut().with_eth_endpoint(eth_endpoint);
|
config.get_base_mut().with_eth_endpoint(eth_endpoint);
|
||||||
|
} else if !cfg!(feature = "eth") {
|
||||||
|
config
|
||||||
|
.get_base_mut()
|
||||||
|
.with_eth_endpoint(DEFAULT_ETH_ENDPOINT);
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
if let Some(eth_private_key) = matches.value_of("eth_private_key") {
|
if let Some(eth_private_key) = matches.value_of(ETH_PRIVATE_KEY_ARG_NAME) {
|
||||||
config.get_base_mut().with_eth_private_key(eth_private_key);
|
config.get_base_mut().with_eth_private_key(eth_private_key);
|
||||||
|
} else if !cfg!(feature = "eth") {
|
||||||
|
config
|
||||||
|
.get_base_mut()
|
||||||
|
.with_eth_private_key(DEFAULT_ETH_PRIVATE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches.is_present(TESTNET_MODE_ARG_NAME) {
|
if !cfg!(feature = "eth") || matches.is_present(TESTNET_MODE_ARG_NAME) {
|
||||||
config.get_base_mut().with_testnet_mode(true)
|
config.get_base_mut().with_testnet_mode(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
|
|
||||||
use crate::client::config::Config;
|
use crate::client::config::Config;
|
||||||
use crate::client::NymClient;
|
use crate::client::NymClient;
|
||||||
use crate::commands::{override_config, TESTNET_MODE_ARG_NAME};
|
use crate::commands::override_config;
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
use crate::commands::{ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME, TESTNET_MODE_ARG_NAME};
|
||||||
use clap::{App, Arg, ArgMatches};
|
use clap::{App, Arg, ArgMatches};
|
||||||
use config::NymConfig;
|
use config::NymConfig;
|
||||||
use log::*;
|
use log::*;
|
||||||
@@ -38,21 +41,23 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
|||||||
.long("port")
|
.long("port")
|
||||||
.help("Port for the socket (if applicable) to listen on")
|
.help("Port for the socket (if applicable) to listen on")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
)
|
);
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
let app = app
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||||
.long(TESTNET_MODE_ARG_NAME)
|
.long(TESTNET_MODE_ARG_NAME)
|
||||||
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement")
|
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement. If this value is set, --eth_endpoint and --eth_private_key don't need to be set.")
|
||||||
);
|
.conflicts_with_all(&[ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME])
|
||||||
#[cfg(not(feature = "coconut"))]
|
)
|
||||||
let app = app
|
.arg(Arg::with_name(ETH_ENDPOINT_ARG_NAME)
|
||||||
.arg(Arg::with_name("eth_endpoint")
|
.long(ETH_ENDPOINT_ARG_NAME)
|
||||||
.long("eth_endpoint")
|
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
|
||||||
.takes_value(true))
|
.takes_value(true))
|
||||||
.arg(Arg::with_name("eth_private_key")
|
.arg(Arg::with_name(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.long("eth_private_key")
|
.long(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.takes_value(true));
|
.takes_value(true));
|
||||||
|
|
||||||
app
|
app
|
||||||
@@ -77,7 +82,7 @@ fn version_check(cfg: &Config) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(matches: &ArgMatches) {
|
pub async fn execute(matches: ArgMatches<'static>) {
|
||||||
let id = matches.value_of("id").unwrap();
|
let id = matches.value_of("id").unwrap();
|
||||||
|
|
||||||
let mut config = match Config::load_from_file(Some(id)) {
|
let mut config = match Config::load_from_file(Some(id)) {
|
||||||
@@ -88,12 +93,12 @@ pub fn execute(matches: &ArgMatches) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
config = override_config(config, matches);
|
config = override_config(config, &matches);
|
||||||
|
|
||||||
if !version_check(&config) {
|
if !version_check(&config) {
|
||||||
error!("failed the local version check");
|
error!("failed the local version check");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NymClient::new(config).run_forever();
|
NymClient::new(config).run_forever().await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ fn parse_package_version() -> Version {
|
|||||||
|
|
||||||
fn minor_0_12_upgrade(
|
fn minor_0_12_upgrade(
|
||||||
mut config: Config,
|
mut config: Config,
|
||||||
_matches: &ArgMatches,
|
_matches: &ArgMatches<'_>,
|
||||||
config_version: &Version,
|
config_version: &Version,
|
||||||
package_version: &Version,
|
package_version: &Version,
|
||||||
) -> Config {
|
) -> Config {
|
||||||
@@ -131,7 +131,7 @@ fn minor_0_12_upgrade(
|
|||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version) {
|
fn do_upgrade(mut config: Config, matches: &ArgMatches<'_>, package_version: Version) {
|
||||||
loop {
|
loop {
|
||||||
let config_version = parse_config_version(&config);
|
let config_version = parse_config_version(&config);
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(matches: &ArgMatches) {
|
pub fn execute(matches: &ArgMatches<'_>) {
|
||||||
let package_version = parse_package_version();
|
let package_version = parse_package_version();
|
||||||
|
|
||||||
let id = matches.value_of("id").unwrap();
|
let id = matches.value_of("id").unwrap();
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ pub mod client;
|
|||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
setup_logging();
|
setup_logging();
|
||||||
println!("{}", banner());
|
println!("{}", banner());
|
||||||
@@ -22,13 +23,13 @@ fn main() {
|
|||||||
.subcommand(commands::upgrade::command_args())
|
.subcommand(commands::upgrade::command_args())
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
execute(arg_matches);
|
execute(arg_matches).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(matches: ArgMatches) {
|
async fn execute(matches: ArgMatches<'static>) {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("init", Some(m)) => commands::init::execute(m),
|
("init", Some(m)) => commands::init::execute(m.clone()).await,
|
||||||
("run", Some(m)) => commands::run::execute(m),
|
("run", Some(m)) => commands::run::execute(m.clone()).await,
|
||||||
("upgrade", Some(m)) => commands::upgrade::execute(m),
|
("upgrade", Some(m)) => commands::upgrade::execute(m),
|
||||||
_ => println!("{}", usage()),
|
_ => println!("{}", usage()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use super::handler::Handler;
|
|||||||
use log::*;
|
use log::*;
|
||||||
use std::{net::SocketAddr, process, sync::Arc};
|
use std::{net::SocketAddr, process, sync::Arc};
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::runtime;
|
|
||||||
use tokio::{sync::Notify, task::JoinHandle};
|
use tokio::{sync::Notify, task::JoinHandle};
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
@@ -87,9 +86,9 @@ impl Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start(mut self, rt_handle: &runtime::Handle, handler: Handler) -> JoinHandle<()> {
|
pub(crate) fn start(mut self, handler: Handler) -> JoinHandle<()> {
|
||||||
info!("Running websocket on {:?}", self.address.to_string());
|
info!("Running websocket on {:?}", self.address.to_string());
|
||||||
|
|
||||||
rt_handle.spawn(async move { self.run(handler).await })
|
tokio::spawn(async move { self.run(handler).await })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "websocket-requests"
|
name = "websocket-requests"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "0.12.0"
|
version = "1.0.0-rc.1"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
rust-version = "1.56"
|
rust-version = "1.56"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
@@ -43,6 +43,7 @@ network-defaults = { path = "../../common/network-defaults" }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut"]
|
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut"]
|
||||||
|
eth = []
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
|
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
|
||||||
@@ -59,12 +59,6 @@ eth_endpoint = '{{ client.eth_endpoint }}'
|
|||||||
|
|
||||||
##### additional client config options #####
|
##### additional client config options #####
|
||||||
|
|
||||||
# ID of the gateway from which the client should be fetching messages.
|
|
||||||
gateway_id = '{{ client.gateway_id }}'
|
|
||||||
|
|
||||||
# Address of the gateway listener to which all client requests should be sent.
|
|
||||||
gateway_listener = '{{ client.gateway_listener }}'
|
|
||||||
|
|
||||||
# A gateway specific, optional, base58 stringified shared key used for
|
# A gateway specific, optional, base58 stringified shared key used for
|
||||||
# communication with particular gateway.
|
# communication with particular gateway.
|
||||||
gateway_shared_key_file = '{{ client.gateway_shared_key_file }}'
|
gateway_shared_key_file = '{{ client.gateway_shared_key_file }}'
|
||||||
@@ -72,12 +66,22 @@ gateway_shared_key_file = '{{ client.gateway_shared_key_file }}'
|
|||||||
# Path to file containing key used for encrypting and decrypting the content of an
|
# Path to file containing key used for encrypting and decrypting the content of an
|
||||||
# acknowledgement so that nobody besides the client knows which packet it refers to.
|
# acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||||
ack_key_file = '{{ client.ack_key_file }}'
|
ack_key_file = '{{ client.ack_key_file }}'
|
||||||
|
|
||||||
##### advanced configuration options #####
|
##### advanced configuration options #####
|
||||||
|
|
||||||
# Absolute path to the home Nym Clients directory.
|
# Absolute path to the home Nym Clients directory.
|
||||||
nym_root_directory = '{{ client.nym_root_directory }}'
|
nym_root_directory = '{{ client.nym_root_directory }}'
|
||||||
|
|
||||||
|
[client.gateway_endpoint]
|
||||||
|
# ID of the gateway from which the client should be fetching messages.
|
||||||
|
gateway_id = '{{ client.gateway_endpoint.gateway_id }}'
|
||||||
|
|
||||||
|
# Address of the gateway owner to which the client should send messages.
|
||||||
|
gateway_owner = '{{ client.gateway_endpoint.gateway_owner }}'
|
||||||
|
|
||||||
|
# Address of the gateway listener to which all client requests should be sent.
|
||||||
|
gateway_listener = '{{ client.gateway_endpoint.gateway_listener }}'
|
||||||
|
|
||||||
|
|
||||||
##### socket config options #####
|
##### socket config options #####
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ use gateway_client::{
|
|||||||
use log::*;
|
use log::*;
|
||||||
use nymsphinx::addressing::clients::Recipient;
|
use nymsphinx::addressing::clients::Recipient;
|
||||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
|
|
||||||
use crate::client::config::Config;
|
use crate::client::config::Config;
|
||||||
use crate::socks::{
|
use crate::socks::{
|
||||||
@@ -43,11 +42,6 @@ pub struct NymClient {
|
|||||||
/// key filepaths, etc.
|
/// key filepaths, etc.
|
||||||
config: Config,
|
config: Config,
|
||||||
|
|
||||||
/// Tokio runtime used for futures execution.
|
|
||||||
// TODO: JS: Personally I think I prefer the implicit way of using it that we've done with the
|
|
||||||
// gateway.
|
|
||||||
runtime: Runtime,
|
|
||||||
|
|
||||||
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
||||||
key_manager: KeyManager,
|
key_manager: KeyManager,
|
||||||
}
|
}
|
||||||
@@ -58,7 +52,6 @@ impl NymClient {
|
|||||||
let key_manager = KeyManager::load_keys(&pathfinder).expect("failed to load stored keys");
|
let key_manager = KeyManager::load_keys(&pathfinder).expect("failed to load stored keys");
|
||||||
|
|
||||||
NymClient {
|
NymClient {
|
||||||
runtime: Runtime::new().unwrap(),
|
|
||||||
config,
|
config,
|
||||||
key_manager,
|
key_manager,
|
||||||
}
|
}
|
||||||
@@ -82,9 +75,6 @@ impl NymClient {
|
|||||||
mix_tx: BatchMixMessageSender,
|
mix_tx: BatchMixMessageSender,
|
||||||
) {
|
) {
|
||||||
info!("Starting loop cover traffic stream...");
|
info!("Starting loop cover traffic stream...");
|
||||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
|
||||||
// set in the constructor which HAS TO be called within context of a tokio runtime
|
|
||||||
let _guard = self.runtime.enter();
|
|
||||||
|
|
||||||
LoopCoverTrafficStream::new(
|
LoopCoverTrafficStream::new(
|
||||||
self.key_manager.ack_key(),
|
self.key_manager.ack_key(),
|
||||||
@@ -97,7 +87,7 @@ impl NymClient {
|
|||||||
self.as_mix_recipient(),
|
self.as_mix_recipient(),
|
||||||
topology_accessor,
|
topology_accessor,
|
||||||
)
|
)
|
||||||
.start(self.runtime.handle());
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_real_traffic_controller(
|
fn start_real_traffic_controller(
|
||||||
@@ -119,10 +109,6 @@ impl NymClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
info!("Starting real traffic stream...");
|
info!("Starting real traffic stream...");
|
||||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
|
||||||
// set in the constructor [of OutQueueControl] which HAS TO be called within context of a tokio runtime
|
|
||||||
// When refactoring this restriction should definitely be removed.
|
|
||||||
let _guard = self.runtime.enter();
|
|
||||||
|
|
||||||
RealMessagesController::new(
|
RealMessagesController::new(
|
||||||
controller_config,
|
controller_config,
|
||||||
@@ -132,7 +118,7 @@ impl NymClient {
|
|||||||
topology_accessor,
|
topology_accessor,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
)
|
)
|
||||||
.start(self.runtime.handle());
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffer controlling all messages fetched from provider
|
// buffer controlling all messages fetched from provider
|
||||||
@@ -150,10 +136,10 @@ impl NymClient {
|
|||||||
mixnet_receiver,
|
mixnet_receiver,
|
||||||
reply_key_storage,
|
reply_key_storage,
|
||||||
)
|
)
|
||||||
.start(self.runtime.handle())
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_gateway_client(
|
async fn start_gateway_client(
|
||||||
&mut self,
|
&mut self,
|
||||||
mixnet_message_sender: MixnetMessageSender,
|
mixnet_message_sender: MixnetMessageSender,
|
||||||
ack_sender: AcknowledgementSender,
|
ack_sender: AcknowledgementSender,
|
||||||
@@ -162,6 +148,10 @@ impl NymClient {
|
|||||||
if gateway_id.is_empty() {
|
if gateway_id.is_empty() {
|
||||||
panic!("The identity of the gateway is unknown - did you run `nym-client` init?")
|
panic!("The identity of the gateway is unknown - did you run `nym-client` init?")
|
||||||
}
|
}
|
||||||
|
let gateway_owner = self.config.get_base().get_gateway_owner();
|
||||||
|
if gateway_owner.is_empty() {
|
||||||
|
panic!("The owner of the gateway is unknown - did you run `nym-client` init?")
|
||||||
|
}
|
||||||
let gateway_address = self.config.get_base().get_gateway_listener();
|
let gateway_address = self.config.get_base().get_gateway_listener();
|
||||||
if gateway_address.is_empty() {
|
if gateway_address.is_empty() {
|
||||||
panic!("The address of the gateway is unknown - did you run `nym-client` init?")
|
panic!("The address of the gateway is unknown - did you run `nym-client` init?")
|
||||||
@@ -170,47 +160,45 @@ impl NymClient {
|
|||||||
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
||||||
.expect("provided gateway id is invalid!");
|
.expect("provided gateway id is invalid!");
|
||||||
|
|
||||||
self.runtime.block_on(async {
|
#[cfg(feature = "coconut")]
|
||||||
#[cfg(feature = "coconut")]
|
let bandwidth_controller = BandwidthController::new(
|
||||||
let bandwidth_controller = BandwidthController::new(
|
self.config.get_base().get_validator_api_endpoints(),
|
||||||
self.config.get_base().get_validator_api_endpoints(),
|
*self.key_manager.identity_keypair().public_key(),
|
||||||
*self.key_manager.identity_keypair().public_key(),
|
);
|
||||||
);
|
#[cfg(not(feature = "coconut"))]
|
||||||
#[cfg(not(feature = "coconut"))]
|
let bandwidth_controller = BandwidthController::new(
|
||||||
let bandwidth_controller = BandwidthController::new(
|
self.config.get_base().get_eth_endpoint(),
|
||||||
self.config.get_base().get_eth_endpoint(),
|
self.config.get_base().get_eth_private_key(),
|
||||||
self.config.get_base().get_eth_private_key(),
|
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
)
|
||||||
)
|
.expect("Could not create bandwidth controller");
|
||||||
.expect("Could not create bandwidth controller");
|
|
||||||
|
|
||||||
let mut gateway_client = GatewayClient::new(
|
let mut gateway_client = GatewayClient::new(
|
||||||
gateway_address,
|
gateway_address,
|
||||||
self.key_manager.identity_keypair(),
|
self.key_manager.identity_keypair(),
|
||||||
gateway_identity,
|
gateway_identity,
|
||||||
Some(self.key_manager.gateway_shared_key()),
|
gateway_owner,
|
||||||
mixnet_message_sender,
|
Some(self.key_manager.gateway_shared_key()),
|
||||||
ack_sender,
|
mixnet_message_sender,
|
||||||
self.config.get_base().get_gateway_response_timeout(),
|
ack_sender,
|
||||||
Some(bandwidth_controller),
|
self.config.get_base().get_gateway_response_timeout(),
|
||||||
);
|
Some(bandwidth_controller),
|
||||||
|
);
|
||||||
|
|
||||||
if self.config.get_base().get_testnet_mode() {
|
if self.config.get_base().get_testnet_mode() {
|
||||||
gateway_client.set_testnet_mode(true)
|
gateway_client.set_testnet_mode(true)
|
||||||
}
|
}
|
||||||
|
gateway_client
|
||||||
|
.authenticate_and_start()
|
||||||
|
.await
|
||||||
|
.expect("could not authenticate and start up the gateway connection");
|
||||||
|
|
||||||
gateway_client
|
gateway_client
|
||||||
.authenticate_and_start()
|
|
||||||
.await
|
|
||||||
.expect("could not authenticate and start up the gateway connection");
|
|
||||||
|
|
||||||
gateway_client
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// future responsible for periodically polling directory server and updating
|
// future responsible for periodically polling directory server and updating
|
||||||
// the current global view of topology
|
// the current global view of topology
|
||||||
fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
async fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||||
self.config.get_base().get_validator_api_endpoints(),
|
self.config.get_base().get_validator_api_endpoints(),
|
||||||
self.config.get_base().get_topology_refresh_rate(),
|
self.config.get_base().get_topology_refresh_rate(),
|
||||||
@@ -221,13 +209,10 @@ impl NymClient {
|
|||||||
// before returning, block entire runtime to refresh the current network view so that any
|
// before returning, block entire runtime to refresh the current network view so that any
|
||||||
// components depending on topology would see a non-empty view
|
// components depending on topology would see a non-empty view
|
||||||
info!("Obtaining initial network topology");
|
info!("Obtaining initial network topology");
|
||||||
self.runtime.block_on(topology_refresher.refresh());
|
topology_refresher.refresh().await;
|
||||||
|
|
||||||
// TODO: a slightly more graceful termination here
|
// TODO: a slightly more graceful termination here
|
||||||
if !self
|
if !topology_refresher.is_topology_routable().await {
|
||||||
.runtime
|
|
||||||
.block_on(topology_refresher.is_topology_routable())
|
|
||||||
{
|
|
||||||
panic!(
|
panic!(
|
||||||
"The current network topology seem to be insufficient to route any packets through\
|
"The current network topology seem to be insufficient to route any packets through\
|
||||||
- check if enough nodes and a gateway are online"
|
- check if enough nodes and a gateway are online"
|
||||||
@@ -235,7 +220,7 @@ impl NymClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
info!("Starting topology refresher...");
|
info!("Starting topology refresher...");
|
||||||
topology_refresher.start(self.runtime.handle());
|
topology_refresher.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// controller for sending sphinx packets to mixnet (either real traffic or cover traffic)
|
// controller for sending sphinx packets to mixnet (either real traffic or cover traffic)
|
||||||
@@ -248,7 +233,7 @@ impl NymClient {
|
|||||||
gateway_client: GatewayClient,
|
gateway_client: GatewayClient,
|
||||||
) {
|
) {
|
||||||
info!("Starting mix traffic controller...");
|
info!("Starting mix traffic controller...");
|
||||||
MixTrafficController::new(mix_rx, gateway_client).start(self.runtime.handle());
|
MixTrafficController::new(mix_rx, gateway_client).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_socks5_listener(
|
fn start_socks5_listener(
|
||||||
@@ -267,14 +252,13 @@ impl NymClient {
|
|||||||
self.config.get_provider_mix_address(),
|
self.config.get_provider_mix_address(),
|
||||||
self.as_mix_recipient(),
|
self.as_mix_recipient(),
|
||||||
);
|
);
|
||||||
self.runtime
|
tokio::spawn(async move { sphinx_socks.serve(msg_input, buffer_requester).await });
|
||||||
.spawn(async move { sphinx_socks.serve(msg_input, buffer_requester).await });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
|
/// blocking version of `start` method. Will run forever (or until SIGINT is sent)
|
||||||
pub fn run_forever(&mut self) {
|
pub async fn run_forever(&mut self) {
|
||||||
self.start();
|
self.start().await;
|
||||||
if let Err(e) = self.runtime.block_on(tokio::signal::ctrl_c()) {
|
if let Err(e) = tokio::signal::ctrl_c().await {
|
||||||
error!(
|
error!(
|
||||||
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
||||||
e
|
e
|
||||||
@@ -286,7 +270,7 @@ impl NymClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self) {
|
pub async fn start(&mut self) {
|
||||||
info!("Starting nym client");
|
info!("Starting nym client");
|
||||||
// channels for inter-component communication
|
// channels for inter-component communication
|
||||||
// TODO: make the channels be internally created by the relevant components
|
// TODO: make the channels be internally created by the relevant components
|
||||||
@@ -318,14 +302,17 @@ impl NymClient {
|
|||||||
|
|
||||||
// the components are started in very specific order. Unless you know what you are doing,
|
// the components are started in very specific order. Unless you know what you are doing,
|
||||||
// do not change that.
|
// do not change that.
|
||||||
self.start_topology_refresher(shared_topology_accessor.clone());
|
self.start_topology_refresher(shared_topology_accessor.clone())
|
||||||
|
.await;
|
||||||
self.start_received_messages_buffer_controller(
|
self.start_received_messages_buffer_controller(
|
||||||
received_buffer_request_receiver,
|
received_buffer_request_receiver,
|
||||||
mixnet_messages_receiver,
|
mixnet_messages_receiver,
|
||||||
reply_key_storage.clone(),
|
reply_key_storage.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let gateway_client = self.start_gateway_client(mixnet_messages_sender, ack_sender);
|
let gateway_client = self
|
||||||
|
.start_gateway_client(mixnet_messages_sender, ack_sender)
|
||||||
|
.await;
|
||||||
|
|
||||||
self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client);
|
self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client);
|
||||||
self.start_real_traffic_controller(
|
self.start_real_traffic_controller(
|
||||||
|
|||||||
@@ -28,7 +28,13 @@ use topology::{filter::VersionFilterable, gateway};
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::client::config::Config;
|
use crate::client::config::Config;
|
||||||
use crate::commands::{override_config, TESTNET_MODE_ARG_NAME};
|
use crate::commands::override_config;
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
use crate::commands::{
|
||||||
|
DEFAULT_ETH_ENDPOINT, DEFAULT_ETH_PRIVATE_KEY, ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME,
|
||||||
|
TESTNET_MODE_ARG_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||||
let app = App::new("init")
|
let app = App::new("init")
|
||||||
@@ -65,24 +71,29 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
|||||||
.long("fastmode")
|
.long("fastmode")
|
||||||
.hidden(true) // this will prevent this flag from being displayed in `--help`
|
.hidden(true) // this will prevent this flag from being displayed in `--help`
|
||||||
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
||||||
)
|
);
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
let app = app
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||||
.long(TESTNET_MODE_ARG_NAME)
|
.long(TESTNET_MODE_ARG_NAME)
|
||||||
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement")
|
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement. If this value is set, --eth_endpoint and --eth_private_key don't need to be set.")
|
||||||
);
|
.conflicts_with_all(&[ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME])
|
||||||
#[cfg(not(feature = "coconut"))]
|
)
|
||||||
let app = app
|
.arg(Arg::with_name(ETH_ENDPOINT_ARG_NAME)
|
||||||
.arg(Arg::with_name("eth_endpoint")
|
.long(ETH_ENDPOINT_ARG_NAME)
|
||||||
.long("eth_endpoint")
|
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.default_value_if(TESTNET_MODE_ARG_NAME, None, DEFAULT_ETH_ENDPOINT)
|
||||||
.required(true))
|
.required(true))
|
||||||
.arg(Arg::with_name("eth_private_key")
|
.arg(Arg::with_name(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.long("eth_private_key")
|
.long(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true));
|
.default_value_if(TESTNET_MODE_ARG_NAME, None, DEFAULT_ETH_PRIVATE_KEY)
|
||||||
|
.required(true)
|
||||||
|
);
|
||||||
|
|
||||||
app
|
app
|
||||||
}
|
}
|
||||||
@@ -125,6 +136,7 @@ async fn register_with_gateway(
|
|||||||
let mut gateway_client = GatewayClient::new_init(
|
let mut gateway_client = GatewayClient::new_init(
|
||||||
gateway.clients_address(),
|
gateway.clients_address(),
|
||||||
gateway.identity_key,
|
gateway.identity_key,
|
||||||
|
gateway.owner.clone(),
|
||||||
our_identity.clone(),
|
our_identity.clone(),
|
||||||
timeout,
|
timeout,
|
||||||
);
|
);
|
||||||
@@ -208,7 +220,7 @@ fn show_address(config: &Config) {
|
|||||||
println!("\nThe address of this client is: {}", client_recipient);
|
println!("\nThe address of this client is: {}", client_recipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(matches: &ArgMatches) {
|
pub async fn execute(matches: ArgMatches<'static>) {
|
||||||
println!("Initialising client...");
|
println!("Initialising client...");
|
||||||
|
|
||||||
let id = matches.value_of("id").unwrap(); // required for now
|
let id = matches.value_of("id").unwrap(); // required for now
|
||||||
@@ -227,7 +239,7 @@ pub fn execute(matches: &ArgMatches) {
|
|||||||
|
|
||||||
// TODO: ideally that should be the last thing that's being done to config.
|
// TODO: ideally that should be the last thing that's being done to config.
|
||||||
// However, we are later further overriding it with gateway id
|
// However, we are later further overriding it with gateway id
|
||||||
config = override_config(config, matches);
|
config = override_config(config, &matches);
|
||||||
if matches.is_present("fastmode") {
|
if matches.is_present("fastmode") {
|
||||||
config.get_base_mut().set_high_default_traffic_volume();
|
config.get_base_mut().set_high_default_traffic_volume();
|
||||||
}
|
}
|
||||||
@@ -240,26 +252,19 @@ pub fn execute(matches: &ArgMatches) {
|
|||||||
|
|
||||||
let chosen_gateway_id = matches.value_of("gateway");
|
let chosen_gateway_id = matches.value_of("gateway");
|
||||||
|
|
||||||
let registration_fut = async {
|
let gateway_details = gateway_details(
|
||||||
let gate_details = gateway_details(
|
config.get_base().get_validator_api_endpoints(),
|
||||||
config.get_base().get_validator_api_endpoints(),
|
chosen_gateway_id,
|
||||||
chosen_gateway_id,
|
)
|
||||||
)
|
.await;
|
||||||
.await;
|
let shared_keys =
|
||||||
config
|
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await;
|
||||||
.get_base_mut()
|
|
||||||
.with_gateway_id(gate_details.identity_key.to_base58_string());
|
|
||||||
let shared_keys =
|
|
||||||
register_with_gateway(&gate_details, key_manager.identity_keypair()).await;
|
|
||||||
(shared_keys, gate_details.clients_address())
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: is there perhaps a way to make it work without having to spawn entire runtime?
|
config.get_base_mut().with_gateway_endpoint(
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
gateway_details.identity_key.to_base58_string(),
|
||||||
let (shared_keys, gateway_listener) = rt.block_on(registration_fut);
|
gateway_details.owner.clone(),
|
||||||
config
|
gateway_details.clients_address(),
|
||||||
.get_base_mut()
|
);
|
||||||
.with_gateway_listener(gateway_listener);
|
|
||||||
key_manager.insert_gateway_shared_key(shared_keys);
|
key_manager.insert_gateway_shared_key(shared_keys);
|
||||||
|
|
||||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||||
|
|||||||
@@ -10,6 +10,16 @@ pub(crate) mod run;
|
|||||||
pub(crate) mod upgrade;
|
pub(crate) mod upgrade;
|
||||||
|
|
||||||
pub(crate) const TESTNET_MODE_ARG_NAME: &str = "testnet-mode";
|
pub(crate) const TESTNET_MODE_ARG_NAME: &str = "testnet-mode";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const ETH_ENDPOINT_ARG_NAME: &str = "eth_endpoint";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const ETH_PRIVATE_KEY_ARG_NAME: &str = "eth_private_key";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const DEFAULT_ETH_ENDPOINT: &str =
|
||||||
|
"https://rinkeby.infura.io/v3/00000000000000000000000000000000";
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
pub(crate) const DEFAULT_ETH_PRIVATE_KEY: &str =
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000001";
|
||||||
|
|
||||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||||
raw.split(',')
|
raw.split(',')
|
||||||
@@ -22,7 +32,7 @@ fn parse_validators(raw: &str) -> Vec<Url> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
|
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> Config {
|
||||||
if let Some(raw_validators) = matches.value_of("validators") {
|
if let Some(raw_validators) = matches.value_of("validators") {
|
||||||
config
|
config
|
||||||
.get_base_mut()
|
.get_base_mut()
|
||||||
@@ -42,15 +52,23 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
if let Some(eth_endpoint) = matches.value_of("eth_endpoint") {
|
if let Some(eth_endpoint) = matches.value_of(ETH_ENDPOINT_ARG_NAME) {
|
||||||
config.get_base_mut().with_eth_endpoint(eth_endpoint);
|
config.get_base_mut().with_eth_endpoint(eth_endpoint);
|
||||||
|
} else if !cfg!(feature = "eth") {
|
||||||
|
config
|
||||||
|
.get_base_mut()
|
||||||
|
.with_eth_endpoint(DEFAULT_ETH_ENDPOINT);
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "coconut"))]
|
#[cfg(not(feature = "coconut"))]
|
||||||
if let Some(eth_private_key) = matches.value_of("eth_private_key") {
|
if let Some(eth_private_key) = matches.value_of(ETH_PRIVATE_KEY_ARG_NAME) {
|
||||||
config.get_base_mut().with_eth_private_key(eth_private_key);
|
config.get_base_mut().with_eth_private_key(eth_private_key);
|
||||||
|
} else if !cfg!(feature = "eth") {
|
||||||
|
config
|
||||||
|
.get_base_mut()
|
||||||
|
.with_eth_private_key(DEFAULT_ETH_PRIVATE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches.is_present(TESTNET_MODE_ARG_NAME) {
|
if !cfg!(feature = "eth") || matches.is_present(TESTNET_MODE_ARG_NAME) {
|
||||||
config.get_base_mut().with_testnet_mode(true)
|
config.get_base_mut().with_testnet_mode(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
|
|
||||||
use crate::client::config::Config;
|
use crate::client::config::Config;
|
||||||
use crate::client::NymClient;
|
use crate::client::NymClient;
|
||||||
use crate::commands::{override_config, TESTNET_MODE_ARG_NAME};
|
use crate::commands::override_config;
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
use crate::commands::{ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME, TESTNET_MODE_ARG_NAME};
|
||||||
use clap::{App, Arg, ArgMatches};
|
use clap::{App, Arg, ArgMatches};
|
||||||
use config::NymConfig;
|
use config::NymConfig;
|
||||||
use log::*;
|
use log::*;
|
||||||
@@ -44,21 +47,23 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
|||||||
.long("port")
|
.long("port")
|
||||||
.help("Port for the socket to listen on")
|
.help("Port for the socket to listen on")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
)
|
);
|
||||||
|
#[cfg(feature = "eth")]
|
||||||
|
#[cfg(not(feature = "coconut"))]
|
||||||
|
let app = app
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
Arg::with_name(TESTNET_MODE_ARG_NAME)
|
||||||
.long(TESTNET_MODE_ARG_NAME)
|
.long(TESTNET_MODE_ARG_NAME)
|
||||||
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement")
|
.help("Set this client to work in a testnet mode that would attempt to use gateway without bandwidth credential requirement. If this value is set, --eth_endpoint and --eth_private_key don't need to be set.")
|
||||||
);
|
.conflicts_with_all(&[ETH_ENDPOINT_ARG_NAME, ETH_PRIVATE_KEY_ARG_NAME])
|
||||||
#[cfg(not(feature = "coconut"))]
|
)
|
||||||
let app = app
|
.arg(Arg::with_name(ETH_ENDPOINT_ARG_NAME)
|
||||||
.arg(Arg::with_name("eth_endpoint")
|
.long(ETH_ENDPOINT_ARG_NAME)
|
||||||
.long("eth_endpoint")
|
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
|
||||||
.takes_value(true))
|
.takes_value(true))
|
||||||
.arg(Arg::with_name("eth_private_key")
|
.arg(Arg::with_name(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.long("eth_private_key")
|
.long(ETH_PRIVATE_KEY_ARG_NAME)
|
||||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens. If you don't want to set this value, use --testnet-mode instead")
|
||||||
.takes_value(true));
|
.takes_value(true));
|
||||||
|
|
||||||
app
|
app
|
||||||
@@ -83,7 +88,7 @@ fn version_check(cfg: &Config) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(matches: &ArgMatches) {
|
pub async fn execute(matches: ArgMatches<'static>) {
|
||||||
let id = matches.value_of("id").unwrap();
|
let id = matches.value_of("id").unwrap();
|
||||||
|
|
||||||
let mut config = match Config::load_from_file(Some(id)) {
|
let mut config = match Config::load_from_file(Some(id)) {
|
||||||
@@ -94,12 +99,12 @@ pub fn execute(matches: &ArgMatches) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
config = override_config(config, matches);
|
config = override_config(config, &matches);
|
||||||
|
|
||||||
if !version_check(&config) {
|
if !version_check(&config) {
|
||||||
error!("failed the local version check");
|
error!("failed the local version check");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NymClient::new(config).run_forever();
|
NymClient::new(config).run_forever().await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ fn parse_package_version() -> Version {
|
|||||||
|
|
||||||
fn minor_0_12_upgrade(
|
fn minor_0_12_upgrade(
|
||||||
mut config: Config,
|
mut config: Config,
|
||||||
_matches: &ArgMatches,
|
_matches: &ArgMatches<'_>,
|
||||||
config_version: &Version,
|
config_version: &Version,
|
||||||
package_version: &Version,
|
package_version: &Version,
|
||||||
) -> Config {
|
) -> Config {
|
||||||
@@ -131,7 +131,7 @@ fn minor_0_12_upgrade(
|
|||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version) {
|
fn do_upgrade(mut config: Config, matches: &ArgMatches<'_>, package_version: Version) {
|
||||||
loop {
|
loop {
|
||||||
let config_version = parse_config_version(&config);
|
let config_version = parse_config_version(&config);
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(matches: &ArgMatches) {
|
pub fn execute(matches: &ArgMatches<'_>) {
|
||||||
let package_version = parse_package_version();
|
let package_version = parse_package_version();
|
||||||
|
|
||||||
let id = matches.value_of("id").unwrap();
|
let id = matches.value_of("id").unwrap();
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ pub mod client;
|
|||||||
mod commands;
|
mod commands;
|
||||||
pub mod socks;
|
pub mod socks;
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
setup_logging();
|
setup_logging();
|
||||||
println!("{}", banner());
|
println!("{}", banner());
|
||||||
@@ -22,13 +23,13 @@ fn main() {
|
|||||||
.subcommand(commands::upgrade::command_args())
|
.subcommand(commands::upgrade::command_args())
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
execute(arg_matches);
|
execute(arg_matches).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(matches: ArgMatches) {
|
async fn execute(matches: ArgMatches<'static>) {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("init", Some(m)) => commands::init::execute(m),
|
("init", Some(m)) => commands::init::execute(m.clone()).await,
|
||||||
("run", Some(m)) => commands::run::execute(m),
|
("run", Some(m)) => commands::run::execute(m.clone()).await,
|
||||||
("upgrade", Some(m)) => commands::upgrade::execute(m),
|
("upgrade", Some(m)) => commands::upgrade::execute(m),
|
||||||
_ => println!("{}", usage()),
|
_ => println!("{}", usage()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
/node_modules/
|
|
||||||
/src/node_modules/@sapper/
|
|
||||||
yarn-error.log
|
|
||||||
/__sapper__/
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
## Prerequisites
|
|
||||||
|
|
||||||
On Ubuntu-ish systems (not tested on Debian but may work):
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo apt update && sudo apt install libwebkit2gtk-4.0-dev \
|
|
||||||
build-essential \
|
|
||||||
curl \
|
|
||||||
wget \
|
|
||||||
libssl-dev \
|
|
||||||
libgtk-3-dev \
|
|
||||||
libappindicator3-dev \
|
|
||||||
patchelf \
|
|
||||||
librsvg2-dev```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
1. Start Sapper([docs](https://sapper.svelte.dev/docs/)) -> `yarn run dev`
|
|
||||||
2. Start Tauri([docs](https://tauri.studio/en/)) in another terminal -> `yarn tauri dev`
|
|
||||||
3. Start validator-api locally, or override `validator-urls` in `index.svelte`
|
|
||||||
|
|
||||||
## Getting around
|
|
||||||
|
|
||||||
+ Frontend -> `tauri-client/`
|
|
||||||
+ logic -> `tauri-client/src/routes/index.svelte`
|
|
||||||
+ assets -> `tauri-client/static`
|
|
||||||
+ Backend -> `tauri-client/src/src-tauri`
|
|
||||||
|
|
||||||
## Build standalone app
|
|
||||||
|
|
||||||
+ yarn tauri build [--debug]
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "TODO",
|
|
||||||
"description": "TODO",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "sapper dev",
|
|
||||||
"build": "sapper build --legacy",
|
|
||||||
"export": "sapper export --legacy",
|
|
||||||
"start": "node __sapper__/build"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@tauri-apps/api": "^1.0.0-beta.4",
|
|
||||||
"compression": "^1.7.1",
|
|
||||||
"polka": "next",
|
|
||||||
"qrious": "^4.0.2",
|
|
||||||
"sirv": "^1.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "^7.0.0",
|
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
|
||||||
"@babel/plugin-transform-runtime": "^7.0.0",
|
|
||||||
"@babel/preset-env": "^7.0.0",
|
|
||||||
"@babel/runtime": "^7.0.0",
|
|
||||||
"@rollup/plugin-babel": "^5.0.0",
|
|
||||||
"@rollup/plugin-commonjs": "^14.0.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
|
||||||
"@rollup/plugin-replace": "^2.4.0",
|
|
||||||
"@rollup/plugin-url": "^5.0.0",
|
|
||||||
"@tauri-apps/cli": "^1.0.0-beta.5",
|
|
||||||
"rollup": "^2.3.4",
|
|
||||||
"rollup-plugin-svelte": "^7.0.0",
|
|
||||||
"rollup-plugin-terser": "^7.0.0",
|
|
||||||
"sapper": "^0.28.0",
|
|
||||||
"sass": "^1.35.2",
|
|
||||||
"svelte": "^3.17.3",
|
|
||||||
"svelte-preprocess": "^4.7.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
import path from "path";
|
|
||||||
import resolve from "@rollup/plugin-node-resolve";
|
|
||||||
import replace from "@rollup/plugin-replace";
|
|
||||||
import commonjs from "@rollup/plugin-commonjs";
|
|
||||||
import url from "@rollup/plugin-url";
|
|
||||||
import svelte from "rollup-plugin-svelte";
|
|
||||||
import babel from "@rollup/plugin-babel";
|
|
||||||
import { terser } from "rollup-plugin-terser";
|
|
||||||
import config from "sapper/config/rollup.js";
|
|
||||||
import pkg from "./package.json";
|
|
||||||
import sveltePreprocess from "svelte-preprocess";
|
|
||||||
|
|
||||||
const mode = process.env.NODE_ENV;
|
|
||||||
const dev = mode === "development";
|
|
||||||
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
|
|
||||||
|
|
||||||
const onwarn = (warning, onwarn) =>
|
|
||||||
(warning.code === "MISSING_EXPORT" && /'preload'/.test(warning.message)) ||
|
|
||||||
(warning.code === "CIRCULAR_DEPENDENCY" &&
|
|
||||||
/[/\\]@sapper[/\\]/.test(warning.message)) ||
|
|
||||||
onwarn(warning);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
client: {
|
|
||||||
input: config.client.input(),
|
|
||||||
output: config.client.output(),
|
|
||||||
plugins: [
|
|
||||||
replace({
|
|
||||||
preventAssignment: true,
|
|
||||||
values: {
|
|
||||||
"process.browser": true,
|
|
||||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
svelte({
|
|
||||||
compilerOptions: {
|
|
||||||
dev,
|
|
||||||
hydratable: true,
|
|
||||||
},
|
|
||||||
preprocess: sveltePreprocess(),
|
|
||||||
}),
|
|
||||||
url({
|
|
||||||
sourceDir: path.resolve(__dirname, "src/node_modules/images"),
|
|
||||||
publicPath: "/client/",
|
|
||||||
}),
|
|
||||||
resolve({
|
|
||||||
browser: true,
|
|
||||||
dedupe: ["svelte"],
|
|
||||||
}),
|
|
||||||
commonjs(),
|
|
||||||
|
|
||||||
legacy &&
|
|
||||||
babel({
|
|
||||||
extensions: [".js", ".mjs", ".html", ".svelte"],
|
|
||||||
babelHelpers: "runtime",
|
|
||||||
exclude: ["node_modules/@babel/**"],
|
|
||||||
presets: [
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
targets: "> 0.25%, not dead",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
"@babel/plugin-syntax-dynamic-import",
|
|
||||||
[
|
|
||||||
"@babel/plugin-transform-runtime",
|
|
||||||
{
|
|
||||||
useESModules: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
|
|
||||||
!dev &&
|
|
||||||
terser({
|
|
||||||
module: true,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
|
|
||||||
preserveEntrySignatures: false,
|
|
||||||
onwarn,
|
|
||||||
},
|
|
||||||
|
|
||||||
server: {
|
|
||||||
input: config.server.input(),
|
|
||||||
output: config.server.output(),
|
|
||||||
plugins: [
|
|
||||||
replace({
|
|
||||||
preventAssignment: true,
|
|
||||||
values: {
|
|
||||||
"process.browser": false,
|
|
||||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
svelte({
|
|
||||||
compilerOptions: {
|
|
||||||
dev,
|
|
||||||
generate: "ssr",
|
|
||||||
hydratable: true,
|
|
||||||
},
|
|
||||||
emitCss: false,
|
|
||||||
}),
|
|
||||||
url({
|
|
||||||
sourceDir: path.resolve(__dirname, "src/node_modules/images"),
|
|
||||||
publicPath: "/client/",
|
|
||||||
emitFiles: false, // already emitted by client build
|
|
||||||
}),
|
|
||||||
resolve({
|
|
||||||
dedupe: ["svelte"],
|
|
||||||
}),
|
|
||||||
commonjs(),
|
|
||||||
],
|
|
||||||
external: Object.keys(pkg.dependencies).concat(
|
|
||||||
require("module").builtinModules
|
|
||||||
),
|
|
||||||
preserveEntrySignatures: "strict",
|
|
||||||
onwarn,
|
|
||||||
},
|
|
||||||
|
|
||||||
serviceworker: {
|
|
||||||
input: config.serviceworker.input(),
|
|
||||||
output: config.serviceworker.output(),
|
|
||||||
plugins: [
|
|
||||||
resolve(),
|
|
||||||
replace({
|
|
||||||
preventAssignment: true,
|
|
||||||
values: {
|
|
||||||
"process.browser": true,
|
|
||||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
commonjs(),
|
|
||||||
!dev && terser(),
|
|
||||||
],
|
|
||||||
preserveEntrySignatures: false,
|
|
||||||
onwarn,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
/**
|
|
||||||
* Run this script to convert the project to TypeScript. This is only guaranteed to work
|
|
||||||
* on the unmodified default template; if you have done code changes you are likely need
|
|
||||||
* to touch up the generated project manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @ts-check
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const { argv } = require('process');
|
|
||||||
|
|
||||||
const projectRoot = argv[2] || path.join(__dirname, '..');
|
|
||||||
|
|
||||||
const isRollup = fs.existsSync(path.join(projectRoot, "rollup.config.js"));
|
|
||||||
|
|
||||||
function warn(message) {
|
|
||||||
console.warn('Warning: ' + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceInFile(fileName, replacements) {
|
|
||||||
if (fs.existsSync(fileName)) {
|
|
||||||
let contents = fs.readFileSync(fileName, 'utf8');
|
|
||||||
let hadUpdates = false;
|
|
||||||
|
|
||||||
replacements.forEach(([from, to]) => {
|
|
||||||
const newContents = contents.replace(from, to);
|
|
||||||
|
|
||||||
const isAlreadyApplied = typeof to !== 'string' || contents.includes(to);
|
|
||||||
|
|
||||||
if (newContents !== contents) {
|
|
||||||
contents = newContents;
|
|
||||||
hadUpdates = true;
|
|
||||||
} else if (!isAlreadyApplied) {
|
|
||||||
warn(`Wanted to update "${from}" in ${fileName}, but did not find it.`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (hadUpdates) {
|
|
||||||
fs.writeFileSync(fileName, contents);
|
|
||||||
} else {
|
|
||||||
console.log(`${fileName} had already been updated.`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn(`Wanted to update ${fileName} but the file did not exist.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createFile(fileName, contents) {
|
|
||||||
if (fs.existsSync(fileName)) {
|
|
||||||
warn(`Wanted to create ${fileName}, but it already existed. Leaving existing file.`);
|
|
||||||
} else {
|
|
||||||
fs.writeFileSync(fileName, contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDepsToPackageJson() {
|
|
||||||
const pkgJSONPath = path.join(projectRoot, 'package.json');
|
|
||||||
const packageJSON = JSON.parse(fs.readFileSync(pkgJSONPath, 'utf8'));
|
|
||||||
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
|
|
||||||
...(isRollup ? { '@rollup/plugin-typescript': '^6.0.0' } : { 'ts-loader': '^8.0.4' }),
|
|
||||||
'@tsconfig/svelte': '^1.0.10',
|
|
||||||
'@types/compression': '^1.7.0',
|
|
||||||
'@types/node': '^14.11.1',
|
|
||||||
'@types/polka': '^0.5.1',
|
|
||||||
'svelte-check': '^1.0.46',
|
|
||||||
'svelte-preprocess': '^4.3.0',
|
|
||||||
tslib: '^2.0.1',
|
|
||||||
typescript: '^4.0.3'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add script for checking
|
|
||||||
packageJSON.scripts = Object.assign(packageJSON.scripts, {
|
|
||||||
validate: 'svelte-check --ignore src/node_modules/@sapper'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Write the package JSON
|
|
||||||
fs.writeFileSync(pkgJSONPath, JSON.stringify(packageJSON, null, ' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeJsExtensionToTs(dir) {
|
|
||||||
const elements = fs.readdirSync(dir, { withFileTypes: true });
|
|
||||||
|
|
||||||
for (let i = 0; i < elements.length; i++) {
|
|
||||||
if (elements[i].isDirectory()) {
|
|
||||||
changeJsExtensionToTs(path.join(dir, elements[i].name));
|
|
||||||
} else if (elements[i].name.match(/^[^_]((?!json).)*js$/)) {
|
|
||||||
fs.renameSync(path.join(dir, elements[i].name), path.join(dir, elements[i].name).replace('.js', '.ts'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSingleSvelteFile({ view, vars, contextModule }) {
|
|
||||||
replaceInFile(path.join(projectRoot, 'src', `${view}.svelte`), [
|
|
||||||
[/(?:<script)(( .*?)*?)>/gm, (m, attrs) => `<script${attrs}${!attrs.includes('lang="ts"') ? ' lang="ts"' : ''}>`],
|
|
||||||
...(vars ? vars.map(({ name, type }) => [`export let ${name};`, `export let ${name}: ${type};`]) : []),
|
|
||||||
...(contextModule ? contextModule.map(({ js, ts }) => [js, ts]) : [])
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch the *.svelte file to use TS
|
|
||||||
function updateSvelteFiles() {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
view: 'components/Nav',
|
|
||||||
vars: [{ name: 'segment', type: 'string' }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
view: 'routes/_layout',
|
|
||||||
vars: [{ name: 'segment', type: 'string' }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
view: 'routes/_error',
|
|
||||||
vars: [
|
|
||||||
{ name: 'status', type: 'number' },
|
|
||||||
{ name: 'error', type: 'Error' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
view: 'routes/blog/index',
|
|
||||||
vars: [{ name: 'posts', type: '{ slug: string; title: string, html: any }[]' }],
|
|
||||||
contextModule: [
|
|
||||||
{
|
|
||||||
js: '.then(r => r.json())',
|
|
||||||
ts: '.then((r: { json: () => any; }) => r.json())'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
js: '.then(posts => {',
|
|
||||||
ts: '.then((posts: { slug: string; title: string, html: any }[]) => {'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
view: 'routes/blog/[slug]',
|
|
||||||
vars: [{ name: 'post', type: '{ slug: string; title: string, html: any }' }]
|
|
||||||
}
|
|
||||||
].forEach(updateSingleSvelteFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateRollupConfig() {
|
|
||||||
// Edit rollup config
|
|
||||||
replaceInFile(path.join(projectRoot, 'rollup.config.js'), [
|
|
||||||
// Edit imports
|
|
||||||
[
|
|
||||||
/'rollup-plugin-terser';\n(?!import sveltePreprocess)/,
|
|
||||||
`'rollup-plugin-terser';
|
|
||||||
import sveltePreprocess from 'svelte-preprocess';
|
|
||||||
import typescript from '@rollup/plugin-typescript';
|
|
||||||
`
|
|
||||||
],
|
|
||||||
// Edit inputs
|
|
||||||
[
|
|
||||||
/(?<!THIS_IS_UNDEFINED[^\n]*\n\s*)onwarn\(warning\);/,
|
|
||||||
`(warning.code === 'THIS_IS_UNDEFINED') ||\n\tonwarn(warning);`
|
|
||||||
],
|
|
||||||
[/input: config.client.input\(\)(?!\.replace)/, `input: config.client.input().replace(/\\.js$/, '.ts')`],
|
|
||||||
[
|
|
||||||
/input: config.server.input\(\)(?!\.replace)/,
|
|
||||||
`input: { server: config.server.input().server.replace(/\\.js$/, ".ts") }`
|
|
||||||
],
|
|
||||||
[
|
|
||||||
/input: config.serviceworker.input\(\)(?!\.replace)/,
|
|
||||||
`input: config.serviceworker.input().replace(/\\.js$/, '.ts')`
|
|
||||||
],
|
|
||||||
// Add preprocess
|
|
||||||
[/compilerOptions/g, 'preprocess: sveltePreprocess({ sourceMap: dev }),\n\t\t\t\tcompilerOptions'],
|
|
||||||
// Add TypeScript
|
|
||||||
[/commonjs\(\)(?!,\n\s*typescript)/g, 'commonjs(),\n\t\t\ttypescript({ sourceMap: dev })']
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateWebpackConfig() {
|
|
||||||
// Edit webpack config
|
|
||||||
replaceInFile(path.join(projectRoot, 'webpack.config.js'), [
|
|
||||||
// Edit imports
|
|
||||||
[
|
|
||||||
/require\('webpack-modules'\);\n(?!const sveltePreprocess)/,
|
|
||||||
`require('webpack-modules');\nconst sveltePreprocess = require('svelte-preprocess');\n`
|
|
||||||
],
|
|
||||||
// Edit extensions
|
|
||||||
[
|
|
||||||
/\['\.mjs', '\.js', '\.json', '\.svelte', '\.html'\]/,
|
|
||||||
`['.mjs', '.js', '.ts', '.json', '.svelte', '.html']`
|
|
||||||
],
|
|
||||||
// Edit entries
|
|
||||||
[
|
|
||||||
/entry: config\.client\.entry\(\)/,
|
|
||||||
`entry: { main: config.client.entry().main.replace(/\\.js$/, '.ts') }`
|
|
||||||
],
|
|
||||||
[
|
|
||||||
/entry: config\.server\.entry\(\)/,
|
|
||||||
`entry: { server: config.server.entry().server.replace(/\\.js$/, '.ts') }`
|
|
||||||
],
|
|
||||||
[
|
|
||||||
/entry: config\.serviceworker\.entry\(\)/,
|
|
||||||
`entry: { 'service-worker': config.serviceworker.entry()['service-worker'].replace(/\\.js$/, '.ts') }`
|
|
||||||
],
|
|
||||||
[
|
|
||||||
/loader: 'svelte-loader',\n\t\t\t\t\t\toptions: {/g,
|
|
||||||
'loader: \'svelte-loader\',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tpreprocess: sveltePreprocess({ sourceMap: dev }),'
|
|
||||||
],
|
|
||||||
// Add TypeScript rules for client and server
|
|
||||||
[
|
|
||||||
/module: {\n\s*rules: \[\n\s*(?!{\n\s*test: \/\\\.ts\$\/)/g,
|
|
||||||
`module: {\n\t\t\trules: [\n\t\t\t\t{\n\t\t\t\t\ttest: /\\.ts$/,\n\t\t\t\t\tloader: 'ts-loader'\n\t\t\t\t},\n\t\t\t\t`
|
|
||||||
],
|
|
||||||
// Add TypeScript rules for serviceworker
|
|
||||||
[
|
|
||||||
/output: config\.serviceworker\.output\(\),\n\s*(?!module)/,
|
|
||||||
`output: config.serviceworker.output(),\n\t\tmodule: {\n\t\t\trules: [\n\t\t\t\t{\n\t\t\t\t\ttest: /\\.ts$/,\n\t\t\t\t\tloader: 'ts-loader'\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t`
|
|
||||||
],
|
|
||||||
// Edit outputs
|
|
||||||
[
|
|
||||||
/output: config\.serviceworker\.output\(\),\n\s*(?!resolve)/,
|
|
||||||
`output: config.serviceworker.output(),\n\t\tresolve: { extensions: ['.mjs', '.js', '.ts', '.json'] },\n\t\t`
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateServiceWorker() {
|
|
||||||
replaceInFile(path.join(projectRoot, 'src', 'service-worker.ts'), [
|
|
||||||
[`shell.concat(files);`, `(shell as string[]).concat(files as string[]);`],
|
|
||||||
[`self.skipWaiting();`, `((self as any) as ServiceWorkerGlobalScope).skipWaiting();`],
|
|
||||||
[`self.clients.claim();`, `((self as any) as ServiceWorkerGlobalScope).clients.claim();`],
|
|
||||||
[`fetchAndCache(request)`, `fetchAndCache(request: Request)`],
|
|
||||||
[`self.addEventListener('activate', event =>`, `self.addEventListener('activate', (event: ExtendableEvent) =>`],
|
|
||||||
[`self.addEventListener('install', event =>`, `self.addEventListener('install', (event: ExtendableEvent) =>`],
|
|
||||||
[`addEventListener('fetch', event =>`, `addEventListener('fetch', (event: FetchEvent) =>`],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createTsConfig() {
|
|
||||||
const tsconfig = `{
|
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"lib": ["DOM", "ES2017", "WebWorker"]
|
|
||||||
},
|
|
||||||
"include": ["src/**/*", "src/node_modules/**/*"],
|
|
||||||
"exclude": ["node_modules/*", "__sapper__/*", "static/*"]
|
|
||||||
}`;
|
|
||||||
|
|
||||||
createFile(path.join(projectRoot, 'tsconfig.json'), tsconfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds the extension recommendation
|
|
||||||
function configureVsCode() {
|
|
||||||
const dir = path.join(projectRoot, '.vscode');
|
|
||||||
|
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
fs.mkdirSync(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
createFile(path.join(projectRoot, '.vscode', 'extensions.json'), `{"recommendations": ["svelte.svelte-vscode"]}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteThisScript() {
|
|
||||||
fs.unlinkSync(path.join(__filename));
|
|
||||||
|
|
||||||
// Check for Mac's DS_store file, and if it's the only one left remove it
|
|
||||||
const remainingFiles = fs.readdirSync(path.join(__dirname));
|
|
||||||
if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') {
|
|
||||||
fs.unlinkSync(path.join(__dirname, '.DS_store'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the scripts folder is empty
|
|
||||||
if (fs.readdirSync(path.join(__dirname)).length === 0) {
|
|
||||||
// Remove the scripts folder
|
|
||||||
fs.rmdirSync(path.join(__dirname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Adding TypeScript with ${isRollup ? "Rollup" : "webpack" }...`);
|
|
||||||
|
|
||||||
addDepsToPackageJson();
|
|
||||||
|
|
||||||
changeJsExtensionToTs(path.join(projectRoot, 'src'));
|
|
||||||
|
|
||||||
updateSvelteFiles();
|
|
||||||
|
|
||||||
if (isRollup) {
|
|
||||||
updateRollupConfig();
|
|
||||||
} else {
|
|
||||||
updateWebpackConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateServiceWorker();
|
|
||||||
|
|
||||||
createTsConfig();
|
|
||||||
|
|
||||||
configureVsCode();
|
|
||||||
|
|
||||||
// Delete this script, but not during testing
|
|
||||||
if (!argv[2]) {
|
|
||||||
deleteThisScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Converted to TypeScript.');
|
|
||||||
|
|
||||||
if (fs.existsSync(path.join(projectRoot, 'node_modules'))) {
|
|
||||||
console.log(`
|
|
||||||
Next:
|
|
||||||
1. run 'npm install' again to install TypeScript dependencies
|
|
||||||
2. run 'npm run build' for the @sapper imports in your project to work
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Generated by Cargo
|
|
||||||
# will have compiled files and executables
|
|
||||||
/target/
|
|
||||||
WixTools
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "app"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "A Tauri App"
|
|
||||||
authors = ["you"]
|
|
||||||
license = ""
|
|
||||||
repository = ""
|
|
||||||
default-run = "app"
|
|
||||||
edition = "2018"
|
|
||||||
build = "src/build.rs"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
tauri-build = { version = "1.0.0-beta.2" }
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
serde_json = "1.0"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
tauri = { version = "1.0.0-beta.4", features = [] }
|
|
||||||
tokio = "1.4"
|
|
||||||
url = "2.2"
|
|
||||||
|
|
||||||
coconut-interface = { path = "../../../common/coconut-interface" }
|
|
||||||
credentials = { path = "../../../common/credentials" }
|
|
||||||
validator-client = {path = "../../../common/client-libs/validator-client"}
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["custom-protocol"]
|
|
||||||
custom-protocol = ["tauri/custom-protocol"]
|
|
||||||
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB |