Compare commits
395 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6efaa7a493 | |||
| 7a407e592b | |||
| 6d0827a1da | |||
| 3fbd3f9c33 | |||
| 795934df83 | |||
| cbbcdea480 | |||
| 31fe1585d2 | |||
| e70cb4e241 | |||
| 321025f39d | |||
| 43c4905c1c | |||
| ec09d32864 | |||
| 5eaa6a442d | |||
| d2a96f5a88 | |||
| 6c3207c25c | |||
| 29ce0192ee | |||
| b4242d86eb | |||
| 0579eb27bf | |||
| 3985352615 | |||
| 13595cde26 | |||
| d50f2d1bc3 | |||
| 4f597387bb | |||
| ce169320f5 | |||
| 59a58e7bbb | |||
| 19a97e1398 | |||
| e79efb3708 | |||
| fb74b0df0a | |||
| 516f85a2c7 | |||
| d3c9592d7d | |||
| 64c34ac762 | |||
| f5809e1423 | |||
| 231dd71cc7 | |||
| 048b491803 | |||
| 8a2307d6e3 | |||
| e26fcced39 | |||
| 338774895a | |||
| 40e6ef40c2 | |||
| 5f2d1c7e11 | |||
| 34a5292c4a | |||
| 514df81b2c | |||
| 4d83f5a34e | |||
| ea93efd00d | |||
| eb106587df | |||
| e98ef7d12a | |||
| 978b4c53cd | |||
| 345df90d2e | |||
| 7f8830f894 | |||
| 1918bcf5ba | |||
| 9e4e8a9b2b | |||
| 077a64b076 | |||
| d3fad05a09 | |||
| 5c937d2a67 | |||
| b403c68a15 | |||
| 65309170b4 | |||
| d41d26f5ac | |||
| 56ebf001aa | |||
| 44687f31ef | |||
| 5c4987cd75 | |||
| 4d30f522b7 | |||
| 26984b619c | |||
| 8cfa4ddc12 | |||
| 387c0698aa | |||
| 4b1a78f6ec | |||
| 31dd960d47 | |||
| 8ec4159532 | |||
| 491d424fd6 | |||
| 20b70bf0f9 | |||
| 97469ebe5f | |||
| d2943d0099 | |||
| 6717afc4d9 | |||
| 3e9d214679 | |||
| 63216fc1d0 | |||
| 84846db9a6 | |||
| 8e442ebed9 | |||
| 50a4b0a755 | |||
| 94a1bc9515 | |||
| bd227d3f51 | |||
| 6318708239 | |||
| 3984fcc804 | |||
| bd008c24ad | |||
| d8c59f4d38 | |||
| 88a3cf2094 | |||
| b74d2447a8 | |||
| ee5eb6042d | |||
| 3aa6462ead | |||
| fd8d226d68 | |||
| 5edb1dd3b0 | |||
| 7c236b2f86 | |||
| 5a082b4170 | |||
| 8cff6e5a73 | |||
| f875b38c87 | |||
| 86621d0b94 | |||
| ea5ec0733c | |||
| 98ccf9e37f | |||
| 3fd74fb590 | |||
| 4d72d72eb0 | |||
| 81b891a21c | |||
| d2c42ab7c6 | |||
| 2e71a442cd | |||
| 9fae4f26a1 | |||
| 1b757a806c | |||
| ce6e40a148 | |||
| 9244413539 | |||
| a554125187 | |||
| 035080cd3b | |||
| 9fc04bd8bc | |||
| f406e1d266 | |||
| 334e99538b | |||
| 9f77ff4d82 | |||
| afa64decc2 | |||
| 04bc42e333 | |||
| 02c5fe2b87 | |||
| defc43a50b | |||
| 9235777426 | |||
| c936e24e70 | |||
| aa4fcc90ec | |||
| 1d289c7c25 | |||
| acee708a66 | |||
| af819ab8e5 | |||
| a811c06295 | |||
| 13616ed992 | |||
| 44d6529adf | |||
| c2c775bd5b | |||
| 014e21f3ef | |||
| 2e90cb1ffc | |||
| 168da8afc4 | |||
| bb38ad62bf | |||
| 387ea3b52e | |||
| 796ae70e50 | |||
| 7beca33673 | |||
| c76bc49abf | |||
| ef32b0e543 | |||
| 0f6f0f3ca7 | |||
| 1f134a9fac | |||
| de4f813de8 | |||
| 390c14a547 | |||
| 4d592ac026 | |||
| 75c7c587dd | |||
| 29ae23bc93 | |||
| 7b78644527 | |||
| c30fdcbe23 | |||
| c3b465725a | |||
| cc2b787cd3 | |||
| 406293d781 | |||
| 5334ff7fc4 | |||
| 1288d4bbcd | |||
| 7c359e29f1 | |||
| 2a5bb6e1a1 | |||
| 91c1c2d43e | |||
| 93c189fcb0 | |||
| b7c64f290f | |||
| fddf1aee28 | |||
| 22c0d8a104 | |||
| 057e9cdcf8 | |||
| bc4d2f70ab | |||
| 0300c6d2d3 | |||
| 19e6554c22 | |||
| ee4f5da834 | |||
| 09b9866bf0 | |||
| b088699dfe | |||
| 909c681555 | |||
| f89c69ae33 | |||
| e84c9b2c8f | |||
| 99a0f159d7 | |||
| 7c0a45ed52 | |||
| 33c30624d2 | |||
| 0fecc56879 | |||
| 7ea009173b | |||
| 571b83d74d | |||
| 74538ac652 | |||
| a5844a461b | |||
| 03ec6b87a8 | |||
| 590acef2af | |||
| c1ad831426 | |||
| 900ea92724 | |||
| f753de780a | |||
| 139a9fdce2 | |||
| fde4492b0b | |||
| 4ec4893552 | |||
| 8506d07428 | |||
| b644afaa67 | |||
| 87260a422b | |||
| 6475282ebc | |||
| 7fdba349ab | |||
| fb77d06ea5 | |||
| 6d3b184ca3 | |||
| d02b0229fc | |||
| 7eb5f7c2b0 | |||
| a18d270d03 | |||
| b2f6836756 | |||
| 07f03f5239 | |||
| aac1b4361e | |||
| 87e429d78a | |||
| da48afc092 | |||
| 9e421024f1 | |||
| 9691b03c87 | |||
| 7ea7b9e482 | |||
| d0fe0a6468 | |||
| a5169ab1b4 | |||
| 7180292c0a | |||
| 68ffc797a7 | |||
| 6a70193bdf | |||
| 4178809555 | |||
| be082f5ed2 | |||
| 6d5755ca1f | |||
| 3efb7531ac | |||
| 9c949988e2 | |||
| 9de5d7213a | |||
| 94eb362a71 | |||
| 327ad7982e | |||
| 0f615f48f2 | |||
| d511611641 | |||
| 17d3ff2d77 | |||
| 43855209e8 | |||
| bf8f109602 | |||
| dd3dcfa7fe | |||
| 653a7fd900 | |||
| 86ea2d23cb | |||
| 42a37442e8 | |||
| 69eec1d3a1 | |||
| 6b24f081e1 | |||
| 6e5d0dac1b | |||
| f0b6a2d7e1 | |||
| 792931d77c | |||
| 9b64fc7755 | |||
| 231d94b6d4 | |||
| a29b0eecea | |||
| a4f3cf9c7e | |||
| 645f9f976b | |||
| 5f2740bf66 | |||
| ecb15034d3 | |||
| bd49c222a3 | |||
| df5ceec522 | |||
| b2d8e45e7e | |||
| fb3878389d | |||
| 0d397ab5cc | |||
| f637debdcc | |||
| bc00bdcbc3 | |||
| b943fd4768 | |||
| ff2279358a | |||
| e8f34bcca8 | |||
| 2e11971780 | |||
| 3c6a879061 | |||
| 0d3d939d55 | |||
| 6ba80c0c06 | |||
| bc7993f440 | |||
| 31d23b88f2 | |||
| 9aed938c79 | |||
| ea8610623f | |||
| 9b9920a27c | |||
| f9bb522885 | |||
| 884d9440f2 | |||
| f6a547e5c2 | |||
| 0956bbee90 | |||
| 595bfd8073 | |||
| d4e9441de9 | |||
| d44a40c186 | |||
| 0d47fe01fb | |||
| aa86bf0ee3 | |||
| bd79fb1200 | |||
| 11a3bee257 | |||
| 50ac19a4f5 | |||
| 961a81312d | |||
| cb56dd1fe2 | |||
| e9871f6bd5 | |||
| 06c3215211 | |||
| 0221d45aff | |||
| adb7e4fb60 | |||
| d0d6e38b02 | |||
| e736025d6d | |||
| dc0f46c11c | |||
| beab341f55 | |||
| 3d6803928b | |||
| 306cfaf0c5 | |||
| f67c184458 | |||
| 79ddcb3b35 | |||
| fe49d38aea | |||
| feda01f1cc | |||
| c212412b90 | |||
| 1e4b360c6d | |||
| d66f253e8b | |||
| 80fc25a3c0 | |||
| ba4c65c558 | |||
| aba10e6a59 | |||
| f1ac0530a3 | |||
| 2f5aed0354 | |||
| bde87587f2 | |||
| f37519942e | |||
| 93ed710fba | |||
| f06fe4d36c | |||
| 626f074229 | |||
| 78ea2eb9c4 | |||
| 6a0725130b | |||
| 74e949a4cb | |||
| 325b7ef93a | |||
| 2502e2f8c3 | |||
| 732ba41179 | |||
| dcfd830407 | |||
| 4626c999f8 | |||
| 5aac04ac01 | |||
| 0d7fcf34d9 | |||
| dc804c1235 | |||
| f4a416c478 | |||
| 9639f08db6 | |||
| 6ec3e3931b | |||
| bfeec4980d | |||
| 11c1a7c515 | |||
| 5b52e775d8 | |||
| 88c7009e88 | |||
| 50494ea1e5 | |||
| ecf3c4c3ac | |||
| 39b4d6a9a2 | |||
| 2ca034be1c | |||
| c116b75f33 | |||
| e904c58e6e | |||
| ce02c858a5 | |||
| 7116c5a85d | |||
| 9b87a06238 | |||
| 02fe3f1c5f | |||
| e2d7df8bf0 | |||
| 5c980b03b6 | |||
| 7dc7250499 | |||
| 86f91eff29 | |||
| f45e87a848 | |||
| 46dc3284ee | |||
| ea11eb5a1f | |||
| ecd3ace897 | |||
| 990f5a81f4 | |||
| d87607787f | |||
| d6fc3fe51f | |||
| ec89954d3e | |||
| 5b6108ec80 | |||
| ccb44ee6ff | |||
| e155d293fc | |||
| c3f48debdf | |||
| a7a11ac3a5 | |||
| 1ed824ab55 | |||
| 7f9da13e51 | |||
| c26fe1977b | |||
| a039f2e73d | |||
| c45492cdc8 | |||
| fb3a7aed6b | |||
| 920c1f8855 | |||
| 3f2b57d4a6 | |||
| dee15b2f24 | |||
| 1da0b34c45 | |||
| 67adcce9a4 | |||
| 6fc68c92d0 | |||
| e3885b9fe6 | |||
| fb8b4f82db | |||
| 40a44028d4 | |||
| 8a26830ea2 | |||
| 997c75cfff | |||
| 627ed95aa4 | |||
| deee4ecce7 | |||
| 5f43bb7671 | |||
| b41f0e9b8a | |||
| f8a224787d | |||
| 47c3287226 | |||
| a4914061e0 | |||
| 3feaf98397 | |||
| af24d776c0 | |||
| 2b303d2bdd | |||
| 5409fe0ec2 | |||
| 601863419b | |||
| 89848ec91b | |||
| b181f96d1b | |||
| 80e58678a0 | |||
| 396248be8e | |||
| 665bb60d91 | |||
| deb0ef381e | |||
| 9f945e9d10 | |||
| ae7f908b8a | |||
| 6e3331cb13 | |||
| 103523d20a | |||
| d40115fe0f | |||
| 3b2e753f91 | |||
| 134f0909cd | |||
| 5e3259c787 | |||
| 7cbff7ce8d | |||
| f5a9b43c4c | |||
| 2eb53ef55a | |||
| 280283e41a | |||
| 07d10c35b6 | |||
| 0ab2a589a6 | |||
| bc849c7c46 | |||
| f94f3b1a1d | |||
| c3bcb96bad | |||
| 9b6816e265 | |||
| 68223000ea | |||
| 9f5e153ddb | |||
| cf87ced120 | |||
| 7560837f01 | |||
| 16b9bcb91d | |||
| 07e946a195 | |||
| 648223a235 |
@@ -19,7 +19,7 @@ jobs:
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
- name: Build
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
- "nym-connect/desktop/package.json"
|
||||
- "nym-wallet/src/**"
|
||||
- "nym-wallet/package.json"
|
||||
- "explorer/**"
|
||||
- "explorer-nextjs/src/**"
|
||||
- ".github/workflows/ci-lint-typescript.yml"
|
||||
|
||||
jobs:
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
@@ -37,12 +37,12 @@ jobs:
|
||||
- name: Install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '116'
|
||||
version: "116"
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: "1.20"
|
||||
|
||||
- name: Install
|
||||
run: yarn
|
||||
|
||||
@@ -4,8 +4,8 @@ on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'explorer/**'
|
||||
- '.github/workflows/ci-nym-network-explorer.yml'
|
||||
- "explorer/**"
|
||||
- ".github/workflows/ci-nym-network-explorer.yml"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -15,78 +15,78 @@ jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
continue-on-error: true
|
||||
- name: Build shared packages
|
||||
run: cd .. && yarn && yarn build
|
||||
- name: Set environment from the example
|
||||
run: cp .env.prod .env
|
||||
# - run: yarn test
|
||||
# continue-on-error: true
|
||||
- run: yarn && yarn build
|
||||
continue-on-error: true
|
||||
- run: yarn storybook:build
|
||||
name: Build storybook
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/dist/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/network-explorer-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Deploy storybook to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ne-sb-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: network-explorer
|
||||
NYM_PROJECT_NAME: "Network Explorer"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "network-explorer-${{ env.GITHUB_REF_SLUG }}"
|
||||
NYM_CI_WWW_LOCATION_STORYBOOK: "ne-sb-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
- name: Deploy
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CD_PROD_NE_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/dist/"
|
||||
REMOTE_HOST: ${{ secrets.CD_PROD_NE_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CD_PROD_NE_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CD_PROD_NE_REMOTE_TARGET }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
continue-on-error: true
|
||||
- name: Build shared packages
|
||||
run: cd .. && yarn && yarn build
|
||||
- name: Set environment from the example
|
||||
run: cp .env.prod .env
|
||||
# - run: yarn test
|
||||
# continue-on-error: true
|
||||
- run: yarn && yarn build
|
||||
continue-on-error: true
|
||||
- run: yarn storybook:build
|
||||
name: Build storybook
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/dist/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/network-explorer-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Deploy storybook to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/ne-sb-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: network-explorer
|
||||
NYM_PROJECT_NAME: "Network Explorer"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "network-explorer-${{ env.GITHUB_REF_SLUG }}"
|
||||
NYM_CI_WWW_LOCATION_STORYBOOK: "ne-sb-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
- name: Deploy
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CD_PROD_NE_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/dist/"
|
||||
REMOTE_HOST: ${{ secrets.CD_PROD_NE_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CD_PROD_NE_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CD_PROD_NE_REMOTE_TARGET }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
@@ -322,7 +322,7 @@ serde_with = "3.9.0"
|
||||
serde_yaml = "0.9.25"
|
||||
sha2 = "0.10.8"
|
||||
si-scale = "0.2.3"
|
||||
sphinx-packet = "0.1.1"
|
||||
sphinx-packet = "0.3.1"
|
||||
sqlx = "0.7.4"
|
||||
strum = "0.26"
|
||||
strum_macros = "0.26"
|
||||
@@ -330,7 +330,7 @@ subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.33.0"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.43"
|
||||
tar = "0.4.44"
|
||||
tempfile = "3.15"
|
||||
thiserror = "2.0"
|
||||
time = "0.3.37"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.49"
|
||||
version = "1.1.48"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.49"
|
||||
version = "1.1.48"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -105,24 +105,26 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
async fn get_aggregate_verification_key(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
ecash_apis: &mut ApiClientsWrapper<'_, C>,
|
||||
apis: &mut ApiClientsWrapper,
|
||||
) -> Result<VerificationKeyAuth, BandwidthControllerError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
|
||||
get_aggregate_verification_key(&self.storage, epoch_id, ecash_apis).await
|
||||
}
|
||||
|
||||
async fn get_coin_index_signatures(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
ecash_apis: &mut ApiClientsWrapper<'_, C>,
|
||||
apis: &mut ApiClientsWrapper,
|
||||
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
|
||||
get_coin_index_signatures(&self.storage, epoch_id, ecash_apis).await
|
||||
}
|
||||
|
||||
@@ -130,12 +132,13 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
expiration_date: Date,
|
||||
ecash_apis: &mut ApiClientsWrapper<'_, C>,
|
||||
apis: &mut ApiClientsWrapper,
|
||||
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
let ecash_apis = apis.get_or_init(epoch_id, &self.client).await?;
|
||||
get_expiration_date_signatures(&self.storage, epoch_id, expiration_date, ecash_apis).await
|
||||
}
|
||||
|
||||
@@ -151,7 +154,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
{
|
||||
let epoch_id = retrieved_ticketbook.ticketbook.epoch_id();
|
||||
let expiration_date = retrieved_ticketbook.ticketbook.expiration_date();
|
||||
let mut api_clients = ApiClientsWrapper::new(&self.client, epoch_id);
|
||||
let mut api_clients = Default::default();
|
||||
|
||||
let verification_key = self
|
||||
.get_aggregate_verification_key(epoch_id, &mut api_clients)
|
||||
|
||||
@@ -21,67 +21,30 @@ use rand::thread_rng;
|
||||
use std::fmt::Display;
|
||||
use std::future::Future;
|
||||
|
||||
pub(crate) trait EcashClientsProvider {
|
||||
async fn try_get_ecash_clients(
|
||||
&mut self,
|
||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>;
|
||||
}
|
||||
// it really doesn't need the RwLock because it's never moved across tasks,
|
||||
// but we need all the Send/Sync action
|
||||
#[derive(Default)]
|
||||
pub(crate) struct ApiClientsWrapper(Option<Vec<EcashApiClient>>);
|
||||
|
||||
impl EcashClientsProvider for Vec<EcashApiClient> {
|
||||
async fn try_get_ecash_clients(
|
||||
impl ApiClientsWrapper {
|
||||
pub(crate) async fn get_or_init<C>(
|
||||
&mut self,
|
||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError> {
|
||||
Ok(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> EcashClientsProvider for &mut ApiClientsWrapper<'_, C>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
{
|
||||
async fn try_get_ecash_clients(
|
||||
&mut self,
|
||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError> {
|
||||
self.clients().await
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum ApiClientsWrapper<'a, C> {
|
||||
Uninitialised {
|
||||
query_client: &'a C,
|
||||
epoch_id: EpochId,
|
||||
},
|
||||
Cached {
|
||||
clients: Vec<EcashApiClient>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, C> ApiClientsWrapper<'a, C> {
|
||||
pub(crate) fn new(query_client: &'a C, epoch_id: EpochId) -> Self {
|
||||
ApiClientsWrapper::Uninitialised {
|
||||
query_client,
|
||||
epoch_id,
|
||||
}
|
||||
}
|
||||
|
||||
async fn clients(&mut self) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
|
||||
dkg_client: &C,
|
||||
) -> Result<Vec<EcashApiClient>, BandwidthControllerError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
{
|
||||
match self {
|
||||
ApiClientsWrapper::Uninitialised {
|
||||
query_client,
|
||||
epoch_id,
|
||||
} => {
|
||||
let clients = all_ecash_api_clients(*query_client, *epoch_id).await?;
|
||||
*self = ApiClientsWrapper::Cached {
|
||||
clients: clients.clone(),
|
||||
};
|
||||
|
||||
Ok(clients)
|
||||
}
|
||||
ApiClientsWrapper::Cached { clients } => Ok(clients.clone()),
|
||||
if let Some(cached) = &self.0 {
|
||||
return Ok(cached.clone());
|
||||
}
|
||||
|
||||
let clients = all_ecash_api_clients(dkg_client, epoch_id).await?;
|
||||
|
||||
// technically we don't have to be cloning all the clients here, but it's way simpler than
|
||||
// dealing with locking and whatnot given the performance penalty is negligible
|
||||
self.0 = Some(clients.clone());
|
||||
Ok(clients)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +76,7 @@ where
|
||||
pub(crate) async fn get_aggregate_verification_key<St>(
|
||||
storage: &St,
|
||||
epoch_id: EpochId,
|
||||
mut ecash_apis: impl EcashClientsProvider,
|
||||
ecash_apis: Vec<EcashApiClient>,
|
||||
) -> Result<VerificationKeyAuth, BandwidthControllerError>
|
||||
where
|
||||
St: Storage,
|
||||
@@ -127,8 +90,6 @@ where
|
||||
return Ok(stored);
|
||||
};
|
||||
|
||||
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
|
||||
|
||||
let master_vk = query_random_apis_until_success(
|
||||
ecash_apis,
|
||||
|api| async move { api.api_client.master_verification_key(Some(epoch_id)).await },
|
||||
@@ -154,7 +115,7 @@ where
|
||||
pub(crate) async fn get_coin_index_signatures<St>(
|
||||
storage: &St,
|
||||
epoch_id: EpochId,
|
||||
mut ecash_apis: impl EcashClientsProvider,
|
||||
ecash_apis: Vec<EcashApiClient>,
|
||||
) -> Result<Vec<AnnotatedCoinIndexSignature>, BandwidthControllerError>
|
||||
where
|
||||
St: Storage,
|
||||
@@ -168,8 +129,6 @@ where
|
||||
return Ok(stored);
|
||||
};
|
||||
|
||||
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
|
||||
|
||||
let index_sigs = query_random_apis_until_success(
|
||||
ecash_apis,
|
||||
|api| async move {
|
||||
@@ -200,7 +159,7 @@ pub(crate) async fn get_expiration_date_signatures<St>(
|
||||
storage: &St,
|
||||
epoch_id: EpochId,
|
||||
expiration_date: Date,
|
||||
mut ecash_apis: impl EcashClientsProvider,
|
||||
ecash_apis: Vec<EcashApiClient>,
|
||||
) -> Result<Vec<AnnotatedExpirationDateSignature>, BandwidthControllerError>
|
||||
where
|
||||
St: Storage,
|
||||
@@ -214,8 +173,6 @@ where
|
||||
return Ok(stored);
|
||||
};
|
||||
|
||||
let ecash_apis = ecash_apis.try_get_ecash_clients().await?;
|
||||
|
||||
let expiration_sigs = query_random_apis_until_success(
|
||||
ecash_apis,
|
||||
|api| async move {
|
||||
|
||||
@@ -37,11 +37,10 @@ nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["sphinx"]
|
||||
default = []
|
||||
aead = ["dep:aead", "aead/std", "aes-gcm-siv", "generic-array"]
|
||||
serde = ["dep:serde", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"]
|
||||
asymmetric = ["x25519-dalek", "ed25519-dalek", "zeroize"]
|
||||
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array", "sha2"]
|
||||
stream_cipher = ["aes", "ctr", "cipher", "generic-array"]
|
||||
sphinx = ["nym-sphinx-types/sphinx"]
|
||||
outfox = ["nym-sphinx-types/outfox"]
|
||||
sphinx = ["nym-sphinx-types/sphinx"]
|
||||
@@ -202,6 +202,18 @@ impl PemStorableKey for PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<x25519_dalek::PublicKey> for PublicKey {
|
||||
fn from(public_key: x25519_dalek::PublicKey) -> Self {
|
||||
PublicKey(public_key)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PublicKey> for x25519_dalek::PublicKey {
|
||||
fn from(public_key: PublicKey) -> Self {
|
||||
public_key.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||
pub struct PrivateKey(x25519_dalek::StaticSecret);
|
||||
|
||||
@@ -308,109 +320,15 @@ impl PemStorableKey for PrivateKey {
|
||||
}
|
||||
}
|
||||
|
||||
// compatibility with sphinx keys:
|
||||
#[cfg(feature = "sphinx")]
|
||||
impl From<PublicKey> for nym_sphinx_types::PublicKey {
|
||||
fn from(key: PublicKey) -> Self {
|
||||
nym_sphinx_types::PublicKey::from(key.to_bytes())
|
||||
impl From<x25519_dalek::StaticSecret> for PrivateKey {
|
||||
fn from(secret: x25519_dalek::StaticSecret) -> Self {
|
||||
PrivateKey(secret)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
impl<'a> From<&'a PublicKey> for nym_sphinx_types::PublicKey {
|
||||
fn from(key: &'a PublicKey) -> Self {
|
||||
nym_sphinx_types::PublicKey::from((*key).to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
impl From<nym_sphinx_types::PublicKey> for PublicKey {
|
||||
fn from(pub_key: nym_sphinx_types::PublicKey) -> Self {
|
||||
Self(x25519_dalek::PublicKey::from(*pub_key.as_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
impl From<PrivateKey> for nym_sphinx_types::PrivateKey {
|
||||
fn from(key: PrivateKey) -> Self {
|
||||
nym_sphinx_types::PrivateKey::from(key.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
impl<'a> From<&'a PrivateKey> for nym_sphinx_types::PrivateKey {
|
||||
fn from(key: &'a PrivateKey) -> Self {
|
||||
nym_sphinx_types::PrivateKey::from(key.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
impl From<nym_sphinx_types::PrivateKey> for PrivateKey {
|
||||
fn from(private_key: nym_sphinx_types::PrivateKey) -> Self {
|
||||
let private_key_bytes = private_key.to_bytes();
|
||||
assert_eq!(private_key_bytes.len(), PRIVATE_KEY_SIZE);
|
||||
Self::from_bytes(&private_key_bytes).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod sphinx_key_conversion {
|
||||
use super::*;
|
||||
use rand_chacha::rand_core::SeedableRng;
|
||||
use rand_chacha::ChaCha20Rng;
|
||||
|
||||
pub(super) fn test_rng() -> ChaCha20Rng {
|
||||
let dummy_seed = [42u8; 32];
|
||||
ChaCha20Rng::from_seed(dummy_seed)
|
||||
}
|
||||
|
||||
const NUM_ITERATIONS: usize = 100;
|
||||
|
||||
#[test]
|
||||
fn works_for_forward_conversion() {
|
||||
let mut rng = test_rng();
|
||||
|
||||
for _ in 0..NUM_ITERATIONS {
|
||||
let keys = KeyPair::new(&mut rng);
|
||||
let private = &keys.private_key;
|
||||
let public = &keys.public_key;
|
||||
|
||||
let dummy_remote = KeyPair::new(&mut rng);
|
||||
let dh1 = private.diffie_hellman(&dummy_remote.public_key);
|
||||
|
||||
let public_bytes = public.to_bytes();
|
||||
|
||||
let sphinx_private: nym_sphinx_types::PrivateKey = private.into();
|
||||
let recovered_private = PrivateKey::from(sphinx_private);
|
||||
|
||||
let dh2 = recovered_private.diffie_hellman(&dummy_remote.public_key);
|
||||
|
||||
let sphinx_public: nym_sphinx_types::PublicKey = public.into();
|
||||
let recovered_public = PublicKey::from(sphinx_public);
|
||||
assert_eq!(public_bytes, recovered_public.to_bytes());
|
||||
|
||||
// even though the byte representation of the private key changed, the resultant DH is the same
|
||||
// which is what matters
|
||||
assert_eq!(dh1, dh2);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn works_for_backward_conversion() {
|
||||
for _ in 0..NUM_ITERATIONS {
|
||||
let (sphinx_private, sphinx_public) = nym_sphinx_types::crypto::keygen();
|
||||
|
||||
let private_bytes = sphinx_private.to_bytes();
|
||||
let public_bytes = sphinx_public.as_bytes();
|
||||
|
||||
let private: PrivateKey = sphinx_private.into();
|
||||
let recovered_sphinx_private: nym_sphinx_types::PrivateKey = private.into();
|
||||
|
||||
let public: PublicKey = sphinx_public.into();
|
||||
let recovered_sphinx_public: nym_sphinx_types::PublicKey = public.into();
|
||||
assert_eq!(private_bytes, recovered_sphinx_private.to_bytes());
|
||||
assert_eq!(public_bytes, recovered_sphinx_public.as_bytes());
|
||||
}
|
||||
impl AsRef<x25519_dalek::StaticSecret> for PrivateKey {
|
||||
fn as_ref(&self) -> &x25519_dalek::StaticSecret {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ mime = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
serde_yaml = { workspace = true }
|
||||
subtle.workspace = true
|
||||
tower = { workspace = true }
|
||||
tracing.workspace = true
|
||||
utoipa = { workspace = true, optional = true }
|
||||
|
||||
@@ -7,6 +7,7 @@ use axum::{extract::Request, response::Response};
|
||||
use futures::future::BoxFuture;
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
use subtle::ConstantTimeEq;
|
||||
use tower::{Layer, Service};
|
||||
use tracing::{debug, instrument, trace};
|
||||
use zeroize::Zeroizing;
|
||||
@@ -76,7 +77,7 @@ impl<S> RequireAuth<S> {
|
||||
return Err("`Authorization` header must contain non-empty `Bearer` token");
|
||||
}
|
||||
|
||||
if self.bearer_token.as_str() != bearer_token {
|
||||
if bool::from(self.bearer_token.as_bytes().ct_ne(bearer_token.as_bytes())) {
|
||||
return Err("`Authorization` header does not contain the correct `Bearer` token");
|
||||
}
|
||||
|
||||
|
||||
@@ -48,12 +48,10 @@ features = ["sync"]
|
||||
[features]
|
||||
default = ["sphinx"]
|
||||
sphinx = [
|
||||
"nym-crypto/sphinx",
|
||||
"nym-sphinx-params/sphinx",
|
||||
"nym-sphinx-types/sphinx",
|
||||
]
|
||||
outfox = [
|
||||
"nym-crypto/outfox",
|
||||
"nym-sphinx-params/outfox",
|
||||
"nym-sphinx-types/outfox",
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@ license = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
nym-crypto = { path = "../../crypto", features = ["asymmetric"] } # all addresses are expressed in terms on their crypto keys
|
||||
nym-crypto = { path = "../../crypto", features = ["asymmetric", "sphinx"] } # all addresses are expressed in terms on their crypto keys
|
||||
nym-sphinx-types = { path = "../types", features = ["sphinx"] } # we need to be able to refer to some types defined inside sphinx crate
|
||||
serde = { workspace = true } # implementing serialization/deserialization for some types, like `Recipient`
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -559,7 +559,7 @@ mod tests {
|
||||
let mut address_bytes = [0; NODE_ADDRESS_LENGTH];
|
||||
rng.fill_bytes(&mut address_bytes);
|
||||
|
||||
let dummy_private = PrivateKey::new_with_rng(rng);
|
||||
let dummy_private = PrivateKey::random_from_rng(rng);
|
||||
let pub_key = (&dummy_private).into();
|
||||
Node {
|
||||
address: NodeAddressBytes::from_bytes(address_bytes),
|
||||
|
||||
@@ -130,28 +130,33 @@ impl Decoder for NymCodec {
|
||||
mod packet_encoding {
|
||||
use super::*;
|
||||
use nym_sphinx_types::{
|
||||
crypto, Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes,
|
||||
DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
|
||||
Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes,
|
||||
PrivateKey, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH,
|
||||
};
|
||||
|
||||
fn random_pubkey() -> nym_sphinx_types::PublicKey {
|
||||
let private_key = PrivateKey::random();
|
||||
(&private_key).into()
|
||||
}
|
||||
|
||||
fn make_valid_outfox_packet(size: PacketSize) -> NymPacket {
|
||||
let (_, node1_pk) = crypto::keygen();
|
||||
let node1_pk = random_pubkey();
|
||||
let node1 = Node::new(
|
||||
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
|
||||
node1_pk,
|
||||
);
|
||||
let (_, node2_pk) = crypto::keygen();
|
||||
let node2_pk = random_pubkey();
|
||||
let node2 = Node::new(
|
||||
NodeAddressBytes::from_bytes([4u8; NODE_ADDRESS_LENGTH]),
|
||||
node2_pk,
|
||||
);
|
||||
let (_, node3_pk) = crypto::keygen();
|
||||
let node3_pk = random_pubkey();
|
||||
let node3 = Node::new(
|
||||
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
|
||||
node3_pk,
|
||||
);
|
||||
|
||||
let (_, node4_pk) = crypto::keygen();
|
||||
let node4_pk = random_pubkey();
|
||||
let node4 = Node::new(
|
||||
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
|
||||
node4_pk,
|
||||
@@ -170,17 +175,17 @@ mod packet_encoding {
|
||||
}
|
||||
|
||||
fn make_valid_sphinx_packet(size: PacketSize) -> NymPacket {
|
||||
let (_, node1_pk) = crypto::keygen();
|
||||
let node1_pk = random_pubkey();
|
||||
let node1 = Node::new(
|
||||
NodeAddressBytes::from_bytes([5u8; NODE_ADDRESS_LENGTH]),
|
||||
node1_pk,
|
||||
);
|
||||
let (_, node2_pk) = crypto::keygen();
|
||||
let node2_pk = random_pubkey();
|
||||
let node2 = Node::new(
|
||||
NodeAddressBytes::from_bytes([4u8; NODE_ADDRESS_LENGTH]),
|
||||
node2_pk,
|
||||
);
|
||||
let (_, node3_pk) = crypto::keygen();
|
||||
let node3_pk = random_pubkey();
|
||||
let node3 = Node::new(
|
||||
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
|
||||
node3_pk,
|
||||
|
||||
@@ -4,8 +4,10 @@ use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressE
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use nym_sphinx_types::{
|
||||
Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, NymPacket, NymPacketError,
|
||||
NymProcessedPacket, OutfoxError, PrivateKey, ProcessedPacket, SphinxError,
|
||||
NymProcessedPacket, OutfoxError, PrivateKey, ProcessedPacketData, SphinxError,
|
||||
Version as SphinxPacketVersion,
|
||||
};
|
||||
use std::fmt::Display;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::packet::FramedNymPacket;
|
||||
@@ -13,12 +15,38 @@ use nym_metrics::nanos;
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MixProcessingResult {
|
||||
pub enum MixProcessingResultData {
|
||||
/// Contains unwrapped data that should first get delayed before being sent to next hop.
|
||||
ForwardHop(MixPacket, Option<SphinxDelay>),
|
||||
ForwardHop {
|
||||
packet: MixPacket,
|
||||
delay: Option<SphinxDelay>,
|
||||
},
|
||||
|
||||
/// Contains all data extracted out of the final hop packet that could be forwarded to the destination.
|
||||
FinalHop(ProcessedFinalHop),
|
||||
FinalHop { final_hop_data: ProcessedFinalHop },
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum MixPacketVersion {
|
||||
Outfox,
|
||||
Sphinx(SphinxPacketVersion),
|
||||
}
|
||||
|
||||
impl Display for MixPacketVersion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
MixPacketVersion::Outfox => "outfox".fmt(f),
|
||||
MixPacketVersion::Sphinx(sphinx_version) => {
|
||||
write!(f, "sphinx-{}", sphinx_version.value())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MixProcessingResult {
|
||||
pub packet_version: MixPacketVersion,
|
||||
pub processing_data: MixProcessingResultData,
|
||||
}
|
||||
|
||||
type ForwardAck = MixPacket;
|
||||
@@ -107,37 +135,63 @@ fn perform_final_processing(
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
match packet {
|
||||
NymProcessedPacket::Sphinx(packet) => {
|
||||
match packet {
|
||||
ProcessedPacket::ForwardHop(packet, address, delay) => {
|
||||
process_forward_hop(NymPacket::Sphinx(*packet), address, delay, packet_type)
|
||||
}
|
||||
let processing_data = match packet.data {
|
||||
ProcessedPacketData::ForwardHop {
|
||||
next_hop_packet,
|
||||
next_hop_address,
|
||||
delay,
|
||||
} => process_forward_hop(
|
||||
NymPacket::Sphinx(next_hop_packet),
|
||||
next_hop_address,
|
||||
delay,
|
||||
packet_type,
|
||||
),
|
||||
// right now there's no use for the surb_id included in the header - probably it should get removed from the
|
||||
// sphinx all together?
|
||||
ProcessedPacket::FinalHop(destination, _, payload) => process_final_hop(
|
||||
ProcessedPacketData::FinalHop {
|
||||
destination,
|
||||
identifier: _,
|
||||
payload,
|
||||
} => process_final_hop(
|
||||
destination,
|
||||
payload.recover_plaintext()?,
|
||||
packet_size,
|
||||
packet_type,
|
||||
),
|
||||
}
|
||||
}?;
|
||||
|
||||
Ok(MixProcessingResult {
|
||||
packet_version: MixPacketVersion::Sphinx(packet.version),
|
||||
processing_data,
|
||||
})
|
||||
}
|
||||
NymProcessedPacket::Outfox(packet) => {
|
||||
let next_address = *packet.next_address();
|
||||
let packet = packet.into_packet();
|
||||
if packet.is_final_hop() {
|
||||
process_final_hop(
|
||||
let processing_data = process_final_hop(
|
||||
DestinationAddressBytes::from_bytes(next_address),
|
||||
packet.recover_plaintext()?.to_vec(),
|
||||
packet_size,
|
||||
packet_type,
|
||||
)
|
||||
)?;
|
||||
Ok(MixProcessingResult {
|
||||
packet_version: MixPacketVersion::Outfox,
|
||||
processing_data,
|
||||
})
|
||||
} else {
|
||||
let mix_packet = MixPacket::new(
|
||||
let packet = MixPacket::new(
|
||||
NymNodeRoutingAddress::try_from_bytes(&next_address)?,
|
||||
NymPacket::Outfox(packet),
|
||||
PacketType::Outfox,
|
||||
);
|
||||
Ok(MixProcessingResult::ForwardHop(mix_packet, None))
|
||||
Ok(MixProcessingResult {
|
||||
packet_version: MixPacketVersion::Outfox,
|
||||
processing_data: MixProcessingResultData::ForwardHop {
|
||||
packet,
|
||||
delay: None,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,14 +202,16 @@ fn process_final_hop(
|
||||
payload: Vec<u8>,
|
||||
packet_size: PacketSize,
|
||||
packet_type: PacketType,
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
) -> Result<MixProcessingResultData, PacketProcessingError> {
|
||||
let (forward_ack, message) = split_into_ack_and_message(payload, packet_size, packet_type)?;
|
||||
|
||||
Ok(MixProcessingResult::FinalHop(ProcessedFinalHop {
|
||||
destination,
|
||||
forward_ack,
|
||||
message,
|
||||
}))
|
||||
Ok(MixProcessingResultData::FinalHop {
|
||||
final_hop_data: ProcessedFinalHop {
|
||||
destination,
|
||||
forward_ack,
|
||||
message,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn split_into_ack_and_message(
|
||||
@@ -211,11 +267,14 @@ fn process_forward_hop(
|
||||
forward_address: NodeAddressBytes,
|
||||
delay: SphinxDelay,
|
||||
packet_type: PacketType,
|
||||
) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
) -> Result<MixProcessingResultData, PacketProcessingError> {
|
||||
let next_hop_address = NymNodeRoutingAddress::try_from(forward_address)?;
|
||||
|
||||
let mix_packet = MixPacket::new(next_hop_address, packet, packet_type);
|
||||
Ok(MixProcessingResult::ForwardHop(mix_packet, Some(delay)))
|
||||
let packet = MixPacket::new(next_hop_address, packet, packet_type);
|
||||
Ok(MixProcessingResultData::ForwardHop {
|
||||
packet,
|
||||
delay: Some(delay),
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: what more could we realistically test here?
|
||||
|
||||
@@ -16,5 +16,5 @@ nym-sphinx-types = { path = "../types" }
|
||||
|
||||
[features]
|
||||
default = ["sphinx"]
|
||||
sphinx = ["nym-crypto/sphinx", "nym-sphinx-types/outfox"]
|
||||
outfox = ["nym-crypto/outfox", "nym-sphinx-types/outfox"]
|
||||
sphinx = ["nym-sphinx-types/outfox"]
|
||||
outfox = ["nym-sphinx-types/outfox"]
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::{array::TryFromSliceError, fmt};
|
||||
use thiserror::Error;
|
||||
|
||||
#[cfg(feature = "outfox")]
|
||||
use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
|
||||
|
||||
#[cfg(feature = "outfox")]
|
||||
pub use nym_outfox::{
|
||||
constants::MIN_PACKET_SIZE, constants::MIX_PARAMS_LEN, constants::OUTFOX_PACKET_OVERHEAD,
|
||||
error::OutfoxError,
|
||||
};
|
||||
// re-exporting types and constants available in sphinx
|
||||
#[cfg(feature = "outfox")]
|
||||
use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
pub use sphinx_packet::{
|
||||
constants::{
|
||||
@@ -21,12 +29,10 @@ pub use sphinx_packet::{
|
||||
payload::{Payload, PAYLOAD_OVERHEAD_SIZE},
|
||||
route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier},
|
||||
surb::{SURBMaterial, SURB},
|
||||
Error as SphinxError, ProcessedPacket,
|
||||
version::Version,
|
||||
version::UPDATED_LEGACY_VERSION,
|
||||
Error as SphinxError, ProcessedPacket, ProcessedPacketData,
|
||||
};
|
||||
#[cfg(feature = "sphinx")]
|
||||
use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
|
||||
use std::{array::TryFromSliceError, fmt};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum NymPacketError {
|
||||
@@ -85,8 +91,12 @@ impl NymPacket {
|
||||
destination: &Destination,
|
||||
delays: &[Delay],
|
||||
) -> Result<NymPacket, NymPacketError> {
|
||||
// FIXME:
|
||||
// for now explicitly use the legacy version until sufficient number of nodes
|
||||
// understand both variants
|
||||
Ok(NymPacket::Sphinx(
|
||||
SphinxPacketBuilder::new()
|
||||
.with_version(UPDATED_LEGACY_VERSION)
|
||||
.with_payload_size(size)
|
||||
.build_packet(message, route, destination, delays)?,
|
||||
))
|
||||
|
||||
@@ -27,7 +27,7 @@ wasm-bindgen = { workspace = true, optional = true }
|
||||
|
||||
## internal
|
||||
nym-config = { path = "../config" }
|
||||
nym-crypto = { path = "../crypto", features = ["sphinx", "outfox"] }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-sphinx-addressing = { path = "../nymsphinx/addressing" }
|
||||
nym-sphinx-types = { path = "../nymsphinx/types", features = [
|
||||
|
||||
@@ -105,7 +105,7 @@ impl<'a> From<&'a RoutingNode> for SphinxNode {
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
SphinxNode::new(node_address_bytes, (&node.sphinx_key).into())
|
||||
SphinxNode::new(node_address_bytes, node.sphinx_key.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"git": {
|
||||
"deploymentEnabled": {
|
||||
"master": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "explorer-api"
|
||||
version = "1.1.47"
|
||||
version = "1.1.46"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"extends": ["next/core-web-vitals"]
|
||||
"extends": ["next/core-web-vitals", "next/typescript"]
|
||||
}
|
||||
|
||||
@@ -3,8 +3,12 @@
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
@@ -25,8 +29,8 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -18,7 +18,7 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
|
||||
## Learn More
|
||||
|
||||
@@ -27,10 +27,10 @@ To learn more about Next.js, take a look at the following resources:
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||
"vcs": {
|
||||
"enabled": false,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": false
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false,
|
||||
"ignore": ["node_modules", ".next", "public"]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "space"
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"suspicious": {
|
||||
"noExplicitAny": "warn"
|
||||
}
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
@@ -1,31 +1,64 @@
|
||||
{
|
||||
"name": "@nymproject/network-explorer",
|
||||
"version": "1.0.0",
|
||||
"name": "@nymproject/explorer-nextjs",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"build:prod": "yarn --cwd .. build && next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "biome check --fix"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nymproject/react": "^1.0.0",
|
||||
"@nymproject/nym-validator-client": "0.18.0",
|
||||
"next": "14.1.4",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-error-boundary": "^4.0.13",
|
||||
"material-react-table": "^2.12.1",
|
||||
"@mui/x-date-pickers": "7.1.1",
|
||||
"@mui/x-data-grid": "7.1.1",
|
||||
"@mui/x-charts": "^7.22.3"
|
||||
"@chain-registry/types": "^0.50.36",
|
||||
"@cosmos-kit/keplr-extension": "^2.14.0",
|
||||
"@cosmos-kit/react": "^2.20.1",
|
||||
"@emotion/cache": "^11.13.5",
|
||||
"@emotion/react": "^11.13.5",
|
||||
"@emotion/styled": "^11.13.5",
|
||||
"@interchain-ui/react": "^1.26.1",
|
||||
"@mui/icons-material": "^5.16.11",
|
||||
"@mui/material": "^6.1.10",
|
||||
"@mui/material-nextjs": "^6.1.9",
|
||||
"@mui/x-date-pickers": "^7.23.2",
|
||||
"@nivo/line": "^0.88.0",
|
||||
"@nymproject/contract-clients": "^1.4.1",
|
||||
"@nymproject/react": "1.0.0",
|
||||
"@tanstack/react-query": "^5.64.2",
|
||||
"@tanstack/react-query-devtools": "^5.64.2",
|
||||
"@tanstack/react-query-next-experimental": "^5.66.0",
|
||||
"@tanstack/react-table": "^8.20.6",
|
||||
"@types/qs": "^6.9.18",
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"chain-registry": "^1.69.64",
|
||||
"cldr-compact-number": "^0.4.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"i18next": "^24.2.2",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"isomorphic-dompurify": "^2.21.0",
|
||||
"material-react-table": "^3.0.3",
|
||||
"next": "15.0.3",
|
||||
"openapi-fetch": "^0.13.4",
|
||||
"qrcode.react": "^4.1.0",
|
||||
"qs": "^6.14.0",
|
||||
"react": "19.0.0-rc-66855b96-20241106",
|
||||
"react-dom": "19.0.0-rc-66855b96-20241106",
|
||||
"react-i18next": "^15.4.0",
|
||||
"react-markdown": "^9.0.3",
|
||||
"react-random-avatars": "^1.3.1",
|
||||
"react-world-flags": "^1.6.0",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.1.4",
|
||||
"eslint-config-next": "15.0.3",
|
||||
"lefthook": "^1.8.5",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 391 B |
@@ -0,0 +1 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,61 @@
|
||||
<svg
|
||||
width="33"
|
||||
height="32"
|
||||
viewBox="0 0 33 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
width="6.4"
|
||||
height="6.38019"
|
||||
transform="matrix(1 1.74846e-07 1.74846e-07 -1 7.06641 25.5204)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
width="6.4"
|
||||
height="6.38019"
|
||||
transform="matrix(1 1.74846e-07 1.74846e-07 -1 0.666504 31.9006)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
width="6.4"
|
||||
height="6.38019"
|
||||
transform="matrix(1 1.74846e-07 1.74846e-07 -1 13.4663 19.1406)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
width="6.4"
|
||||
height="6.38019"
|
||||
transform="matrix(1 1.74846e-07 1.74846e-07 -1 19.8667 12.761)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<path
|
||||
d="M32.6663 32L26.2663 32L26.2663 6.38018L0.708989 6.38017L0.70899 -1.52588e-05L24.9863 -1.1014e-05C29.2278 -1.02724e-05 32.6663 3.43845 32.6663 7.68L32.6663 32Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,7 @@
|
||||
<svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="15" width="3" height="3" transform="rotate(-90 0 15)" fill="currentColor" />
|
||||
<rect x="3" y="12" width="3" height="3" transform="rotate(-90 3 12)" fill="currentColor" />
|
||||
<rect x="6" y="9" width="3" height="3" transform="rotate(-90 6 9)" fill="currentColor" />
|
||||
<rect x="9" y="6" width="3" height="3" transform="rotate(-90 9 6)" fill="currentColor"/>
|
||||
<path d="M0 2.19345e-05V3.00002H11.9997V15H14.9997V3.00002C14.9997 1.34317 13.6565 2.19345e-05 11.9997 2.19345e-05H0Z" fill="currentColor" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 579 B |
@@ -0,0 +1,31 @@
|
||||
<svg width="361" height="361" viewBox="0 0 361 361" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_236_24563)">
|
||||
<path d="M180.789 120.41V150.41H210.789V180.41H240.789V180.41C240.789 147.273 213.926 120.41 180.789 120.41V120.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M180.789 240.487L180.789 210.487L150.789 210.487L150.789 180.487L120.789 180.487V180.487C120.789 213.624 147.652 240.487 180.789 240.487V240.487Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M120.789 180.41L150.789 180.41L150.789 150.41L180.789 150.41L180.789 120.41V120.41C147.652 120.41 120.789 147.273 120.789 180.41V180.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M240.789 180.487L210.789 180.487L210.789 210.487L180.789 210.487L180.789 240.487V240.487C213.926 240.487 240.789 213.624 240.789 180.487V180.487Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M330.773 120.41L330.773 150.41V150.41C347.342 150.41 360.773 136.979 360.773 120.41V120.41L330.773 120.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M270.789 60.4102L270.789 90.4102L300.789 90.4102L300.789 60.4102L270.789 60.4102Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M240.789 30.4102L240.789 60.4102L270.789 60.4102L270.789 30.4102L240.789 30.4102Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M60.7891 30.4102L60.7891 60.4102L90.7891 60.4102L90.7891 30.4102L60.7891 30.4102Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M30.7734 60.4102L30.7734 90.4102L60.7734 90.4102L60.7734 60.4102L30.7734 60.4102Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M90.7891 0.410156L90.7891 30.4102L240.789 30.4102L240.789 0.410181L90.7891 0.410156Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<rect width="30" height="150.466" transform="matrix(-1.62921e-07 1 1 1.62921e-07 180.789 120.41)" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<rect width="120" height="30" transform="matrix(-1.62921e-07 1 1 1.62921e-07 330.773 0.410156)" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M301.023 90.4102L301.023 120.41L331.023 120.41L331.023 90.4102L301.023 90.4102Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M30.7734 240.41L30.7734 210.41V210.41C14.2049 210.41 0.77344 223.842 0.773438 240.41V240.41L30.7734 240.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M90.7734 300.41L90.7734 270.41L60.7734 270.41L60.7734 300.41L90.7734 300.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M120.773 330.41L120.773 300.41L90.7734 300.41L90.7734 330.41L120.773 330.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M300.773 330.41L300.773 300.41L270.773 300.41L270.773 330.41L300.773 330.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M330.773 300.41L330.773 270.41L300.773 270.41L300.773 300.41L330.773 300.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M270.773 360.41L270.773 330.41L120.773 330.41L120.773 360.41L270.773 360.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<rect width="30" height="150.481" transform="matrix(1.62921e-07 -1 -1 -1.62921e-07 180.789 240.41)" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<rect width="120" height="30" transform="matrix(1.62921e-07 -1 -1 -1.62921e-07 30.7734 360.41)" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
<path d="M60.5391 270.41L60.5391 240.41L30.5391 240.41L30.5391 270.41L60.5391 270.41Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_236_24563">
|
||||
<rect width="360" height="360" fill="white" style="fill:white;fill-opacity:1;" transform="translate(0.773438 0.410156)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M3 3L-4.47035e-08 3L-8.31509e-07 6L3 6L3 3Z" fill="currentColor" />
|
||||
<path d="M6 6L3 6L3 9L6 9L6 6Z" fill="currentColor" />
|
||||
<path d="M9 9L6 9L6 12L9 12L9 9Z" fill="currentColor" />
|
||||
<path d="M12 6L9 6L9 9L12 9L12 6Z" fill="currentColor" />
|
||||
<path d="M15 3L12 3L12 6L15 6L15 3Z" fill="currentColor" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 431 B |
@@ -0,0 +1,14 @@
|
||||
<svg
|
||||
width="9"
|
||||
height="5"
|
||||
viewBox="0 0 9 5"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0.828125 0.828125L4.5 4.5L8.17188 0.828125"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 256 B |
@@ -0,0 +1,35 @@
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10.6668 13.3333V14.6667H10.0002V15.3333H2.00016V14.6667H1.3335V3.99999H2.00016V3.33333H4.00016V13.3333H10.6668Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<path
|
||||
d="M10.6665 4.66667V0.666672H5.33317V1.33334H4.6665V12H5.33317V12.6667H13.9998V12H14.6665V4.66667H10.6665ZM13.3332 11.3333H5.99984V2.00001H9.33317V6.00001H13.3332V11.3333Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<path
|
||||
d="M14.6668 3.33334V4H11.3335V0.666672H12.0002V1.33334H12.6668V2.00001H13.3335V2.66667H14.0002V3.33334H14.6668Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 967 B |
@@ -0,0 +1,135 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
>
|
||||
<g clip-path="url(#clip0_8428_65000)">
|
||||
<rect
|
||||
y="3"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 0 3)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
y="15"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 0 15)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="12"
|
||||
y="3"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 12 3)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="9"
|
||||
y="12"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 9 12)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="12"
|
||||
y="15"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 12 15)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="3"
|
||||
y="6"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 3 6)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="3"
|
||||
y="12"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 3 12)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="9"
|
||||
y="6"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 9 6)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
x="6"
|
||||
y="9"
|
||||
width="3"
|
||||
height="3"
|
||||
transform="rotate(-90 6 9)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_8428_65000">
|
||||
<rect
|
||||
width="15"
|
||||
height="15"
|
||||
fill="white"
|
||||
style="fill: white; fill-opacity: 1"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21.8343 11.2552C23.7199 14.0472 24.6511 17.1964 24.303 20.8219C24.3015 20.8372 24.2936 20.8513 24.2811 20.8606C22.8532 21.9165 21.4697 22.5573 20.1057 22.9823C20.0951 22.9855 20.0837 22.9853 20.0732 22.9817C20.0627 22.9782 20.0535 22.9714 20.047 22.9623C19.7319 22.5207 19.4456 22.0552 19.1947 21.5663C19.1803 21.5375 19.1935 21.5028 19.2231 21.4915C19.6779 21.3189 20.1103 21.1121 20.5262 20.8673C20.559 20.8479 20.5611 20.8007 20.5308 20.778C20.4425 20.712 20.3551 20.6426 20.2714 20.5733C20.2557 20.5604 20.2347 20.5579 20.2169 20.5665C17.5166 21.8223 14.5586 21.8223 11.8263 20.5665C11.8086 20.5585 11.7875 20.5613 11.7723 20.5739C11.6888 20.6432 11.6011 20.712 11.5137 20.778C11.4834 20.8007 11.4859 20.8479 11.5189 20.8673C11.9349 21.1075 12.3673 21.3189 12.8214 21.4923C12.8508 21.5037 12.8648 21.5375 12.8502 21.5663C12.6048 22.0558 12.3184 22.5213 11.9975 22.9629C11.9835 22.9808 11.9605 22.989 11.9388 22.9823C10.5813 22.5573 9.19781 21.9165 7.76992 20.8606C7.75802 20.8513 7.74947 20.8366 7.74822 20.8213C7.45729 17.6853 8.0502 14.51 10.2146 11.2546C10.2198 11.246 10.2277 11.2393 10.2369 11.2353C11.3019 10.743 12.4428 10.3809 13.6353 10.1741C13.657 10.1707 13.6787 10.1808 13.69 10.2002C13.8373 10.4629 14.0057 10.7998 14.1197 11.0751C15.3767 10.8818 16.6532 10.8818 17.9365 11.0751C18.0505 10.8057 18.213 10.4629 18.3597 10.2002C18.365 10.1906 18.3731 10.1829 18.3829 10.1782C18.3927 10.1735 18.4037 10.1721 18.4144 10.1741C19.6075 10.3815 20.7485 10.7437 21.8126 11.2353C21.822 11.2393 21.8297 11.246 21.8343 11.2552V11.2552ZM14.7587 17.2178C14.7719 16.2908 14.1007 15.5236 13.2582 15.5236C12.4226 15.5236 11.7579 16.284 11.7579 17.2178C11.7579 18.1514 12.4357 18.9118 13.2582 18.9118C14.094 18.9118 14.7587 18.1514 14.7587 17.2178V17.2178ZM20.3062 17.2178C20.3194 16.2908 19.6482 15.5236 18.8059 15.5236C17.9701 15.5236 17.3054 16.284 17.3054 17.2178C17.3054 18.1514 17.9833 18.9118 18.8059 18.9118C19.6482 18.9118 20.3062 18.1514 20.3062 17.2178V17.2178Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||||
<g clip-path="url(#clip0_6568_5882)">
|
||||
<path d="M4 8H8V9H4V8ZM4 6H8V7H4V6ZM7 1H3C2.45 1 2 1.45 2 2V10C2 10.55 2.445 11 2.995 11H9C9.55 11 10 10.55 10 10V4L7 1ZM9 10H3V2H6.5V4.5H9V10Z" fill="#242B2D" style="fill:#242B2D;fill:color(display-p3 0.1412 0.1686 0.1765);fill-opacity:1;"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6568_5882">
|
||||
<rect width="12" height="12" fill="white" style="fill:white;fill-opacity:1;"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 526 B |
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||||
<path d="M2.5 5H2V4H3V4.5H3.5V5H4V5.5H4.5V6H5V6.5H5.5V0.5H6.5V6.5H7V6H7.5V5.5H8V5H8.5V4.5H9V4H10V5H9.5V5.5H9V6H8.5V6.5H8V7H7.5V7.5H7V8H6.5V8.5H5.5V8H5V7.5H4.5V7H4V6.5H3.5V6H3V5.5H2.5V5Z" fill="#242B2D" style="fill:#242B2D;fill:color(display-p3 0.1412 0.1686 0.1765);fill-opacity:1;"/>
|
||||
<path d="M11 10.5H1V11.5H11V10.5Z" fill="#242B2D" style="fill:#242B2D;fill:color(display-p3 0.1412 0.1686 0.1765);fill-opacity:1;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 520 B |
@@ -0,0 +1,22 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="25"
|
||||
viewBox="0 0 24 25"
|
||||
fill="none"
|
||||
>
|
||||
<circle cx="12" cy="12.5" r="10" fill="url(#paint0_angular_2549_7570)" />
|
||||
<defs>
|
||||
<radialGradient
|
||||
id="paint0_angular_2549_7570"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(12 12.5) rotate(90) scale(12)"
|
||||
>
|
||||
<stop stopColor="#22D27E" />
|
||||
<stop offset="1" stopColor="#9002FF" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 515 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="84" height="84" viewBox="0 0 84 84" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M63 0L56 -2.44784e-06L56 7L63 7L70 7H77V14V21L77 28L84 28V21V14C84 6.26801 77.732 0 70 0H63ZM7 14L7 7H14H21L28 7L28 2.14186e-06L21 0H14C6.26801 0 0 6.26801 0 14V21L-3.87835e-06 28L7 28L7 21V14ZM84 70C84 77.732 77.732 84 70 84H63H56L56 77H63H70H77V70L77 63L77 56L84 56V63V70ZM21 77H14L14 70L21 70L21 63H28L28 56H35L35 63H42H49L49 56H56L56 49L63 49L63 42V35L56 35V28L49 28L49 21L42 21H35L35 28L28 28L28 35H21L21 42V49L28 49L28 56H21L21 63L14 63L14 70H7L7 77L7 70L7 63L7 56L0 56L-3.87835e-06 63L0 70C0 77.732 6.26801 84 14 84H21H28L28 77H21ZM28 49L28 42L28 35H35L35 28H42L49 28L49 35L56 35V42L56 49H49V56L42 56H35V49H28Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 869 B |
@@ -0,0 +1,79 @@
|
||||
<svg
|
||||
width="84"
|
||||
height="84"
|
||||
viewBox="0 0 84 84"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
width="7"
|
||||
height="56"
|
||||
transform="matrix(-2.36041e-07 1 1 7.28523e-08 28 77)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
width="7"
|
||||
height="56"
|
||||
transform="matrix(1 0 -1.63189e-07 -1 0 56)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<path
|
||||
d="M63 0L63 21L84 21L84 28L63 28C59.134 28 56 24.866 56 21L56 0H63Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
width="7"
|
||||
height="42"
|
||||
transform="matrix(1 0 -1.63189e-07 -1 28 42)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<rect
|
||||
width="7"
|
||||
height="35"
|
||||
transform="matrix(-2.36041e-07 1 1 7.28523e-08 49 49)"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<path
|
||||
d="M28 84L28 77L7 77L7 56L-1.89145e-06 56L-2.80939e-06 77C-2.97838e-06 80.866 3.134 84 7 84L28 84Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
<path
|
||||
d="M56 56L56 49L35 49L35 28L28 28L28 49C28 52.866 31.134 56 35 56L56 56Z"
|
||||
fill="#242B2D"
|
||||
style="
|
||||
fill: #242b2d;
|
||||
fill: color(display-p3 0.1412 0.1686 0.1765);
|
||||
fill-opacity: 1;
|
||||
"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9408 7.86426C10.9716 7.86426 6.94678 11.8731 6.94678 16.8225C6.94678 20.7866 9.52132 24.1347 13.0965 25.3217C13.5462 25.4001 13.7148 25.1313 13.7148 24.8962C13.7148 24.6834 13.7035 23.9779 13.7035 23.2277C11.4438 23.642 10.8592 22.679 10.6793 22.1751C10.5781 21.9175 10.1397 21.1225 9.75741 20.9097C9.44262 20.7418 8.99292 20.3274 9.74617 20.3162C10.4545 20.3051 10.9604 20.9657 11.129 21.2345C11.9385 22.5894 13.2314 22.2087 13.7485 21.9735C13.8272 21.3912 14.0633 20.9993 14.3219 20.7754C12.3207 20.5514 10.2296 19.7788 10.2296 16.3522C10.2296 15.378 10.5781 14.5718 11.1515 13.9447C11.0616 13.7207 10.7468 12.8025 11.2414 11.5707C11.2414 11.5707 11.9947 11.3356 13.7148 12.489C14.4343 12.2874 15.1988 12.1866 15.9633 12.1866C16.7278 12.1866 17.4923 12.2874 18.2118 12.489C19.9319 11.3244 20.6852 11.5707 20.6852 11.5707C21.1798 12.8025 20.8651 13.7207 20.7751 13.9447C21.3485 14.5718 21.697 15.3668 21.697 16.3522C21.697 19.79 19.5946 20.5514 17.5935 20.7754C17.9195 21.0553 18.2006 21.5928 18.2006 22.4326C18.2006 23.6308 18.1893 24.5938 18.1893 24.8962C18.1893 25.1313 18.358 25.4113 18.8077 25.3217C22.3603 24.1347 24.9349 20.7754 24.9349 16.8225C24.9349 11.8731 20.91 7.86426 15.9408 7.86426Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg viewBox="0 0 89 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M0 2.73999C0 1.50288 1.00579 0.5 2.2465 0.5H10.4256C11.8792 0.5 13.1513 1.47412 13.5263 2.87439L18.7506 22.3815C18.8474 22.7432 19.3816 22.6733 19.3816 22.299V0.5H25.8001V22.2599C25.8001 23.497 24.7943 24.4999 23.5536 24.4999H15.314C13.8643 24.4999 12.5946 23.5308 12.216 22.1355L7.04928 3.0892C6.95141 2.72844 6.41855 2.79902 6.41855 3.17275V24.4999H0V2.73999Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M55.5159 0.500025C54.2752 0.500025 53.2694 1.5029 53.2694 2.74002V24.4999H59.6879V3.18233C59.6879 2.79548 60.2483 2.74066 60.3237 3.12013L64.0601 21.9219C64.3579 23.4203 65.6762 24.4999 67.2082 24.4999L74.6942 24.4999C76.2294 24.4999 77.5496 23.4158 77.8439 21.9135L81.5171 3.16662C81.5916 2.78643 82.153 2.84061 82.153 3.22798V24.4999H88.5714V2.74002C88.5714 1.5029 87.5656 0.500025 86.3249 0.500025L78.3813 0.50002C76.859 0.500019 75.5461 1.56646 75.2383 3.05306L71.2361 22.3844C71.1655 22.7251 70.6773 22.7246 70.6074 22.3838L66.6405 3.05837C66.3349 1.56926 65.0208 0.500019 63.4964 0.50002L55.5159 0.500025Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M26.5569 0.50009H33.3531L39.2253 13.0169C39.4563 13.5093 40.1589 13.5085 40.3888 13.0155L46.2237 0.50009H53.1458L41.8949 24.5H34.9858L39.4713 14.9H35.3564C34.1107 14.9 32.9775 14.1813 32.4496 13.0563L26.5569 0.50009Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="84" height="84" viewBox="0 0 84 84" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M63 0H56V7H63H70H77V14V21V28H84V21V14C84 6.26801 77.732 0 70 0H63ZM7 77H14H21H28V84H21H14C6.26801 84 0 77.732 0 70V63V56H7L7 63L7 70L7 77ZM70 84C77.732 84 84 77.732 84 70V63V56H77V63V70V77H70H63H56V84H63H70ZM7 7L7 14L7 21L7 28H0V21V14C1.93187e-06 6.26801 6.26802 0 14 0H21H28V7L21 7L14 7L7 7ZM63 21L63 28L56 28L56 21L63 21ZM63 21V14L70 14L70 21L63 21ZM49 35V28L56 28V35H49ZM49 49V42L49 35L42 35L35 35L35 28L28 28L28 21L21 21L21 14L14 14L14 21L21 21L21 28L28 28V35L35 35V42V49L28 49L28 56L21 56L21 63H14L14 70H21L21 63L28 63L28 56H35V49H42L49 49ZM56 56H49L49 49L56 49V56ZM63 63L56 63V56L63 56L63 63ZM63 63H70V70H63L63 63Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 872 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="84" height="84" viewBox="0 0 84 84" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M84 14C84 6.26801 77.732 0 70 0H63H56V7H63H70H77V14V21V28H84V21V14ZM28 14C20.268 14 14 20.268 14 28C14 35.732 20.268 42 28 42C20.268 42 14 48.268 14 56C14 63.732 20.268 70 28 70C35.7299 70 41.9966 63.7354 42 56.0062C42.0034 63.7353 48.2701 70 56 70C63.732 70 70 63.732 70 56C70 48.2701 63.7353 42.0034 56.0062 42C63.7353 41.9966 70 35.7299 70 28C70 20.268 63.732 14 56 14C48.268 14 42 20.268 42 28C42 20.268 35.732 14 28 14ZM49 28V35L56 35H63V28V21L56 21H49V28ZM42 28.0062C41.9966 35.7329 35.7339 41.996 28.0074 42C35.736 42.004 42 48.2705 42 56C42 48.268 48.268 42 56 42C48.2701 42 42.0034 35.7353 42 28.0062ZM56 63H63V56V49L56 49H49V56V63L56 63ZM28 35H35V28V21L28 21H21V28L21 35L28 35ZM21 49V56L21 63L28 63H35V56V49L28 49H21ZM7 77H14H21H28V84H21H14C6.26801 84 0 77.732 0 70V63V56H7L7 63L7 70L7 77ZM70 84C77.732 84 84 77.732 84 70V63V56H77V63V70V77H70H63H56V84H63H70ZM7 7L7 14L7 21L7 28H0V21V14C1.93187e-06 6.26801 6.26802 0 14 0H21H28V7L21 7L14 7L7 7Z" fill="#14E76F" style="fill:#14E76F;fill:color(display-p3 0.0784 0.9059 0.4353);fill-opacity:1;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.90246 15.9332C8.90246 15.9332 15.4128 13.1912 17.6706 12.2256C18.5362 11.8394 21.4715 10.6036 21.4715 10.6036C21.4715 10.6036 22.8262 10.0629 22.7133 11.376C22.6757 11.9167 22.3746 13.8091 22.0736 15.8559C21.622 18.7525 21.1328 21.9194 21.1328 21.9194C21.1328 21.9194 21.0575 22.8077 20.4178 22.9621C19.7781 23.1166 18.7243 22.4215 18.5362 22.267C18.3856 22.1511 15.7138 20.4132 14.7354 19.5635C14.4719 19.3318 14.1709 18.8684 14.773 18.3277C16.1278 17.0532 17.7459 15.4698 18.7243 14.4656C19.1759 14.0022 19.6275 12.9208 17.7459 14.2339C15.0741 16.1263 12.4398 17.9029 12.4398 17.9029C12.4398 17.9029 11.8377 18.289 10.7088 17.9414C9.57979 17.5939 8.26268 17.1304 8.26268 17.1304C8.26268 17.1304 7.35957 16.5511 8.90246 15.9332Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 845 B |
@@ -0,0 +1,23 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="25"
|
||||
viewBox="0 0 24 25"
|
||||
fill="none"
|
||||
>
|
||||
<g clipPath="url(#clip0_2549_7563)">
|
||||
<path
|
||||
d="M20.4841 4.01607C15.8041 -0.67593 8.19607 -0.67593 3.51607 4.01607C-1.17593 8.70807 -1.17593 16.3041 3.51607 20.9841C8.20807 25.6761 15.8041 25.6761 20.4841 20.9841C25.1761 16.3041 25.1761 8.69607 20.4841 4.01607ZM19.4521 19.9521C15.3361 24.0681 8.65207 24.0681 4.53607 19.9521C0.42007 15.8361 0.42007 9.15207 4.53607 5.03607C8.65207 0.92007 15.3361 0.92007 19.4521 5.03607C23.5801 9.16407 23.5801 15.8361 19.4521 19.9521Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M18.48 19.4965V5.50447C17.868 4.92847 17.184 4.42447 16.452 4.02847V17.4085L7.62002 3.98047C6.85202 4.38847 6.14402 4.89247 5.52002 5.49247V19.4965C6.13202 20.0725 6.81602 20.5765 7.54802 20.9725V7.59247L16.38 21.0205C17.148 20.6125 17.856 20.0965 18.48 19.4965Z"
|
||||
fill="black"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2549_7563">
|
||||
<rect width="24" height="24" fill="white" transform="translate(0 0.5)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<path d="M17.4206 15.4955L22.9798 9.03333H21.6625L16.8354 14.6444L12.98 9.03333H8.5332L14.3633 17.5182L8.5332 24.2948H9.85065L14.9482 18.3694L19.0198 24.2948H23.4665L17.4202 15.4955H17.4206ZM15.6161 17.593L15.0254 16.7481L10.3253 10.0251H12.3489L16.1419 15.4507L16.7326 16.2956L21.6631 23.3482H19.6396L15.6161 17.5933V17.593Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 453 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<path d="M24.9004 12.0986C24.6915 11.3132 24.0734 10.6936 23.2871 10.4812C21.8652 10.1001 16.1605 10.1001 16.1605 10.1001C16.1605 10.1001 10.4587 10.1001 9.03399 10.4812C8.25053 10.6906 7.63247 11.3103 7.42065 12.0986C7.04053 13.5241 7.04053 16.5001 7.04053 16.5001C7.04053 16.5001 7.04053 19.4761 7.42065 20.9016C7.62957 21.687 8.24763 22.3066 9.03399 22.519C10.4587 22.9001 16.1605 22.9001 16.1605 22.9001C16.1605 22.9001 21.8652 22.9001 23.2871 22.519C24.0705 22.3096 24.6886 21.6899 24.9004 20.9016C25.2805 19.4761 25.2805 16.5001 25.2805 16.5001C25.2805 16.5001 25.2805 13.5241 24.9004 12.0986Z" fill="currentColor"/>
|
||||
<path d="M14.3383 19.2434L19.0767 16.5001L14.3383 13.7568V19.2434Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 810 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.9004 12.0986C24.6915 11.3132 24.0734 10.6936 23.2871 10.4812C21.8652 10.1001 16.1605 10.1001 16.1605 10.1001C16.1605 10.1001 10.4587 10.1001 9.03399 10.4812C8.25053 10.6906 7.63247 11.3103 7.42065 12.0986C7.04053 13.5241 7.04053 16.5001 7.04053 16.5001C7.04053 16.5001 7.04053 19.4761 7.42065 20.9016C7.62957 21.687 8.24763 22.3066 9.03399 22.519C10.4587 22.9001 16.1605 22.9001 16.1605 22.9001C16.1605 22.9001 21.8652 22.9001 23.2871 22.519C24.0705 22.3096 24.6886 21.6899 24.9004 20.9016C25.2805 19.4761 25.2805 16.5001 25.2805 16.5001C25.2805 16.5001 25.2805 13.5241 24.9004 12.0986Z" fill="currentColor"/>
|
||||
<path d="M14.3383 19.2434L19.0767 16.5001L14.3383 13.7568V19.2434Z" fill="#242B2D"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 811 B |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 543 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 387 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
||||
|
Before Width: | Height: | Size: 629 B After Width: | Height: | Size: 128 B |
@@ -0,0 +1 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
||||
|
After Width: | Height: | Size: 385 B |
@@ -0,0 +1,62 @@
|
||||
// import BlogArticlesCards from "@/components/blogs/BlogArticleCards";
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "@/components/headings/SectionHeading";
|
||||
import ExplorerButtonGroup from "@/components/toggleButton/ToggleButton";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
import Markdown from "react-markdown";
|
||||
|
||||
export default async function Account({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ address: string }>;
|
||||
}) {
|
||||
try {
|
||||
const address = (await params).address;
|
||||
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Grid container columnSpacing={5} rowSpacing={5}>
|
||||
<Grid size={12}>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between" }}>
|
||||
<SectionHeading title="Nym Node Details" />
|
||||
<ExplorerButtonGroup
|
||||
onPage="Account"
|
||||
options={[
|
||||
{
|
||||
label: "Nym Node",
|
||||
isSelected: true,
|
||||
link: `/account/${address}/not-found/`,
|
||||
},
|
||||
{
|
||||
label: "Account",
|
||||
isSelected: false,
|
||||
link: `/account/${address}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Typography variant="h5">
|
||||
<Markdown className="reactMarkDownLink">
|
||||
This account does’t have a Nym node bonded. Is this your account?
|
||||
Start [setting up your node](https://nym.com/docs) today!
|
||||
</Markdown>
|
||||
</Typography>
|
||||
{/* <Grid container columnSpacing={5} rowSpacing={5}>
|
||||
<Grid size={12}>
|
||||
<SectionHeading title="Onboarding" />
|
||||
</Grid>
|
||||
<BlogArticlesCards ids={[1]} />
|
||||
</Grid> */}
|
||||
</ContentLayout>
|
||||
);
|
||||
} catch (error) {
|
||||
let errorMessage = "An error occurred";
|
||||
if (error instanceof Error) {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { fetchNodes } from "@/app/api";
|
||||
import type { NodeData } from "@/app/api/types";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
import { AccountBalancesCard } from "../../../../components/accountPageComponents/AccountBalancesCard";
|
||||
import { AccountInfoCard } from "../../../../components/accountPageComponents/AccountInfoCard";
|
||||
import { ContentLayout } from "../../../../components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "../../../../components/headings/SectionHeading";
|
||||
import ExplorerButtonGroup from "../../../../components/toggleButton/ToggleButton";
|
||||
|
||||
export default async function Account({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ address: string }>;
|
||||
}) {
|
||||
try {
|
||||
const address = (await params).address;
|
||||
|
||||
const nymNodes: NodeData[] = await fetchNodes();
|
||||
|
||||
const nymNode = nymNodes.find(
|
||||
(node) => node.bond_information.owner === address,
|
||||
);
|
||||
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Grid container columnSpacing={5} rowSpacing={5}>
|
||||
<Grid size={6}>
|
||||
<SectionHeading title="Account Details" />
|
||||
</Grid>
|
||||
|
||||
<Grid size={6} justifyContent="flex-end">
|
||||
<Box sx={{ display: "flex", justifyContent: "end" }}>
|
||||
<ExplorerButtonGroup
|
||||
onPage="Account"
|
||||
options={[
|
||||
{
|
||||
label: "Nym Node",
|
||||
isSelected: false,
|
||||
link: nymNode
|
||||
? `/nym-node/${nymNode.node_id}`
|
||||
: `/account/${address}/not-found`,
|
||||
},
|
||||
{
|
||||
label: "Account",
|
||||
isSelected: true,
|
||||
link: `/account/${address}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid size={{ xs: 12, md: 4 }}>
|
||||
<AccountInfoCard address={address} />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 8 }}>
|
||||
<AccountBalancesCard address={address} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ContentLayout>
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("error :>> ", error);
|
||||
return <Typography>Error loading account data</Typography>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import { fetchNodeIdByIdentityKey, fetchNodeInfo } from "@/app/api";
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "@/components/headings/SectionHeading";
|
||||
import { BasicInfoCard } from "@/components/nymNodePageComponents/BasicInfoCard";
|
||||
import { NodeDataCard } from "@/components/nymNodePageComponents/NodeDataCard";
|
||||
// import { NodeChatCard } from "@/components/nymNodePageComponents/ChatCard";
|
||||
import NodeDelegationsCard from "@/components/nymNodePageComponents/NodeDelegationsCard";
|
||||
import { NodeParametersCard } from "@/components/nymNodePageComponents/NodeParametersCard";
|
||||
import { NodeProfileCard } from "@/components/nymNodePageComponents/NodeProfileCard";
|
||||
import { NodeRoleCard } from "@/components/nymNodePageComponents/NodeRoleCard";
|
||||
import ExplorerButtonGroup from "@/components/toggleButton/ToggleButton";
|
||||
import { Box } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
|
||||
export default async function NymNode({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ id: string }>; // node_id or identity_key
|
||||
}) {
|
||||
try {
|
||||
let id: string | number;
|
||||
const paramsId = (await params).id;
|
||||
|
||||
// check if the params id is a node_id or identity_key
|
||||
|
||||
if (paramsId.length > 10) {
|
||||
id = await fetchNodeIdByIdentityKey(paramsId);
|
||||
} else {
|
||||
id = Number(paramsId);
|
||||
}
|
||||
|
||||
const observatoryNymNode = await fetchNodeInfo(id);
|
||||
|
||||
if (!observatoryNymNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Grid container columnSpacing={5} rowSpacing={5}>
|
||||
<Grid size={12}>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between" }}>
|
||||
<SectionHeading title="Nym Node Details" />
|
||||
{observatoryNymNode.bonding_address && (
|
||||
<ExplorerButtonGroup
|
||||
onPage="Nym Node"
|
||||
options={[
|
||||
{
|
||||
label: "Nym Node",
|
||||
isSelected: true,
|
||||
link: `/nym-node/${id}`,
|
||||
},
|
||||
{
|
||||
label: "Account",
|
||||
isSelected: false,
|
||||
link: `/account/${observatoryNymNode.bonding_address}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<NodeProfileCard id={id} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<BasicInfoCard id={id} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<NodeRoleCard id={id} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeParametersCard id={id} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeDataCard id={id} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
}}
|
||||
>
|
||||
<NodeDelegationsCard id={id} />
|
||||
</Grid>
|
||||
{/*
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
}}
|
||||
>
|
||||
<NodeChatCard />
|
||||
</Grid> */}
|
||||
</Grid>
|
||||
</ContentLayout>
|
||||
);
|
||||
} catch (error) {
|
||||
let errorMessage = "An error occurred";
|
||||
if (error instanceof Error) {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
import TableOfContents from "@/components/blogs/TableOfContents";
|
||||
import type BlogArticle from "@/components/blogs/types";
|
||||
import { Breadcrumbs } from "@/components/breadcrumbs/Breadcrumbs";
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "@/components/headings/SectionHeading";
|
||||
import { Link } from "@/components/muiLink";
|
||||
import { Wrapper } from "@/components/wrapper";
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
import { format } from "date-fns";
|
||||
import Image from "next/image";
|
||||
import Markdown from "react-markdown";
|
||||
|
||||
export default async function BlogPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug: string }>;
|
||||
}) {
|
||||
const { slug } = await params;
|
||||
|
||||
try {
|
||||
const blogArticle: BlogArticle = await import(`@/data/${slug}.json`);
|
||||
const breadcrumbItems = [
|
||||
{
|
||||
label: "Onboarding",
|
||||
href: "/onboarding",
|
||||
},
|
||||
{ label: blogArticle.title, isCurrentPage: true },
|
||||
];
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Wrapper>
|
||||
<Grid container spacing={5}>
|
||||
<Grid size={{ xs: 12, md: 8 }}>
|
||||
<Stack spacing={4}>
|
||||
<Breadcrumbs items={breadcrumbItems} />
|
||||
<SectionHeading title={blogArticle.title} />
|
||||
<Box
|
||||
sx={{
|
||||
borderTop: "1px dashed",
|
||||
paddingBlockStart: "10px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="subtitle3"
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: "20px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: "10px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
Author
|
||||
{(blogArticle?.attributes?.blogAuthors?.length ?? 0) > 1
|
||||
? "s"
|
||||
: ""}
|
||||
:{" "}
|
||||
{blogArticle?.attributes?.blogAuthors?.map(
|
||||
(author: string) => (
|
||||
<Typography key={author} variant="subtitle3">
|
||||
{author}
|
||||
</Typography>
|
||||
),
|
||||
)}
|
||||
</Box>
|
||||
<time dateTime={blogArticle?.attributes?.date.toString()}>
|
||||
{format(blogArticle?.attributes?.date, "MMMM dd, yyyy")}
|
||||
</time>
|
||||
</Typography>
|
||||
<Typography variant="subtitle3">
|
||||
{blogArticle.attributes.readingTime}{" "}
|
||||
{blogArticle.attributes.readingTime > 1 ? "mins" : "min"}{" "}
|
||||
read
|
||||
</Typography>
|
||||
</Box>
|
||||
<Image
|
||||
src={blogArticle.image}
|
||||
alt="blog-image"
|
||||
width={120}
|
||||
height={60}
|
||||
sizes="100vw"
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "auto",
|
||||
}}
|
||||
/>
|
||||
<Box>
|
||||
{blogArticle.overview.content.map(({ text }) => (
|
||||
<Box key={text} sx={{ mt: 3 }}>
|
||||
<Typography variant="body2" component="span">
|
||||
<Markdown className="reactMarkDownLink reactMarkDownList">
|
||||
{text}
|
||||
</Markdown>
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
{blogArticle.sections.map((section) => (
|
||||
<Box key={section.heading} id={section.id}>
|
||||
<SectionHeading title={section.heading} />
|
||||
{section.text.map(({ text }) => (
|
||||
<Box key={text} sx={{ mt: 3 }}>
|
||||
<Typography variant="body2" component="span">
|
||||
<Markdown className="reactMarkDownLink reactMarkDownList">
|
||||
{text}
|
||||
</Markdown>
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid size={{ md: 4 }}>
|
||||
<TableOfContents
|
||||
headings={blogArticle.sections.map((section) => ({
|
||||
heading: section.heading,
|
||||
id: section.id,
|
||||
}))}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
</ContentLayout>
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Wrapper>
|
||||
<SectionHeading title={"Off the grid, like your data"} />
|
||||
<Typography variant="body2">
|
||||
Oops! Looks like the page you’re looking for got mixed up in the
|
||||
noise. Don’t worry, your privacy is intact. Let’s get you
|
||||
<Link href="/">back to the homepage.</Link>
|
||||
</Typography>
|
||||
</Wrapper>
|
||||
</ContentLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import BlogArticlesCards from "@/components/blogs/BlogArticleCards";
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "@/components/headings/SectionHeading";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
|
||||
export default function OnboardingPage() {
|
||||
return (
|
||||
<ContentLayout>
|
||||
<SectionHeading title="Onboarding page" />
|
||||
<Grid container spacing={4}>
|
||||
<BlogArticlesCards ids={[1]} />
|
||||
</Grid>
|
||||
</ContentLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// import BlogArticlesCards from "@/components/blogs/BlogArticleCards";
|
||||
// import Grid from "@mui/material/Grid2";
|
||||
import { ContentLayout } from "../../../components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "../../../components/headings/SectionHeading";
|
||||
import OverviewCards from "../../../components/staking/OverviewCards";
|
||||
import StakeTableWithAction from "../../../components/staking/StakeTableWithAction";
|
||||
import SubHeaderRow from "../../../components/staking/SubHeaderRow";
|
||||
|
||||
export default async function StakingPage() {
|
||||
return (
|
||||
<ContentLayout>
|
||||
<SectionHeading title="Staking" />
|
||||
<SubHeaderRow />
|
||||
<OverviewCards />
|
||||
<StakeTableWithAction />
|
||||
{/* <Grid container columnSpacing={5} rowSpacing={5}>
|
||||
<Grid size={12}>
|
||||
<SectionHeading title="Onboarding" />
|
||||
</Grid>
|
||||
<BlogArticlesCards ids={[1]} />
|
||||
</Grid> */}
|
||||
</ContentLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// import BlogArticlesCards from "@/components/blogs/BlogArticleCards";
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
import SectionHeading from "@/components/headings/SectionHeading";
|
||||
import NodeTableWithAction from "@/components/nodeTable/NodeTableWithAction";
|
||||
import NodeAndAddressSearch from "@/components/search/NodeAndAddressSearch";
|
||||
import { Wrapper } from "@/components/wrapper";
|
||||
import { Box, Stack } from "@mui/material";
|
||||
// import Grid from "@mui/material/Grid2";
|
||||
|
||||
export default function ExplorerPage() {
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Wrapper>
|
||||
<Stack gap={5}>
|
||||
<SectionHeading title="Explorer" />
|
||||
<NodeAndAddressSearch />
|
||||
</Stack>
|
||||
<Box sx={{ mt: 5 }}>
|
||||
<NodeTableWithAction />
|
||||
</Box>
|
||||
{/* <Grid container columnSpacing={5} rowSpacing={5} mt={10}>
|
||||
<Grid size={12}>
|
||||
<SectionHeading title="Onboarding" />
|
||||
</Grid>
|
||||
<BlogArticlesCards limit={2} />
|
||||
</Grid> */}
|
||||
</Wrapper>
|
||||
</ContentLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
import { addSeconds } from "date-fns";
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type {
|
||||
CurrentEpochData,
|
||||
ExplorerData,
|
||||
GatewayStatus,
|
||||
IAccountBalancesInfo,
|
||||
IObservatoryNode,
|
||||
IPacketsAndStakingData,
|
||||
NodeData,
|
||||
NodeRewardDetails,
|
||||
NymTokenomics,
|
||||
ObservatoryBalance,
|
||||
} from "./types";
|
||||
import {
|
||||
CURRENT_EPOCH,
|
||||
CURRENT_EPOCH_REWARDS,
|
||||
DATA_OBSERVATORY_BALANCES_URL,
|
||||
DATA_OBSERVATORY_NODES_DELEGATIONS_URL,
|
||||
DATA_OBSERVATORY_NODES_URL,
|
||||
NS_API_MIXNODES_STATS,
|
||||
NYM_ACCOUNT_ADDRESS,
|
||||
NYM_NODES,
|
||||
NYM_PRICES_API,
|
||||
OBSERVATORY_GATEWAYS_URL,
|
||||
} from "./urls";
|
||||
|
||||
// Fetch function for epoch rewards
|
||||
export const fetchEpochRewards = async (): Promise<
|
||||
ExplorerData["currentEpochRewardsData"]
|
||||
> => {
|
||||
const response = await fetch(CURRENT_EPOCH_REWARDS, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
cache: "no-store", // Ensures fresh data on every request
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch epoch rewards");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
};
|
||||
|
||||
// Fetch gateway status based on identity key
|
||||
export const fetchGatewayStatus = async (
|
||||
identityKey: string,
|
||||
): Promise<GatewayStatus | null> => {
|
||||
const response = await fetch(`${OBSERVATORY_GATEWAYS_URL}/${identityKey}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch gateway status");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const fetchNodeInfo = async (
|
||||
id: number,
|
||||
): Promise<IObservatoryNode | undefined> => {
|
||||
const nodes = await fetchObservatoryNodes();
|
||||
return nodes?.find((node) => node.node_id === id);
|
||||
};
|
||||
|
||||
export const fetchNodeIdByIdentityKey = async (
|
||||
identity_key: string,
|
||||
): Promise<number> => {
|
||||
const nodes = await fetchObservatoryNodes();
|
||||
const node = nodes?.find((node) => node.identity_key === identity_key);
|
||||
return node?.node_id || 0;
|
||||
};
|
||||
|
||||
export const fetchNodeDelegations = async (
|
||||
id: number,
|
||||
): Promise<NodeRewardDetails[]> => {
|
||||
const response = await fetch(
|
||||
`${DATA_OBSERVATORY_NODES_DELEGATIONS_URL}/${id}/delegations`,
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch delegations");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const fetchCurrentEpoch = async () => {
|
||||
const response = await fetch(CURRENT_EPOCH, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
cache: "no-store", // Ensures fresh data on every request
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch current epoch data");
|
||||
}
|
||||
|
||||
const data: CurrentEpochData = await response.json();
|
||||
const epochEndTime = addSeconds(
|
||||
new Date(data.current_epoch_start),
|
||||
data.epoch_length.secs,
|
||||
).toISOString();
|
||||
|
||||
return { ...data, current_epoch_end: epochEndTime };
|
||||
};
|
||||
|
||||
// Fetch balances based on the address
|
||||
export const fetchBalances = async (address: string): Promise<number> => {
|
||||
const response = await fetch(`${DATA_OBSERVATORY_BALANCES_URL}/${address}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch balances");
|
||||
}
|
||||
|
||||
const balances: ObservatoryBalance = await response.json();
|
||||
|
||||
// Calculate total stake
|
||||
return (
|
||||
Number(balances.rewards.staking_rewards.amount) +
|
||||
Number(balances.delegated.amount)
|
||||
);
|
||||
};
|
||||
|
||||
// Fetch function to get total staker rewards
|
||||
export const fetchTotalStakerRewards = async (
|
||||
address: string,
|
||||
): Promise<number> => {
|
||||
const response = await fetch(`${DATA_OBSERVATORY_BALANCES_URL}/${address}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch balances");
|
||||
}
|
||||
|
||||
const balances: ObservatoryBalance = await response.json();
|
||||
|
||||
// Return the staking rewards amount
|
||||
return Number(balances.rewards.staking_rewards.amount);
|
||||
};
|
||||
|
||||
// Fetch function to get the original stake
|
||||
export const fetchOriginalStake = async (address: string): Promise<number> => {
|
||||
const response = await fetch(`${DATA_OBSERVATORY_BALANCES_URL}/${address}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch balances");
|
||||
}
|
||||
|
||||
const balances: ObservatoryBalance = await response.json();
|
||||
|
||||
// Return the delegated amount
|
||||
return Number(balances.delegated.amount);
|
||||
};
|
||||
|
||||
export const fetchNoise = async (): Promise<IPacketsAndStakingData[]> => {
|
||||
const response = await fetch(NS_API_MIXNODES_STATS, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
|
||||
const data: IPacketsAndStakingData[] = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
// Fetch Account Balance
|
||||
export const fetchAccountBalance = async (
|
||||
address: string,
|
||||
): Promise<IAccountBalancesInfo> => {
|
||||
const res = await fetch(`${NYM_ACCOUNT_ADDRESS}/${address}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch account balance error from api");
|
||||
}
|
||||
|
||||
const data: IAccountBalancesInfo = await res.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
// 🔹 Fetch Nodes
|
||||
export const fetchNodes = async (): Promise<NodeData[]> => {
|
||||
const res = await fetch(NYM_NODES, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch nodes");
|
||||
}
|
||||
const data: NodeData[] = await res.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
export const fetchObservatoryNodes = async (): Promise<IObservatoryNode[]> => {
|
||||
const allNodes: IObservatoryNode[] = [];
|
||||
let page = 1;
|
||||
const PAGE_SIZE = 200;
|
||||
let hasMoreData = true;
|
||||
|
||||
while (hasMoreData) {
|
||||
const response = await fetch(
|
||||
`${DATA_OBSERVATORY_NODES_URL}?page=${page}&limit=${PAGE_SIZE}`,
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch observatory nodes (page ${page})`);
|
||||
}
|
||||
|
||||
const nodes: IObservatoryNode[] = await response.json();
|
||||
allNodes.push(...nodes);
|
||||
|
||||
if (nodes.length < PAGE_SIZE) {
|
||||
hasMoreData = false; // Stop fetching when the last page has fewer than 200 items
|
||||
} else {
|
||||
page++; // Move to the next page
|
||||
}
|
||||
}
|
||||
|
||||
return allNodes;
|
||||
};
|
||||
|
||||
// 🔹 Fetch NYM Price
|
||||
export const fetchNymPrice = async (): Promise<NymTokenomics> => {
|
||||
const res = await fetch(NYM_PRICES_API, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch NYM price");
|
||||
}
|
||||
const data: NymTokenomics = await res.json();
|
||||
return data;
|
||||
};
|
||||
@@ -0,0 +1,482 @@
|
||||
export type API_RESPONSE<T> = {
|
||||
data: T[];
|
||||
};
|
||||
|
||||
export type Denom = "unym" | "nym";
|
||||
|
||||
export interface IPacketsAndStakingData {
|
||||
date_utc: string;
|
||||
total_packets_received: number;
|
||||
total_packets_sent: number;
|
||||
total_packets_dropped: number;
|
||||
total_stake: number;
|
||||
}
|
||||
|
||||
export interface CurrentEpochData {
|
||||
id: number;
|
||||
current_epoch_id: number;
|
||||
current_epoch_start: string;
|
||||
epoch_length: { secs: number; nanos: number };
|
||||
epochs_in_interval: number;
|
||||
total_elapsed_epochs: number;
|
||||
}
|
||||
export interface ExplorerData {
|
||||
circulatingNymSupplyData: {
|
||||
circulating_supply: { denom: Denom; amount: string };
|
||||
mixmining_reserve: { denom: Denom; amount: string };
|
||||
total_supply: { denom: Denom; amount: string };
|
||||
vesting_tokens: { denom: Denom; amount: string };
|
||||
};
|
||||
nymNodesData: {
|
||||
gateways: {
|
||||
bonded: { count: number; last_updated_utc: string };
|
||||
blacklisted: { count: number; last_updated_utc: string };
|
||||
historical: { count: number; last_updated_utc: string };
|
||||
explorer: { count: number; last_updated_utc: string };
|
||||
};
|
||||
mixnodes: {
|
||||
bonded: {
|
||||
count: number;
|
||||
active: number;
|
||||
inactive: number;
|
||||
reserve: number;
|
||||
last_updated_utc: string;
|
||||
};
|
||||
blacklisted: {
|
||||
count: number;
|
||||
last_updated_utc: string;
|
||||
};
|
||||
historical: { count: number; last_updated_utc: string };
|
||||
};
|
||||
};
|
||||
packetsAndStakingData: IPacketsAndStakingData[];
|
||||
|
||||
currentEpochRewardsData: {
|
||||
interval: {
|
||||
reward_pool: string;
|
||||
staking_supply: string;
|
||||
staking_supply_scale_factor: string;
|
||||
epoch_reward_budget: string;
|
||||
stake_saturation_point: string;
|
||||
active_set_work_factor: string;
|
||||
interval_pool_emission: string;
|
||||
sybil_resistance: string;
|
||||
};
|
||||
rewarded_set: {
|
||||
entry_gateways: number;
|
||||
exit_gateways: number;
|
||||
mixnodes: number;
|
||||
standby: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type NodeDescription = {
|
||||
last_polled: string;
|
||||
host_information: {
|
||||
ip_address: string[];
|
||||
hostname: string;
|
||||
keys: {
|
||||
ed25519: string;
|
||||
x25519: string;
|
||||
x25519_noise: string | null;
|
||||
};
|
||||
};
|
||||
declared_role: {
|
||||
mixnode: boolean;
|
||||
entry: boolean;
|
||||
exit_nr: boolean;
|
||||
exit_ipr: boolean;
|
||||
};
|
||||
auxiliary_details: {
|
||||
location: string;
|
||||
announce_ports: {
|
||||
verloc_port: number | null;
|
||||
mix_port: number | null;
|
||||
};
|
||||
accepted_operator_terms_and_conditions: boolean;
|
||||
};
|
||||
build_information: {
|
||||
binary_name: string;
|
||||
build_timestamp: string;
|
||||
build_version: string;
|
||||
commit_sha: string;
|
||||
commit_timestamp: string;
|
||||
commit_branch: string;
|
||||
rustc_version: string;
|
||||
rustc_channel: string;
|
||||
cargo_profile: string;
|
||||
cargo_triple: string;
|
||||
};
|
||||
network_requester: {
|
||||
address: string;
|
||||
uses_exit_policy: boolean;
|
||||
};
|
||||
ip_packet_router: {
|
||||
address: string;
|
||||
};
|
||||
authenticator: {
|
||||
address: string;
|
||||
};
|
||||
wireguard: string | null;
|
||||
mixnet_websockets: {
|
||||
ws_port: number;
|
||||
wss_port: number | null;
|
||||
};
|
||||
} | null;
|
||||
|
||||
export type BondInformation = {
|
||||
node_id: number;
|
||||
owner: string;
|
||||
original_pledge: {
|
||||
denom: string;
|
||||
amount: string;
|
||||
};
|
||||
bonding_height: number;
|
||||
is_unbonding: boolean;
|
||||
node: {
|
||||
host: string;
|
||||
custom_http_port: number;
|
||||
identity_key: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type RewardingDetails = {
|
||||
cost_params: {
|
||||
profit_margin_percent: string;
|
||||
interval_operating_cost: {
|
||||
denom: string;
|
||||
amount: string;
|
||||
};
|
||||
};
|
||||
operator: string;
|
||||
delegates: string;
|
||||
total_unit_reward: string;
|
||||
unit_delegation: string;
|
||||
last_rewarded_epoch: number;
|
||||
unique_delegations: number;
|
||||
};
|
||||
|
||||
export type Location = {
|
||||
two_letter_iso_country_code?: string;
|
||||
three_letter_iso_country_code?: string;
|
||||
country_name?: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
};
|
||||
|
||||
export type NodeData = {
|
||||
node_id: number;
|
||||
contract_node_type: string;
|
||||
description: NodeDescription;
|
||||
bond_information: BondInformation;
|
||||
rewarding_details: RewardingDetails;
|
||||
location: Location;
|
||||
};
|
||||
|
||||
// ACCOUNT BALANCES
|
||||
|
||||
export interface IRewardDetails {
|
||||
amount_staked: IAmountDetails;
|
||||
node_id: number;
|
||||
node_still_fully_bonded: boolean;
|
||||
rewards: IAmountDetails;
|
||||
}
|
||||
|
||||
export interface IAmountDetails {
|
||||
denom: string;
|
||||
amount: string;
|
||||
}
|
||||
|
||||
export interface IDelegationDetails {
|
||||
node_id: number;
|
||||
delegated: IAmountDetails;
|
||||
height: number;
|
||||
proxy: null | string;
|
||||
}
|
||||
|
||||
export interface IAccountBalancesInfo {
|
||||
accumulated_rewards: IRewardDetails[];
|
||||
address: string;
|
||||
balances: IAmountDetails[];
|
||||
claimable_rewards: IAmountDetails;
|
||||
delegations: IDelegationDetails[];
|
||||
operator_rewards?: null | IAmountDetails;
|
||||
total_delegations: IAmountDetails;
|
||||
total_value: IAmountDetails;
|
||||
vesting_account?: null | string;
|
||||
}
|
||||
|
||||
export interface IObservatoryNode {
|
||||
accepted_tnc: boolean;
|
||||
bonded: boolean;
|
||||
bonding_address: string;
|
||||
description: {
|
||||
authenticator: {
|
||||
address: string;
|
||||
};
|
||||
auxiliary_details: {
|
||||
accepted_operator_terms_and_conditions: boolean;
|
||||
announce_ports: {
|
||||
mix_port: number | null;
|
||||
verloc_port: number | null;
|
||||
};
|
||||
location: string | null;
|
||||
};
|
||||
build_information: {
|
||||
binary_name: string;
|
||||
build_timestamp: string;
|
||||
build_version: string;
|
||||
cargo_profile: string;
|
||||
cargo_triple: string;
|
||||
commit_branch: string;
|
||||
commit_sha: string;
|
||||
commit_timestamp: string;
|
||||
rustc_channel: string;
|
||||
rustc_version: string;
|
||||
};
|
||||
declared_role: {
|
||||
entry: boolean;
|
||||
exit_ipr: boolean;
|
||||
exit_nr: boolean;
|
||||
mixnode: boolean;
|
||||
};
|
||||
host_information: {
|
||||
hostname: string | null;
|
||||
ip_address: string[];
|
||||
};
|
||||
keys: {
|
||||
ed25519: string;
|
||||
x25519: string;
|
||||
x25519_noise: string | null;
|
||||
};
|
||||
ip_packet_router: {
|
||||
address: string;
|
||||
};
|
||||
last_polled: string;
|
||||
mixnet_websockets: {
|
||||
ws_port: number;
|
||||
wss_port: number | null;
|
||||
};
|
||||
network_requester: {
|
||||
address: string;
|
||||
uses_exit_policy: boolean;
|
||||
};
|
||||
wireguard: string | null;
|
||||
geoip: {
|
||||
city: string;
|
||||
country: string;
|
||||
ip_address: string;
|
||||
loc: string;
|
||||
node_id: number;
|
||||
org: string;
|
||||
postal: string;
|
||||
region: string;
|
||||
};
|
||||
};
|
||||
identity_key: string;
|
||||
ip_address: string;
|
||||
node_id: number;
|
||||
node_type: string;
|
||||
original_pledge: number;
|
||||
rewarding_details: {
|
||||
cost_params: {
|
||||
interval_operating_cost: {
|
||||
amount: string;
|
||||
denom: string;
|
||||
};
|
||||
profit_margin_percent: string;
|
||||
};
|
||||
delegates: string;
|
||||
last_rewarded_epoch: number;
|
||||
operator: string;
|
||||
total_unit_reward: string;
|
||||
unique_delegations: number;
|
||||
unit_delegation: string;
|
||||
};
|
||||
self_description: {
|
||||
details: string;
|
||||
moniker: string;
|
||||
security_contact: string;
|
||||
website: string;
|
||||
};
|
||||
total_stake: number;
|
||||
uptime: number;
|
||||
}
|
||||
export interface NodeRewardDetails {
|
||||
amount: {
|
||||
amount: string;
|
||||
denom: string;
|
||||
};
|
||||
cumulative_reward_ratio: string;
|
||||
height: number;
|
||||
node_id: number;
|
||||
owner: string;
|
||||
}
|
||||
|
||||
export type LastProbeResult = {
|
||||
gateway: string;
|
||||
outcome: {
|
||||
as_entry: {
|
||||
can_connect: boolean;
|
||||
can_route: boolean;
|
||||
};
|
||||
as_exit: {
|
||||
can_connect: boolean;
|
||||
can_route_ip_external_v4: boolean;
|
||||
can_route_ip_external_v6: boolean;
|
||||
can_route_ip_v4: boolean;
|
||||
can_route_ip_v6: boolean;
|
||||
};
|
||||
wg: {
|
||||
can_handshake_v4: boolean;
|
||||
can_handshake_v6: boolean;
|
||||
can_register: boolean;
|
||||
can_resolve_dns_v4: boolean;
|
||||
can_resolve_dns_v6: boolean;
|
||||
ping_hosts_performance_v4: number;
|
||||
ping_hosts_performance_v6: number;
|
||||
ping_ips_performance_v4: number;
|
||||
ping_ips_performance_v6: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export type GatewayStatus = {
|
||||
blacklisted: boolean;
|
||||
bonded: boolean;
|
||||
config_score: number;
|
||||
description: {
|
||||
details: string;
|
||||
moniker: string;
|
||||
security_contact: string;
|
||||
website: string;
|
||||
};
|
||||
explorer_pretty_bond: {
|
||||
identity_key: string;
|
||||
location: {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
two_letter_iso_country_code: string;
|
||||
};
|
||||
owner: string;
|
||||
pledge_amount: {
|
||||
amount: string;
|
||||
denom: string;
|
||||
};
|
||||
};
|
||||
gateway_identity_key: string;
|
||||
last_probe_log: string;
|
||||
last_probe_result: LastProbeResult; // Reference to the separate type
|
||||
last_testrun_utc: string;
|
||||
last_updated_utc: string;
|
||||
performance: number;
|
||||
routing_score: number;
|
||||
self_described: {
|
||||
authenticator: {
|
||||
address: string;
|
||||
};
|
||||
auxiliary_details: {
|
||||
accepted_operator_terms_and_conditions: boolean;
|
||||
announce_ports: {
|
||||
mix_port: number | null;
|
||||
verloc_port: number | null;
|
||||
};
|
||||
location: string;
|
||||
};
|
||||
build_information: {
|
||||
binary_name: string;
|
||||
build_timestamp: string;
|
||||
build_version: string;
|
||||
cargo_profile: string;
|
||||
cargo_triple: string;
|
||||
};
|
||||
declared_role: {
|
||||
entry: boolean;
|
||||
exit_ipr: boolean;
|
||||
exit_nr: boolean;
|
||||
mixnode: boolean;
|
||||
};
|
||||
host_information: {
|
||||
hostname: string;
|
||||
ip_address: string[];
|
||||
keys: {
|
||||
ed25519: string;
|
||||
x25519: string;
|
||||
x25519_noise: string | null;
|
||||
};
|
||||
};
|
||||
ip_packet_router: {
|
||||
address: string;
|
||||
};
|
||||
last_polled: string;
|
||||
mixnet_websockets: {
|
||||
ws_port: number;
|
||||
wss_port: number | null;
|
||||
};
|
||||
network_requester: {
|
||||
address: string;
|
||||
uses_exit_policy: boolean;
|
||||
};
|
||||
wireguard: {
|
||||
port: number;
|
||||
public_key: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type BalanceDetails = {
|
||||
amount: number;
|
||||
denom: string;
|
||||
};
|
||||
|
||||
export type ObservatoryRewards = {
|
||||
operator_commissions: BalanceDetails;
|
||||
staking_rewards: BalanceDetails;
|
||||
unlocked: BalanceDetails;
|
||||
};
|
||||
|
||||
export type ObservatoryBalance = {
|
||||
delegated: BalanceDetails;
|
||||
locked: BalanceDetails;
|
||||
rewards: ObservatoryRewards;
|
||||
self_bonded: BalanceDetails;
|
||||
spendable: BalanceDetails;
|
||||
};
|
||||
|
||||
export type Quote = {
|
||||
ath_date: string;
|
||||
ath_price: number;
|
||||
market_cap: number;
|
||||
market_cap_change_24h: number;
|
||||
percent_change_12h: number;
|
||||
percent_change_15m: number;
|
||||
percent_change_1h: number;
|
||||
percent_change_1y: number;
|
||||
percent_change_24h: number;
|
||||
percent_change_30d: number;
|
||||
percent_change_30m: number;
|
||||
percent_change_6h: number;
|
||||
percent_change_7d: number;
|
||||
percent_from_price_ath: number;
|
||||
price: number;
|
||||
volume_24h: number;
|
||||
volume_24h_change_24h: number;
|
||||
};
|
||||
|
||||
export type Quotes = {
|
||||
USD: Quote;
|
||||
};
|
||||
|
||||
export type NymTokenomics = {
|
||||
beta_value: number;
|
||||
first_data_at: string;
|
||||
id: string;
|
||||
last_updated: string;
|
||||
max_supply: number;
|
||||
name: string;
|
||||
quotes: Quotes;
|
||||
rank: number;
|
||||
symbol: string;
|
||||
total_supply: number;
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
export const NYM_NODES =
|
||||
"https://explorer.nymtech.net/api/v1/tmp/unstable/nym-nodes";
|
||||
export const HARBOURMASTER_API_MIXNODES_STATS =
|
||||
"https://harbourmaster.nymtech.net/v2/mixnodes/stats";
|
||||
export const NS_API_MIXNODES_STATS =
|
||||
"https://staging-node-status-api.nymte.ch/v2/mixnodes/stats";
|
||||
|
||||
export const CURRENT_EPOCH =
|
||||
"https://validator.nymtech.net/api/v1/epoch/current";
|
||||
export const CURRENT_EPOCH_REWARDS =
|
||||
"https://validator.nymtech.net/api/v1/epoch/reward_params";
|
||||
export const NYM_NODE_BONDED =
|
||||
"https://validator.nymtech.net/api/v1/nym-nodes/bonded";
|
||||
export const NYM_ACCOUNT_ADDRESS =
|
||||
"https://explorer.nymtech.net/api/v1/tmp/unstable/account";
|
||||
export const NYM_PRICES_API = "https://api.nym.spectredao.net/api/v1/nym-price";
|
||||
export const VALIDATOR_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_VALIDATOR_URL || "https://rpc.nymtech.net";
|
||||
export const DATA_OBSERVATORY_NODES_URL =
|
||||
"https://api.nym.spectredao.net/api/v1/nodes";
|
||||
export const DATA_OBSERVATORY_NODES_DELEGATIONS_URL =
|
||||
"https://api.nym.spectredao.net/api/v1/nodes";
|
||||
export const DATA_OBSERVATORY_DELEGATIONS_URL =
|
||||
"https://api.nym.spectredao.net/api/v1/delegations";
|
||||
export const DATA_OBSERVATORY_BALANCES_URL =
|
||||
"https://api.nym.spectredao.net/api/v1/balances";
|
||||
export const OBSERVATORY_GATEWAYS_URL =
|
||||
"https://mainnet-node-status-api.nymtech.cc/v2/gateways";
|
||||
@@ -0,0 +1 @@
|
||||
export const TABLET_WIDTH = "(min-width:700px)";
|
||||
@@ -0,0 +1,27 @@
|
||||
"use client";
|
||||
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
import { Link } from "@/components/muiLink";
|
||||
import { Button, Stack, Typography } from "@mui/material";
|
||||
|
||||
const ErrorPage = ({ error }: { error: Error }) => {
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Stack spacing={2} justifyContent="flex-start">
|
||||
<Typography variant="body1">
|
||||
An error occurred: {error.message}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
Please try again later or contact support
|
||||
</Typography>
|
||||
<Link href="/" underline="none">
|
||||
<Button variant="contained" sx={{ maxWidth: 100 }} size="small">
|
||||
Home
|
||||
</Button>
|
||||
</Link>
|
||||
</Stack>
|
||||
</ContentLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorPage;
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,34 @@
|
||||
// API
|
||||
import { client } from "../../../lib/strapiClient";
|
||||
|
||||
// Types
|
||||
import type { Languages } from "../../../i18n";
|
||||
|
||||
import type { components } from "@/app/lib/strapi";
|
||||
// Constants
|
||||
import { footerApiPath } from "../../footer/config/constants";
|
||||
|
||||
// Fetch footer data
|
||||
export const getFooter = async (
|
||||
locale: Languages,
|
||||
): Promise<{
|
||||
id?: number;
|
||||
attributes?: components["schemas"]["Footer"];
|
||||
} | null> => {
|
||||
const footer = await client.GET(footerApiPath, {
|
||||
params: {
|
||||
query: {
|
||||
locale,
|
||||
// @ts-expect-error - populate is not typed correctly?
|
||||
|
||||
populate: {
|
||||
linkBlocks: {
|
||||
populate: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return footer?.data?.data ? footer?.data?.data : null;
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
// Types
|
||||
import type { components } from "../../../lib/strapi";
|
||||
|
||||
// Components
|
||||
import { Link } from "@/components/muiLink";
|
||||
|
||||
// MUI Components
|
||||
import { Box, Grid2, Typography } from "@mui/material";
|
||||
|
||||
export const FooterLinks = ({
|
||||
linkBlocks = [],
|
||||
}: {
|
||||
linkBlocks: components["schemas"]["FooterLinkBlockComponent"][];
|
||||
}) => {
|
||||
return (
|
||||
<Grid2
|
||||
container
|
||||
spacing={{ xs: 2, md: 3 }}
|
||||
columns={{ xs: 1, sm: 8, md: 5 }}
|
||||
>
|
||||
{linkBlocks?.map((block) => {
|
||||
return (
|
||||
<Grid2 key={block.id} size={{ xs: 1, sm: 4, md: 1 }}>
|
||||
<Typography
|
||||
component={block?.heading?.level || "h3"}
|
||||
variant="subtitle1"
|
||||
sx={{ mb: 4 }}
|
||||
>
|
||||
{block?.heading?.title}
|
||||
</Typography>
|
||||
<Box
|
||||
component={"ul"}
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
{block?.links?.map((link) => {
|
||||
const isLinkExternal = link.url?.startsWith("http");
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
listStyle: "none",
|
||||
}}
|
||||
component={"li"}
|
||||
key={link.id}
|
||||
>
|
||||
<Link
|
||||
href={link?.url || ""}
|
||||
sx={{
|
||||
textDecoration: "none",
|
||||
"&:hover": {
|
||||
textDecoration: "underline",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography variant="body3">
|
||||
{link.title}
|
||||
{isLinkExternal ? " ↗" : ""}
|
||||
</Typography>
|
||||
</Link>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Grid2>
|
||||
);
|
||||
})}
|
||||
</Grid2>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export const footerApiPath = "/footer";
|
||||
@@ -0,0 +1,68 @@
|
||||
:root {
|
||||
--max-width: 1120px;
|
||||
--border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color-scheme: dark;
|
||||
}
|
||||
}
|
||||
|
||||
.MuiCardActionArea-focusHighlight {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
right: 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #aaa;
|
||||
border-radius: 8px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.reactMarkDownLink a {
|
||||
color: #000000;
|
||||
display: inline;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.reactMarkDownList ul {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.reactMarkDownList ol {
|
||||
margin-left: 20px;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { createInstance } from "i18next";
|
||||
import resourcesToBackend from "i18next-resources-to-backend";
|
||||
import { initReactI18next } from "react-i18next/initReactI18next";
|
||||
import { getOptions } from "./settings";
|
||||
import type { Languages } from "./types";
|
||||
|
||||
const initI18next = async ({ lng, ns }: { lng: Languages; ns?: string }) => {
|
||||
const i18nInstance = createInstance();
|
||||
await i18nInstance
|
||||
.use(initReactI18next)
|
||||
.use(
|
||||
resourcesToBackend(
|
||||
(language: string, namespace: string) =>
|
||||
import(`./locales/${language}/${namespace}.json`),
|
||||
),
|
||||
)
|
||||
.init(getOptions(lng, ns));
|
||||
return i18nInstance;
|
||||
};
|
||||
|
||||
export const useTranslation = async ({
|
||||
lng,
|
||||
ns,
|
||||
options,
|
||||
}: {
|
||||
lng: Languages;
|
||||
ns?: string;
|
||||
options?: { keyPrefix: string };
|
||||
}) => {
|
||||
const i18nextInstance = await initI18next({ lng, ns });
|
||||
return {
|
||||
t: i18nextInstance.getFixedT(
|
||||
lng,
|
||||
Array.isArray(ns) ? ns[0] : ns,
|
||||
options?.keyPrefix,
|
||||
),
|
||||
i18n: i18nextInstance,
|
||||
};
|
||||
};
|
||||
|
||||
export type { Languages, GeneralTranslations } from "./types";
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"title": "Early access to NymVPN",
|
||||
"description": "Try out NymVPN!",
|
||||
"closed": "Sorry, testing is currently closed",
|
||||
"card": {
|
||||
"cta": "Get a key to use Nym VPN",
|
||||
"title": "Use this key information in the NymVPN client",
|
||||
"table": {
|
||||
"addr": "IP address",
|
||||
"privateKey": "Private Key",
|
||||
"publicKey": "Public Key"
|
||||
},
|
||||
"cli": "Use this command to run the CLI:",
|
||||
"cliOptions": "Optionally, specify the entry and exit gateways below to change the CLI command above:"
|
||||
},
|
||||
"vpnFreeTesting": {
|
||||
"hero": {
|
||||
"title": {
|
||||
"firstLine": "NymVPN beta: Access now"
|
||||
},
|
||||
"getCredential": {
|
||||
"title": "Get a NymVPN credential",
|
||||
"description": "Enter the redeem code you received by email or direct message to generate your credential.",
|
||||
"inputLabel": "Redeem code",
|
||||
"ctaText": "Redeem",
|
||||
"prompt": "Need a code? Sign up for the beta tests on our [homepage](/{{lng}})."
|
||||
},
|
||||
"imageAlt": "NymVPN beta access now",
|
||||
"finalSteps": [
|
||||
{
|
||||
"title": "Save your NymVPN credential",
|
||||
"description": "Download, copy, or scan this credential into the NymVPN app. Be aware that credentials expire after a limited period once redeemed."
|
||||
},
|
||||
{
|
||||
"title": "Add the credential ",
|
||||
"description": "Enter your credential into the app, connect, and start testing."
|
||||
}
|
||||
],
|
||||
"finalStepsAlert": " To use your credentials, please ensure you have downloaded and installed the application first. If you haven't yet, you can do it [here](https://nymvpn.com/download)."
|
||||
},
|
||||
"redeemFreePass": {
|
||||
"errors": {
|
||||
"invalidCode": "The code you provided is invalid",
|
||||
"alreadyRedeemed": "The code you provided has already been redeemed",
|
||||
"unknown": "Oh no, something went wrong!"
|
||||
}
|
||||
},
|
||||
|
||||
"firstSection": {
|
||||
"title": "Refining NymVPN with your feedback",
|
||||
"content": [
|
||||
"During the alpha testing phase, NymVPN aims to gather essential feedback from our users regarding our core functionalities, user experience, privacy, and security.",
|
||||
"Your input is invaluable to the NymVPN team, assisting us in making the service more user-friendly and robust for all users.",
|
||||
"Please remember that NymVPN is currently in its experimental stage!"
|
||||
]
|
||||
},
|
||||
"secondSection": {
|
||||
"title": "How Nym will use your feedback",
|
||||
"content": [
|
||||
"***To gather insights on performance and stability***, ensuring that NymVPN operates smoothly across various devices and network conditions",
|
||||
"***To detect and resolve issues***, enhancing the app's privacy and security for all users",
|
||||
"***To improve ease of use***, making NymVPN more intuitive and accessible",
|
||||
"***To prioritize upcoming features***, understanding what our users find the most beneficial"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"title": "Blog",
|
||||
"subtitle": "Latest posts",
|
||||
"description": "Explore the NymVPN blog for the latest in online security and privacy",
|
||||
"banner": {
|
||||
"cta": { "text": "Sign up now", "href": "/" },
|
||||
"title": "Want to help test NymVPN?",
|
||||
|
||||
"bulletPoints": [
|
||||
"Protect your privacy with the anonymous 5-hop mixnet",
|
||||
"Get everyday privacy with the fast 2-hop WireGuard dVPN",
|
||||
"Use for free during the beta test phase"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"title": "1. Create account",
|
||||
"accountGeneration": {
|
||||
"title": "Loging / Create an account",
|
||||
"description": "Generate secret recovery phrase for your account, you will use it to log in into NymVPN",
|
||||
"buttonText": "Generate secret phrase",
|
||||
"generationSection": {
|
||||
"title": "Your secret recovery phrase",
|
||||
"description": "Make sure to write down your 24-word secret phrase and store it in a safe place. You will need it to log into the NymVPN. **Never show your mnemonic to anyone!**",
|
||||
"confirmationText": "I have saved my secret recovery phrase in safe place"
|
||||
}
|
||||
},
|
||||
"orderSumary": {
|
||||
"biannualPlan": "2-year plan",
|
||||
"annualPlan": "1-year plan",
|
||||
"monthlyPlan": "1-month plan",
|
||||
"saveText": "Save",
|
||||
"taxationCountryText1": "Country of taxation:",
|
||||
"taxationCountryText2": "Country of taxation"
|
||||
},
|
||||
"PaymentMethod": {
|
||||
"title": "2. Select payment method",
|
||||
"description": "Zero-knowledge access ensures your payments and identity are private in mixnet/dVPN, though your Nym payment may appear in your financial history.",
|
||||
"payments": {
|
||||
"creditCard": {
|
||||
"type": "credit-card",
|
||||
"title": "Credit card",
|
||||
"isEnabled": true
|
||||
},
|
||||
"googlePay": {
|
||||
"type": "google-pay",
|
||||
"title": "Pay with Google Pay",
|
||||
"isEnabled": false
|
||||
},
|
||||
"applePay": {
|
||||
"type": "apple-pay",
|
||||
"title": "Pay with Apple Pay",
|
||||
"isEnabled": false
|
||||
},
|
||||
"bitcoin": {
|
||||
"type": "bitcoin",
|
||||
"title": "Pay with cryptocurrency",
|
||||
"isEnabled": true
|
||||
},
|
||||
"nymToken": {
|
||||
"type": "nym-token",
|
||||
"title": "Pay with Nym token",
|
||||
"isEnabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"creditCard": {
|
||||
"cardNumberLabel": "Card number",
|
||||
"expiryDateLabel": "Expiration",
|
||||
"cvcLabel": "CVV",
|
||||
"text1": "By submitting your information and continuing to purchase, you accept the [Terms of Service](/terms), [Privacy Policy](/privacy) and electronic document delivery.",
|
||||
"text2": "The Services are subscription based and will automatically renew until canceled. Please see subscription and cancellation terms."
|
||||
},
|
||||
"stripeModal": {
|
||||
"generic_decline": {
|
||||
"title": "Card declined",
|
||||
"subtitle": "Sorry, your card was declined by the bank.",
|
||||
"suggestion": "Please double-check your card details, verify sufficient funds, or contact your bank for assistance.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"insufficient_funds": {
|
||||
"title": "Insufficient Funds",
|
||||
"subtitle": "Oops! It seems there are insufficient funds in your account to complete this transaction.",
|
||||
"suggestion": "Please check your account balance or choose an alternative payment method.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"lost_card": {
|
||||
"title": "Card declined",
|
||||
"subtitle": "Sorry, your card was declined by the bank.",
|
||||
"suggestion": "Please double-check your card details, verify sufficient funds, or contact your bank for assistance.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"stolen_card": {
|
||||
"title": "Card declined",
|
||||
"subtitle": "Sorry, your card was declined by the bank.",
|
||||
"suggestion": "Please double-check your card details, verify sufficient funds, or contact your bank for assistance.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"expired_card": {
|
||||
"title": "Card expired",
|
||||
"subtitle": "Sorry, your card has expired.",
|
||||
"suggestion": "Please use a different card or contact your bank for assistance.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"incorrect_cvc": {
|
||||
"title": "Incorrect CVC",
|
||||
"subtitle": "Sorry, the CVC you entered is incorrect.",
|
||||
"suggestion": "Please double-check your card details and try again.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"incorrect_number": {
|
||||
"title": "Incorrect card number",
|
||||
"subtitle": "Sorry, the card number you entered is incorrect.",
|
||||
"suggestion": "Please double-check your card details and try again.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"processing_error": {
|
||||
"title": "Processing error",
|
||||
"subtitle": "Sorry, we are unable to process your payment at this time.",
|
||||
"suggestion": "Please try again later or contact your bank for assistance.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"card_velocity_exceeded": {
|
||||
"title": "Card declined",
|
||||
"subtitle": "Sorry, your card was declined by the bank.",
|
||||
"suggestion": "Please double-check your card details, verify sufficient funds, or contact your bank for assistance.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"default": {
|
||||
"title": "Error",
|
||||
"subtitle": "Oops! It seems something went bad",
|
||||
"suggestion": "Please double-check your card details, and try again.",
|
||||
"nextButton": { "text": "Review Details", "link": "goBack" }
|
||||
},
|
||||
"required_action": {
|
||||
"title": "Additional action required",
|
||||
"subtitle": "Your payment requires additional action before it can be completed.",
|
||||
"description": "Please follow the instructions provided by your bank to complete the payment.",
|
||||
"nextButton": {
|
||||
"text": "Follow instructions"
|
||||
}
|
||||
},
|
||||
"card_network_error": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"checkout_abandoned": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"network_timeout": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"application_fees_not_allowed": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"server_error": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"service_owntime": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"service_unavailable": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"session_expired": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"browser_not_supported": {
|
||||
"title": "Card network error",
|
||||
"subtitle": "We are unable to process your payment at this time. Please try again later.",
|
||||
"prevButton": "Prev again",
|
||||
"nextButton": {
|
||||
"text": "Next again",
|
||||
"link": "contact",
|
||||
"target": "_self"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"title": "Contact",
|
||||
"description": "Get in touch with the NymVPN team",
|
||||
"contactOptions": [
|
||||
{
|
||||
"title": "Support",
|
||||
"description": "Send us message if you need help. Make sure to check our [Support page](https://support.nymvpn.com/hc/en-us) first ❤️",
|
||||
"link": {
|
||||
"name": "support@nymvpn.com",
|
||||
"href": "mailto:support@nymvpn.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "General",
|
||||
"description": "Get in touch for general inquiries, press or public affairs",
|
||||
"link": {
|
||||
"name": "contact@nymtech.net",
|
||||
"href": "mailto:contact@nymtech.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Community",
|
||||
"description": "Chat directly with the team, Developer Relations and Community Managers on the Nym Matrix, Discord or Telegram groups",
|
||||
"link": {
|
||||
"name": "Community page",
|
||||
"href": "https://nymtech.net/community"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
{
|
||||
"passwordProtectionModal": {
|
||||
"title": "Password",
|
||||
"subtitle": "Please enter the password to access the NymVPN Download page."
|
||||
},
|
||||
"downloadCard": {
|
||||
"mobileSelectText": "Select platform",
|
||||
"mobileSelectLabel": "Choose",
|
||||
"title": "# Download NymVPN for {{selection}}",
|
||||
"features": [
|
||||
"Advanced privacy with the 5-hop mixnet",
|
||||
"Everyday privacy with the 2-hop WireGuard dVPN",
|
||||
"30+ entry and exit locations on all continents"
|
||||
],
|
||||
"cta1": {
|
||||
"id": "download_getnymvpn_button_clicked",
|
||||
"text": "Sign up",
|
||||
"href": "pricing"
|
||||
},
|
||||
"cta2": {
|
||||
"android": {
|
||||
"text": "View F-Droid instructions",
|
||||
"url": "https://nymtech.net/go/github/fdroid"
|
||||
},
|
||||
"ios": {
|
||||
"text": "Test via Apple TestFlight",
|
||||
"url": "https://testflight.apple.com/join/0vmRJNrL"
|
||||
},
|
||||
"linux": { "text": "View install instructions" },
|
||||
"macos": { "text": "Download" },
|
||||
"windows": { "text": "Download" }
|
||||
},
|
||||
"cta3": {
|
||||
"android": {
|
||||
"text": "Download APK",
|
||||
"url": "https://github.com/nymtech/nym-vpn-client/releases{{version}}"
|
||||
}
|
||||
},
|
||||
"alternativeDownload": {
|
||||
"android": "You can also [request](https://support.nymvpn.com/hc/en-us/requests/new) access to Google Play Closed testing or [learn](https://developer.android.com/studio/command-line/apksigner#usage-verify) how to verify APK.",
|
||||
"linux": "Or directly download NymVPN binaries from our [GitHub page](https://nymtech.net/go/github/nym-vpn-client/releases{{version}})."
|
||||
},
|
||||
"versionText": "Latest app version: {{version}}",
|
||||
"sha256Title": "You can verify the app with this SHA-256 fingerprint:"
|
||||
},
|
||||
"howToInstallInstructions": {
|
||||
"linux": [
|
||||
{
|
||||
"title": [
|
||||
"How to install",
|
||||
"NymVPN on Ubuntu 22.04 and Debian-based distributions"
|
||||
],
|
||||
"description": "Follow the instructions below. For installs on Ubuntu 24.04, check our [Help Center](https://support.nymvpn.com/hc/en-us/articles/26068327280529-Does-NymVPN-work-on-Ubuntu-24-04).",
|
||||
"steps": [
|
||||
{
|
||||
"title": "1. Download the Nym repo setup from the Terminal",
|
||||
"textToCopy": "wget https://apt.nymtech.net/pool/main/n/nym-repo-setup/nym-repo-setup_1.0.1_amd64.deb -O /tmp/nym-repo-setup_1.0.1_amd64.deb"
|
||||
},
|
||||
{
|
||||
"title": "2. Install the downloaded file from the Terminal",
|
||||
"textToCopy": "sudo dpkg -i /tmp/nym-repo-setup_1.0.1_amd64.deb"
|
||||
},
|
||||
{
|
||||
"title": "3. Install NymVPN from the Terminal",
|
||||
"textToCopy": "sudo apt install nym-vpn"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": [
|
||||
"How to install",
|
||||
"NymVPN on Arch Linux (and Arch-based) distributions"
|
||||
],
|
||||
"description": "Follow the instructions below",
|
||||
"steps": [
|
||||
{
|
||||
"title": "1. Install the following AUR packages (prebuilt binaries)",
|
||||
"description": "Using your favorite AUR helper/Pacman wrapper",
|
||||
"textToCopy": "yay -S nym-vpnd-bin nym-vpn-app-bin"
|
||||
},
|
||||
{
|
||||
"title": "(1.) Or if you prefer to build from sources",
|
||||
"description": "The packages will take some time to compile",
|
||||
"textToCopy": "yay -S nym-vpnd nym-vpn-app"
|
||||
},
|
||||
{
|
||||
"title": "2. Enable and start the VPN service",
|
||||
"description": "A systemd service is provided, the following command need to be run only once",
|
||||
"textToCopy": "sudo systemctl enable --now nym-vpnd.service"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": ["How to install", "NymVPN on any Linux distribution"],
|
||||
"description": "The client app is provided as a portable AppImage and daemon is provided as a prebuilt binary wrapped as a systemd service",
|
||||
"steps": [
|
||||
{
|
||||
"title": "Install",
|
||||
"textToCopy": "curl -fsSL https://nymtech.net/go/github/nym-vpn-client/raw/main/.pkg/linux/install | bash"
|
||||
},
|
||||
{
|
||||
"title": "Uninstall",
|
||||
"textToCopy": "curl -fsSL https://nymtech.net/go/github/nym-vpn-client/raw/main/.pkg/linux/install | bash -s uninstall"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"darwin": [
|
||||
{
|
||||
"title": ["How to install", "NymVPN on macOS"],
|
||||
"description": "Follow the instructions below",
|
||||
"steps": [
|
||||
{
|
||||
"title": "1. Download and install NymVPN",
|
||||
"description": "To download and install the NymVPN macOS app, click on the \"Download app\" button above. Double-click the downloaded .dmg file to mount the \"NymVPN Installer\" disk image."
|
||||
},
|
||||
{
|
||||
"title": "2. Optional: Verify the SHA-256 hash",
|
||||
"description": "You can verify the SHA-256 hash of the downloaded file."
|
||||
},
|
||||
{
|
||||
"title": "3. Install the app",
|
||||
"description": "In the \"NymVPN Installer\" disk image, drag and drop the NymVPN app in your Application folder. Then, in your Application folder, open the NymVPN app."
|
||||
},
|
||||
{
|
||||
"title": "4. Grant necessary permissions",
|
||||
"description": "Upon opening the NymVPN app, click \"Yes\" in the modal window asking you if you are sure to open it."
|
||||
},
|
||||
{
|
||||
"title": "5. Install the helper tool",
|
||||
"description": "The app opens. Click on \"Connect\". To allow NymVPN to run network connections in the background, install the mandatory NymVPN helper: Type your device or account password, and click \"Install Helper\". The System Settings will open, and a NymVPN line will be added in the \"Allow in the Background\" section."
|
||||
},
|
||||
{
|
||||
"title": "6. Enter your credential and connect",
|
||||
"description": "Click on \"Connect\". Enter your NymVPN account credentials when prompted and enjoy!"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"windows": [
|
||||
{
|
||||
"title": ["How to install", "NymVPN on Windows"],
|
||||
"description": "Follow the instructions below",
|
||||
"steps": [
|
||||
{
|
||||
"title": "1. Download NymVPN",
|
||||
"description": "To download the NymVPN Windows app, click on the \"Download app\" button above."
|
||||
},
|
||||
{
|
||||
"title": "2. Optional: Verify the SHA-256 hash",
|
||||
"description": "You can verify the SHA-256 hash of the downloaded file."
|
||||
},
|
||||
{
|
||||
"title": "3. Install the NymVPN application",
|
||||
"description": "Open the downloaded NymVPN .exe file, and follow the install instructions."
|
||||
},
|
||||
{
|
||||
"title": "4. Optional: Install VCRUNTIME140.dll",
|
||||
"description": "If the install fails because \"VCRUNTIME140.dll was not found\", go to https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170 and download and install the missing DLL for your device. Then complete the NymVPN app install process."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"howUseNym": {
|
||||
"title": "How to use our {{selection}} VPN app",
|
||||
"description": "In 3 simple steps",
|
||||
"enumerationCardProps": [
|
||||
{
|
||||
"iconName": "one",
|
||||
"title": "Get credentials",
|
||||
"description": "Join the NymVPN alpha and redeem your credentials."
|
||||
},
|
||||
{
|
||||
"iconName": "two",
|
||||
"title": "Download",
|
||||
"description": "Get the NymVPN apps for your devices."
|
||||
},
|
||||
{
|
||||
"iconName": "three",
|
||||
"title": "Connect",
|
||||
"description": "Connect to NymVPN private servers."
|
||||
}
|
||||
]
|
||||
},
|
||||
"banner": {
|
||||
"bannerImage": "banner1",
|
||||
"title": ["Fast and secure VPN for {{dynamicText}}"],
|
||||
"text": [
|
||||
"Pick the 2-hop WireGuard dVPN mode for a faster {{dynamicText}} VPN connection or get advanced privacy with the 5-hop mixnet mode, all in one app."
|
||||
]
|
||||
},
|
||||
"faqs": {
|
||||
"title": "VPN for {{dynamicText}} frequently asked questions",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "Is NymVPN compatible with all operating systems?",
|
||||
"description": "NymVPN is compatible with the main operating systems, including Android, iOS, Linux, macOS and Windows. We will expand support to additional operating systems, browsers and devices in the near future."
|
||||
},
|
||||
{
|
||||
"title": "How many devices can I use with one NymVPN subscription?",
|
||||
"description": "NymVPN will allow simultaneous connections on multiple devices. Stay tuned!"
|
||||
},
|
||||
{
|
||||
"title": "Does NymVPN offer a money-back guarantee?",
|
||||
"description": "NymVPN will offer either 7-day or 30-day prorated money-back guarantees. Specific terms may apply based on the subscription and payment method."
|
||||
},
|
||||
{
|
||||
"title": "Does NymVPN offer a free trial?",
|
||||
"description": "NymVPN does not offer a free trial at the moment. However, we are continuously developing new offerings, so stay tuned for updates."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
{
|
||||
"title": "Features",
|
||||
"subtitle": "Dive into the magic that makes NymVPN stand out in the digital crowd",
|
||||
"categories": [
|
||||
{
|
||||
"title": "Technology",
|
||||
"features": [
|
||||
{
|
||||
"title": "5-hop novel mixnet",
|
||||
"text": "Split and encrypt your data into smaller packets, which are mixed, rebuilt and decrypted on the receiving side; Further protect your data and metadata with cover traffic and time delays.",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://nymtech.net/about/mixnet"
|
||||
},
|
||||
"iconName": "mixnet",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"title": "2-hop secure WireGuard decentralized VPN",
|
||||
"text": "Go speedy with a two-hop onion encryption and no cover traffic.",
|
||||
"iconName": "wireguard",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"title": "Robust cryptographic primitives",
|
||||
"text": "Protect your data with with AES128, ChaChaPoly and BLAKE2.",
|
||||
"iconName": "cryptographicPrimitives"
|
||||
},
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Zero-knowledge proof access",
|
||||
"text": "Access the network without revealing sensitive information, enhancing your privacy and security.",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://nymtech.net/about/zk-nyms"
|
||||
},
|
||||
"iconName": "zero"
|
||||
},
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Key rotation / forward secrecy / replay protection",
|
||||
"text": "Keep your data confidential with sophisticated, cutting-edge cryptographic techniques.",
|
||||
"iconName": "key"
|
||||
},
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Censorship resistance",
|
||||
"text": "Bypass internet censorship with innovative traffic obfuscation.",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://blog.nymtech.net/nym-censorship-resistance-update-d2f5e08e66d1"
|
||||
},
|
||||
"iconName": "censorship",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Post-quantum cryptography",
|
||||
"text": "Quantum-encrypt your data for long-term secrecy.",
|
||||
"iconName": "quantum",
|
||||
"isMedium": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "In-app features",
|
||||
"features": [
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Killswitch and autoconnect",
|
||||
"text": "Automatically connect, or suspend traffic as needed for uninterrupted protection.",
|
||||
"iconName": "killswitch"
|
||||
},
|
||||
{
|
||||
"title": "Advanced privacy in one app",
|
||||
"text": "Benefit from unmatched privacy and seamless speeds, all within a single application.",
|
||||
"iconName": "oneApp",
|
||||
"isLarge": true
|
||||
},
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Privacy-enhancing payments",
|
||||
"text": "Conceal your identity when buying the subscription, thanks to zero-knowledge credentials.",
|
||||
"iconName": "payment",
|
||||
"isLarge": true
|
||||
},
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Split tunnelling",
|
||||
"text": "Pick where to route your traffic, for each of your needs: the mixnet for superior privacy and the decentralized VPN for performance.",
|
||||
"iconName": "split"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Benefits",
|
||||
"features": [
|
||||
{
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Unlinkable online activity",
|
||||
"text": "Prevent the correlation of your IPs with network requests, ensuring a robust safeguard against unauthorized access to your traffic and private data.",
|
||||
"iconName": "unlinkable"
|
||||
},
|
||||
{
|
||||
"title": "Decentralized and incentivized network",
|
||||
"text": "Connect via a failsafe, independent and community-governed network structure.",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://nymtech.net/build/nodes"
|
||||
},
|
||||
"iconName": "decentralized"
|
||||
},
|
||||
{
|
||||
"title": "Swiss headquartered",
|
||||
"text": "Benefit from Swiss jurisdiction and data regulations, for maximum protection.",
|
||||
"iconName": "swiss"
|
||||
},
|
||||
{
|
||||
"title": "Open source",
|
||||
"text": "Enjoy products developed in a transparent and collaborative manner, open to public contributions and scrutiny.",
|
||||
"cta": { "text": "Learn more", "href": "https://nymtech.net/docs" },
|
||||
"iconName": "openSource"
|
||||
},
|
||||
{
|
||||
"title": "World-class privacy and cryptography expert team",
|
||||
"text": "Benefit from the support of an elite team with PhDs, peer-reviewed work, and strong academic credentials (e.g., INRIA, KU Leuven, MIT, UCL).",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://nymtech.net/about/team"
|
||||
},
|
||||
"iconName": "team",
|
||||
"isLarge": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"langSelectorLabel": "Language",
|
||||
"socialLinks": [
|
||||
{ "name": "Telegram", "link": "https://nymtech.net/go/telegram" },
|
||||
{ "name": "Twitter", "link": "https://nymtech.net/go/x" },
|
||||
{
|
||||
"name": "Discord",
|
||||
"link": "https://nymtech.net/go/discord"
|
||||
},
|
||||
{ "name": "GitHub", "link": "https://nymtech.net/go/github" },
|
||||
{ "name": "YouTube", "link": "https://nymtech.net/go/youtube" }
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"title": "Get started",
|
||||
"links": [
|
||||
{
|
||||
"name": "Download NymVPN",
|
||||
"link": "download"
|
||||
},
|
||||
{
|
||||
"name": "Test NymVPN",
|
||||
"link": "alpha"
|
||||
},
|
||||
{
|
||||
"name": "Become an operator",
|
||||
"link": "https://nymtech.net/operators"
|
||||
},
|
||||
{ "name": "Visit nymtech.net", "link": "https://nymtech.net" },
|
||||
{
|
||||
"name": "Subscribe to Nym’s newsletter",
|
||||
"link": "https://eepurl.com/gdor_f"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Popular blog posts",
|
||||
"links": [
|
||||
{ "name": "Decentralized VPNs", "link": "blog/decentralized-vpns" },
|
||||
{
|
||||
"name": "Blockchain-based VPNs",
|
||||
"link": "blog/blockchain-based-vpns-all-you-need-to-know"
|
||||
},
|
||||
{
|
||||
"name": "Privacy protection with VPN",
|
||||
"link": "blog/how-does-a-vpn-protect-you-and-your-privacy"
|
||||
},
|
||||
{
|
||||
"name": "Tracking prevention with VPN",
|
||||
"link": "blog/can-you-be-tracked-while-using-a-vpn"
|
||||
},
|
||||
{
|
||||
"name": "Online privacy threats",
|
||||
"link": "blog/internet-privacy-main-threats-and-protections"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Resources",
|
||||
"links": [
|
||||
{ "name": "NymVPN blog", "link": "blog" },
|
||||
{
|
||||
"name": "NymVPN public roadmap",
|
||||
"link": "https://trello.com/b/qVhBo3e2/nymvpn-public-roadmap"
|
||||
},
|
||||
{
|
||||
"name": "NymVPN localization",
|
||||
"link": "https://weblate.nymte.ch/projects/nymvpn/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Company",
|
||||
"links": [
|
||||
{ "name": "Contact", "link": "contact" },
|
||||
{
|
||||
"name": "Careers",
|
||||
"link": "https://nym.teamtailor.com/"
|
||||
},
|
||||
{
|
||||
"name": "Support",
|
||||
"link": "https://support.nymvpn.com/hc/en-us"
|
||||
},
|
||||
{ "name": "Imprint", "link": "imprint" },
|
||||
{ "name": "Privacy statements", "link": "privacy" },
|
||||
{ "name": "Terms of use", "link": "terms" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"trademarkText": "WireGuard is a registered trademark of Jason A. Donenfeld",
|
||||
"rightsText": "© 2024 Nym Technologies S.A., all rights reserved"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"title": "Redeem your NymVPN free pass",
|
||||
"description": "You can try out NymVPN for free if you have a received a code by email or in a direct message",
|
||||
"instructions": {
|
||||
"getStarted": {
|
||||
"label": "Enter code",
|
||||
"description": "Please enter your redemption code",
|
||||
"warning": "You will only be able to download the free pass once, so please make sure you are using a device where you copy the free pass into the NymVPN app, or keep it somewhere safe like a password manager"
|
||||
},
|
||||
"issuing": {
|
||||
"label": "Get free pass",
|
||||
"description": "Getting your free pass...",
|
||||
"info": "Your free pass will be valid for one week from today. So please make sure you use it before it expires!"
|
||||
},
|
||||
"download": {
|
||||
"label": "Copy into app",
|
||||
"description": "🎉 Your free pass is downloading as a file in the background and is also ready to copy and paste into the NymVPN app",
|
||||
"info": "Your free pass will be valid for one week from today. So please make sure you use it before it expires!"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"invalidCode": "The code you provided is invalid",
|
||||
"alreadyRedeemed": "The code you provided has already been redeemed",
|
||||
"unknown": "Oh no, something went wrong!"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"alerts": {
|
||||
"alpha": "NymVPN is currently in its beta release. To instantly get your access credentials, sign up on our [homepage](/en)."
|
||||
},
|
||||
"copyToClipboard": {
|
||||
"copy": "Copy",
|
||||
"copied": "Copied",
|
||||
"copiedTimeLimitation": "Copied to clipboard for {{time}}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"hero": {
|
||||
"title": "Privacy made simple",
|
||||
"subtitle": "Enjoy secure browsing, streaming, and messaging with our unmatched blend of decentralized VPN, mixnet, and zero-knowledge payments.",
|
||||
"preCta": "Sign up now for instant free beta credentials.",
|
||||
"form": {
|
||||
"placeholder": "Your email address",
|
||||
"ctaText": "Submit"
|
||||
}
|
||||
},
|
||||
"featuresSection": {
|
||||
"title": "Features",
|
||||
"featuresGrid": [
|
||||
{
|
||||
"category": "Technology",
|
||||
"title": "5-hop novel Nym mixnet",
|
||||
"text": "Elevated privacy with advanced onion encryption, data splitting, mixing, and concealment in cover traffic.",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://nymtech.net/about/mixnet"
|
||||
},
|
||||
"iconName": "mixnet",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"title": "2-hop secure WireGuard decentralized VPN",
|
||||
"text": "Swift two-hop decentralized mode with onion encryption but no cover traffic.",
|
||||
"iconName": "wireguard",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"category": "Benefits",
|
||||
"title": "Unlinkable online activity",
|
||||
"text": "Inability to correlate IPs with network requests, by design. No backdoor or covert access to traffic and private data.",
|
||||
"iconName": "unlinkable"
|
||||
},
|
||||
{
|
||||
"category": "In-app features",
|
||||
"title": "Advanced privacy in one app",
|
||||
"text": "Unmatched privacy within a single application thanks to the unique blend of mixnet and decentralized VPN.",
|
||||
"iconName": "oneApp"
|
||||
},
|
||||
{
|
||||
"category": "In-app features",
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Privacy-enhancing payments",
|
||||
"text": "Zero-knowledge payment method, ensuring privacy and concealing user identity for transactions.",
|
||||
"iconName": "payment"
|
||||
}
|
||||
],
|
||||
"featuresCta": {
|
||||
"title": "Discover NymVPN features",
|
||||
"href": "features"
|
||||
}
|
||||
},
|
||||
"fullWidthBanner": {
|
||||
"title": "Advanced privacy. In your hands.",
|
||||
"text": [
|
||||
"Tailor your privacy options to suit your requirements. Opt for the fast decentralized VPN or prioritize higher privacy with the mixnet, all within a single app, while benefitting from the high redundancy of the decentralized Nym network and unlinkability of your data."
|
||||
]
|
||||
},
|
||||
"centeredBanner": {
|
||||
"title": "Robust security for all your devices",
|
||||
"text": [
|
||||
"Protect against eavesdroppers and corporate / government surveillance. Prevent data leaks with our upcoming built-in kill switch, available across all your devices with just one account."
|
||||
]
|
||||
},
|
||||
"comparationTable": {
|
||||
"title": "Digital integrity guaranteed",
|
||||
"subtitle": "See how NymVPN compares with the alternatives",
|
||||
"heads": ["", "NymVPN", "VPNs", "decentralized VPNs", "Tor"],
|
||||
"rows": [
|
||||
{
|
||||
"title": "Independent multi-hop routing",
|
||||
"description": "Traffic routed via at least 2 independent server hops"
|
||||
},
|
||||
{
|
||||
"title": "Unlinkable online activity",
|
||||
"description": "Impossible to correlate traffic with end users"
|
||||
},
|
||||
{
|
||||
"title": "Privacy-preserving payments",
|
||||
"description": "User identity concealment during VPN service subscription"
|
||||
},
|
||||
{
|
||||
"title": "Traffic analysis resistance",
|
||||
"description": "Packet shuffling and encryption to protect your data and metadata"
|
||||
},
|
||||
{
|
||||
"title": "High quality of service",
|
||||
"description": "Incentivization of server operators for a high quality of service"
|
||||
},
|
||||
{
|
||||
"title": "Open source",
|
||||
"description": "Software development with publicly accessible source code"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mailCollectionBanner": {
|
||||
"title": "Join the NymVPN beta phase",
|
||||
"text": [
|
||||
"Sign up now and instantly receive your free access credentials. Join the community on [Discord](https://nymtech.net/go/discord) or [Matrix](https://matrix.to/#/#NymVPN:nymtech.chat)."
|
||||
],
|
||||
"form": {
|
||||
"placeholder": "Your email address",
|
||||
"ctaText": "Submit"
|
||||
}
|
||||
},
|
||||
"inNumbers": [
|
||||
{
|
||||
"title": "750+",
|
||||
"subtitle": "Privacy-mixing nodes",
|
||||
"text": "Experience unparalleled protection – hundreds of independently-run nodes randomly chosen at every epoch",
|
||||
"icon": "privacyMixingNodes",
|
||||
"link": "https://explorer.nymtech.net/network-components/mixnodes"
|
||||
},
|
||||
{
|
||||
"title": "110+",
|
||||
"subtitle": "Exit servers",
|
||||
"text": "Enjoy a resilient, high-quality set of exit gateways and network requesters",
|
||||
"icon": "exitServers",
|
||||
"link": "https://explorer.nymtech.net/network-components/gateways"
|
||||
},
|
||||
{
|
||||
"title": "30+",
|
||||
"subtitle": "Countries",
|
||||
"text": "Access our extensive global network spanning Africa, Americas, Asia, Europe and Oceania",
|
||||
"icon": "countries",
|
||||
"link": "https://explorer.nymtech.net/nodemap"
|
||||
}
|
||||
],
|
||||
"socialReviews": {
|
||||
"title": "Don't just take our word for it",
|
||||
"subtitle": "Featured in leading publications and trusted by privacy advocates.",
|
||||
"reviews": [
|
||||
{
|
||||
"author": "Chelsea Manning",
|
||||
"mediaName": "Activist, whistleblower, Security Consultant @ Nym",
|
||||
"authorImg": "chelsea-manning",
|
||||
"text": "As technology evolves, so do the challenges to our privacy. NymVPN isn't just a response to these challenges; it's a proactive privacy and censorship resistance solution designed to stay ahead of the curve in protecting user data in an increasingly tense and uncertain world."
|
||||
},
|
||||
{
|
||||
"date": "11:22 AM · Nov 18, 2023",
|
||||
"social": "twitter",
|
||||
"author": "🏴☠️ Bluetouff",
|
||||
"mediaName": "@bluetouff, blogger and activist",
|
||||
"authorImg": "bluetouff",
|
||||
"text": "If you want to test a decentralized #VPN, it's over here 👉👉 [https://nymvpn.com/en](https://nymvpn.com/en) 👈👈... No more nonsense about zero logs with Nord-thingies and big US VPNs subjected to the Patriot Act... Go decentralized and try a serious anonymization network by joining the beta",
|
||||
"hashtags": "#VPN",
|
||||
"url": "https://twitter.com/bluetouff/status/1725821717245739165"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"title": "Imprint",
|
||||
"address": [
|
||||
"NYM Technologies SA",
|
||||
"place Numa-Droz 2",
|
||||
"2000 Neuchâtel",
|
||||
"Switzerland",
|
||||
" ",
|
||||
"Company registration: CH-020-3042168-7",
|
||||
"UID: CHE-367.426.629",
|
||||
" ",
|
||||
"Email: <contact@nymtech.net>",
|
||||
" ",
|
||||
"Despite careful control of the content, we assume no liability for the content of external links. The operators of the linked pages are solely responsible for their content."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"hero": {
|
||||
"title": "NymVPN pricing",
|
||||
"subtitle": "Discover our VPN plans offering transparent and flexible pricing for your online security",
|
||||
"prices": [
|
||||
{
|
||||
"Betatag": "Beta",
|
||||
"title": "1-month plan",
|
||||
"price": "€11.99 ",
|
||||
"priceExtension": "/Month",
|
||||
"subPrice": "€11.99 for 1 month",
|
||||
"notPrice": "",
|
||||
"cta": {
|
||||
"text": "Select plan",
|
||||
"href": "https://nymtech.net/about/mixnet"
|
||||
},
|
||||
"popular": "",
|
||||
"plan": "monthly_plan"
|
||||
},
|
||||
{
|
||||
"Betatag": "Beta",
|
||||
"title": "2-year plan",
|
||||
"price": "€6.99 ",
|
||||
"priceExtension": "/Month",
|
||||
"subPrice": "€167.76 for 2 years",
|
||||
"notPrice": "€287.76",
|
||||
"cta": {
|
||||
"text": "Select plan",
|
||||
"href": "https://nymtech.net/about/mixnet"
|
||||
},
|
||||
"popular": "POPULAR",
|
||||
"plan": "biannual_plan"
|
||||
},
|
||||
{
|
||||
"Betatag": "Beta",
|
||||
"title": "1-year plan",
|
||||
"price": "€7.99 ",
|
||||
"priceExtension": "/Month",
|
||||
"subPrice": "€95.88 for 1 year",
|
||||
"notPrice": "€143.88",
|
||||
|
||||
"cta": {
|
||||
"text": "Select plan",
|
||||
"href": "https://nymtech.net/about/mixnet"
|
||||
},
|
||||
"popular": "",
|
||||
"plan": "annual_plan"
|
||||
}
|
||||
]
|
||||
},
|
||||
"featuresSection": {
|
||||
"title": "Why choose NymVPN",
|
||||
"featuresGrid": [
|
||||
{
|
||||
"category": "Technology",
|
||||
"title": "5-hop novel Nym mixnet",
|
||||
"text": "Elevated privacy with advanced onion encryption, data splitting, mixing, and concealment in cover traffic.",
|
||||
"cta": {
|
||||
"text": "Learn more",
|
||||
"href": "https://nymtech.net/about/mixnet"
|
||||
},
|
||||
"iconName": "mixnet",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"title": "2-hop secure WireGuard decentralized VPN",
|
||||
"text": "Swift two-hop decentralized mode with onion encryption but no cover traffic.",
|
||||
"iconName": "wireguard",
|
||||
"isMedium": true
|
||||
},
|
||||
{
|
||||
"category": "Benefits",
|
||||
"title": "Unlinkable online activity",
|
||||
"text": "Inability to correlate IPs with network requests, by design. No backdoor or covert access to traffic and private data.",
|
||||
"iconName": "unlinkable"
|
||||
},
|
||||
{
|
||||
"category": "In-app features",
|
||||
"title": "Advanced privacy in one app",
|
||||
"text": "Unmatched privacy within a single application thanks to the unique blend of mixnet and decentralized VPN.",
|
||||
"iconName": "oneApp"
|
||||
},
|
||||
{
|
||||
"category": "In-app features",
|
||||
"categoryStatus": "Coming soon",
|
||||
"title": "Privacy-enhancing payments",
|
||||
"text": "Zero-knowledge payment method, ensuring privacy and concealing user identity for transactions.",
|
||||
"iconName": "payment"
|
||||
}
|
||||
],
|
||||
"featuresCta": {
|
||||
"title": "Discover all NymVPN features",
|
||||
"href": "features"
|
||||
}
|
||||
},
|
||||
"faqsSection": {
|
||||
"title": "NymVPN pricing frequently asked questions",
|
||||
"description": "Do you have questions about our pricing? Find quick answers here.",
|
||||
"faqsCategories": [
|
||||
{
|
||||
"category": "Pricing",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "Is there a NymVPN free trial?",
|
||||
"description": "At the moment NymVPN does not offer a free trial, but we offer a 30-day money-back guarantee."
|
||||
},
|
||||
{
|
||||
"title": "What payment methods can I use to buy NymVPN?",
|
||||
"description": "You can purchase our VPN with various paying methods, including debit/credit cards and cryptocurrencies like NYM or Bitcoin."
|
||||
},
|
||||
{
|
||||
"title": "Does NymVPN offer a money-back guarantee?",
|
||||
"description": "Yes, we offer a hassle-free 30-day money-back guarantee."
|
||||
},
|
||||
{
|
||||
"title": "Does NymVPN offer a special pricing for businesses or organizations?",
|
||||
"description": "If you represent a business or an organization, contact our Sales team at [contact@nymtech.net](mailto:contact@nymtech.net) to find out how NymVPN can help you."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "General",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "What is NymVPN?",
|
||||
"description": "NymVPN is a privacy-focused network-protection product that combines Nym's secure mixnet technology with a decentralized WireGuard VPN for comprehensive online privacy across all use cases."
|
||||
},
|
||||
{
|
||||
"title": "What makes NymVPN different from traditional VPNs?",
|
||||
"description": "NymVPN distinguishes itself with its distinctive blend of a mixnet and a decentralized VPN. By design, and in contrast to traditional VPNs, NymVPN cannot access user data or browsing history, nor link traffic to personal information, such as email or payment details. NymVPN also distinguishes itself with a multi-hop routing by default. This combination offers unparalleled online privacy and security across all online use cases. Check our [NymVPN litepaper](https://nymvpn.com/nymVPN-litepaper.pdf) for more detailed information."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "What features does NymVPN offer?",
|
||||
"description": "Find out more about all our VPN features on this page: [NymVPN features](https://nymvpn.com/features)."
|
||||
},
|
||||
{
|
||||
"title": "Do I get a new IP address every time I use NymVPN?",
|
||||
"description": "When you launch NymVPN, you get connected to a randomly select exit server, either globally or within the country you have selected. Nym cannot guarantee the attribution of a different IP address for every connection."
|
||||
},
|
||||
{
|
||||
"title": "When will the updated NymVPN be available?",
|
||||
"description": "To stay informed and get early access, we recommend [signing up to our waitlist](http://eepurl.com/iDk0h-/). Follow our [Twitter account](https://nymtech.net/go/x) for announcements and updates."
|
||||
},
|
||||
{
|
||||
"title": "What is the expected duration of the beta phase?",
|
||||
"description": "The expected duration of the beta phase for NymVPN will be announced in our official communications and updates. Stay tuned for more information on the beta timeline."
|
||||
},
|
||||
{
|
||||
"title": "How can I provide feedback or report issues during the beta?",
|
||||
"description": "You can provide feedback using your preferred format, whether it's through the in-app report feature, [email](mailto:contact@nymtech.net), [social media](https://nymtech.net/go/x), or our [Discord](https://nymtech.net/go/discord) / [Matrix](https://matrix.to/#/#NymVPN:nymtech.chat) channels. Your input is valuable to us!"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
{
|
||||
"links": ["website", "apps"],
|
||||
"website": {
|
||||
"title": "NymVPN website privacy statement",
|
||||
"subtitle": "",
|
||||
"content": [
|
||||
{
|
||||
"title": "",
|
||||
"newlines": ["Version 1.1, last updated on February 19, 2024"]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"newlines": [
|
||||
"Thank you for visiting our website nymvpn.com and for your interest in our company.",
|
||||
"Nym Technologies SA, a Swiss Company established under the laws of Switzerland, and registered with the Chamber of Commerce and Industry of Switzerland with number CHE-367.426.629 operates a website hosted at the URL https://nymvpn.com/.",
|
||||
"In this privacy statement (the “Statement”) we will explain how our organization uses your personal data that we collect when you use our website. Our data protection practice is in accordance with the legal regulations of the Swiss Federal Act on Data Protection and its ordinances (“FADP”). This Statement serves to fulfill the information obligations arising from the FADP. These can be found, for example, in article 19 ff. FADP."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "TABLE OF CONTENT",
|
||||
"newlines": [
|
||||
"The followings topics will be discussed in this Statement:",
|
||||
"I. Collecting personal data",
|
||||
"II. How we get your personal data",
|
||||
"III. Purposes of data processing",
|
||||
"IV. The personal data controller",
|
||||
"V. With whom we share your personal data",
|
||||
"VI. Newsletter",
|
||||
"VII. How we store your personal data",
|
||||
"VIII. Your data protection rights",
|
||||
"IX. What are cookies?",
|
||||
"X. How do we use cookies?",
|
||||
"XI. Stripe",
|
||||
"XII. Changes to our Website privacy statement",
|
||||
"XIII. How to contact us",
|
||||
"XIV. Contact the appropriate legal authority",
|
||||
"VX. Governing law"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "I. COLLECTING PERSONAL DATA",
|
||||
"newlines": [
|
||||
"We collect the following personal data:",
|
||||
"- Information about the browser type and version used;",
|
||||
"- The operating system of the retrieval device;",
|
||||
"- Date and time of access;",
|
||||
"- Website and resources (image, files, other page content) accessed on our website;",
|
||||
"- Referrer URLs;",
|
||||
"- Information about the features you use, the frequency of usage, and the duration of your sessions;",
|
||||
"- Inferred location, this is a rough approximation of your location which may be tens of kilometers off;",
|
||||
"- Screen size;",
|
||||
"- Device model; and",
|
||||
"- On-site behavior (page viewed, time spent etc.).",
|
||||
"Additionally, when you fill in forms to request additional information, join our newsletters or to sign-up to become a customer, we process the data provided by you in those forms."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "II. HOW WE GET YOUR PERSONAL DATA",
|
||||
"newlines": [
|
||||
"As a side-effect of how web browsers work, you directly provide us with the personal data we collect. We collect personal data and process personal data when you, among others:",
|
||||
"- Register online or place an order for any of our products or services;",
|
||||
"- Use or view our website; and",
|
||||
"- Subscribe to our waitlist or newsletter."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "III. PURPOSES OF DATA PROCESSING",
|
||||
"newlines": [
|
||||
"We have among others the following reasons (purposes) for processing personal data:",
|
||||
"- In order to operate the website;",
|
||||
"- To iteratively improve the website;",
|
||||
"- To address bugs;",
|
||||
"- To improve our commercial offerings;",
|
||||
"- To better localize our website; and",
|
||||
"- To keep you updated about Nym and its products (through our newsletter).",
|
||||
"These purposes can all be considered legitimate interests of Nym."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IV. THE PERSONAL DATA CONTROLLER",
|
||||
"newlines": [
|
||||
"We are the controller of personal data with regard to the website."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "V. WITH WHOM WE SHARE YOUR PERSONAL DATA",
|
||||
"newlines": [
|
||||
"With third parties:",
|
||||
"We provide personal data only to parties who help us optimize our services, execute the agreement with you or to parties with whom we are legally obliged to share the data.",
|
||||
"We may share your personal data with Stripe, our payment processor, in case you enter into a contract with us on our website.",
|
||||
"Additionally, we make use of data processors with whom we have entered into data processing agreements. One notable example is Mailchimp, which does process data in the USA. These data processors remain our responsibility and are therefore not third parties, even though they may appear as such to you.",
|
||||
"Cross-border data transfer:",
|
||||
"Nym is based in Switzerland, which means that a third country relationship exists in relation to the European Union (the “EU”) and the European Economic Area (the “EEA”). The EU/EEA has deemed the Swiss data protection regulations to be adequate and vice versa. As part of the provision of services, personal data is transferred to the EU/EEA for further processing and vice versa. This means that your data will only be processed on the basis of special guarantees and that the third country in the EEA has an adequate level of data protection. For some of the third-party service providers, we may transfer your data to one of their databases outside Switzerland or the EEA, potentially including countries which may not have an adequate level of protection for your personal data. In such event, we enter into agreements with such third parties ensuring an adequate level of protection for your personal data.",
|
||||
"Sharing with authorities:",
|
||||
"It is possible that we will need to disclose your personal data when required by law or if we believe that disclosure is necessary to investigate, prevent, or take action regarding suspected or actual illegal activities or to assist government enforcement agencies, investigate and defend ourselves against any third-party claims or allegations, protect the security or integrity of our website or exercise or protect the rights and safety of our users, personnel, or others. We attempt to notify you about legal demands for your personal data when appropriate in our judgment and technically feasible, unless prohibited by law or court order or when the request is an emergency. We may dispute such demands when we believe, in our discretion, that the requests are overbroad, vague or lack proper authority, but we do not promise to challenge every demand."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VI. NEWSLETTER",
|
||||
"newlines": [
|
||||
"You can subscribe to our newsletter via our website. We receive for this:",
|
||||
"- Your email address.",
|
||||
"When you sign up for the newsletter, you consent to the processing of your personal data for the purpose of sending the newsletter. We use a marketing platform for this purpose. In every newsletter you receive from us, we offer the opportunity to unsubscribe. The data in our marketing platform are processed in the USA.",
|
||||
"Your personal data shared with the Nym Newsletter provider Mailchimp will be stored on servers located in the United States of America, the United Kingdom as well as in the EU. Mailchimp will process your data in the USA and has submitted to the EU-USA Privacy Shield, for its processing in the United Kingdom the Commission adequacy decision on the United Kingdom applies. We have also concluded standard data protection clauses with Mailchimp. Contact details you provide for sending newsletters are deleted [one year; TBC] after the last newsletter has been sent."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VII. HOW WE STORE YOUR PERSONAL DATA",
|
||||
"newlines": [
|
||||
"We take the protection of your data seriously and take appropriate measures to prevent misuse, loss, unauthorized access, unwanted disclosure and unauthorized modification, but no method of transmission over the internet, or method of electronic storage is 100% secure.",
|
||||
"We may retain de-personalized (anonymous) information after the deletion of your personal data."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VIII. YOUR DATA PROTECTION RIGHTS",
|
||||
"newlines": [
|
||||
"We would like to make sure you are fully aware of all your data protection rights. If we hold personal data about you under the FADP, you have rights including:",
|
||||
"- The right to be informed – You have the right to be informed of the collection and processing of your personal data.",
|
||||
"- The right of access - You have the right to request us for copies of your personal data. We may charge you a small fee for this service.",
|
||||
"- The right to rectification - You have the right to request that we correct any information that you believe is inaccurate. You also have the right to request us to complete information you believe is incomplete.",
|
||||
"- The right to erasure - You have the right to request that we erase your personal data, under certain circumstances.",
|
||||
"- The right to restrict processing - You have the right to request us to restrict the processing of your personal information in certain circumstances.",
|
||||
"- The right to object to processing - You have the right to object to the processing of your personal data, under certain circumstances.",
|
||||
"We shall in general respond to your request within 30 days. We may ask you to verify your identity before executing your request. If your request is difficult to process, we may need more time to comply with your request and may delay the execution of your request."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IX. WHAT ARE COOKIES?",
|
||||
"newlines": [
|
||||
"We integrate and use cookies on various pages to enable certain functions of our website and to integrate external web services. The so-called 'cookies' are small text files that your browser can store on your access device. These text files contain a characteristic string that uniquely identifies the browser when you return to our website. This way, the information you previously provided can be retrieved. The process of saving a cookie file is also referred to as 'setting a cookie'."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "X. HOW DO WE USE COOKIES?",
|
||||
"newlines": [
|
||||
"We use cookies for the following purpose:",
|
||||
"- Integrations with payment providers such as Stripe."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XI. STRIPE",
|
||||
"newlines": [
|
||||
"We use Stripe for payment processing and refunds and to integrate with their services we use cookies. When using our payment processor Stripe, your bank/the payment provider will process your personal data as controllers of such processing. You can read more about the payment providers on their websites."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XII. CHANGES TO OUR WEBSITE PRIVACY STATEMENT",
|
||||
"newlines": [
|
||||
"We keep this Statement under regular review and reserve the right to amend this Statement without prior notification. If we change this Statement, we will inform you on our website and via our newsletter."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIII. HOW TO CONTACT US",
|
||||
"newlines": [
|
||||
"If you have any questions about our Statement, the personal data we hold of you, or you would like to exercise one of your data protection rights, please do not hesitate to contact us through:",
|
||||
"a. Our contact page available on our website: https://nymvpn.com/en/contact",
|
||||
"b. Our email address: legal@nymtech.net; or",
|
||||
"Our address: Nym Technologies SA, place Numa-Droz 2, 2000 Neuchâtel, Switzerland."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIV. CONTACT THE APPROPRIATE LEGAL AUTHORITY",
|
||||
"newlines": [
|
||||
"Should you wish to report a complaint or if you feel that we have not addressed your concern in a satisfactory manner, you may contact the supervisory authority. The supervisory authority for data protection in Switzerland is the Federal Data Protection and Information Commissioner (“FDPIC”). For further information, please consult the contact form of the FDPIC:",
|
||||
"https://www.edoeb.admin.ch/edoeb/de/home/deredoeb/kontakt.html."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XV. GOVERNING LAW",
|
||||
"newlines": [
|
||||
"This Statement and any questions relating thereto shall be governed by the laws of Switzerland."
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"apps": {
|
||||
"title": "NymVPN apps privacy statement",
|
||||
"subtitle": "",
|
||||
"content": [
|
||||
{
|
||||
"title": "",
|
||||
"newlines": ["Version 1.1, last updated on March 25, 2024"]
|
||||
},
|
||||
{
|
||||
"newlines": [
|
||||
"Thank you for visiting NymVPN and for your interest in our company.",
|
||||
"Nym Technologies SA, a Swiss Company established under the laws of Switzerland, and registered with the Chamber of Commerce and Industry of Switzerland with number CHE-367.426.629 provides a Virtual Private Network (VPN) service named NymVPN.",
|
||||
"In this privacy statement (the “NymVPN Statement”) we will explain, in accordance with the legal regulations of the Swiss Federal Act on Data Protection and its ordinances (“FADP”) how we process your personal data. This Statement serves to fulfill the information obligations arising from the FADP. These can be found, for example, in article 19 ff. FADP."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "TABLE OF CONTENT",
|
||||
"newlines": [
|
||||
"The followings topics will be discussed in this VPN Statement:",
|
||||
"I. General remark",
|
||||
"II. Notice regarding lawful interception",
|
||||
"III. How we get your personal data",
|
||||
"IV. Collecting personal data when you have enabled telemetry",
|
||||
"V. Collecting personal data in general",
|
||||
"VI. Purposes of data processing",
|
||||
"VII. The personal data controller",
|
||||
"VIII. Payment providers",
|
||||
"IX. With whom we share your personal data",
|
||||
"X. How long we store your personal data",
|
||||
"XI. Your data protection rights",
|
||||
"XII. Changes to our NymVPN Statement",
|
||||
"XIII. How to contact us",
|
||||
"XIV. Contact the appropriate authority",
|
||||
"XV. Governing law"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "I. GENERAL REMARK",
|
||||
"newlines": [
|
||||
"Your internet activity while using NymVPN services is not monitored, recorded, logged, stored, or passed to any third party, unless doing so is required by applicable law, e.g. in case of a lawful intercept request, required for providing the NymVPN services, required for billing and debt collection purposes or you have granted consent to this (by enabling telemetry)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "II. NOTICE REGARDING LAWFUL INTERCEPTION",
|
||||
"newlines": [
|
||||
"It should be noted that while we operate from Switzerland, a VPN is based on an ingress point (the device on which you run NymVPN) and one or more egress points, the exit node(s) that our service works with. In network terms, the exit node will also appear to be the location from which your network traffic originates, as seen by any internet services you access through NymVPN. This means that at any exit node, the local laws regarding lawful interception apply and your traffic will no longer be protected by NymVPN. For the sake of completeness, we note that our technology is designed in such a way that we will be unable to provide meaningful data in response to a lawful interception request."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "III. HOW WE GET YOUR PERSONAL DATA",
|
||||
"newlines": [
|
||||
"We collect personal data and process personal data when you use NymVPN."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IV. COLLECTING PERSONAL DATA WHEN YOU HAVE ENABLED TELEMETRY",
|
||||
"newlines": [
|
||||
"We collect the following data when you use NymVPN and have enabled our telemetry tool:",
|
||||
"- Usage analysis: Our telemetry tool, when enabled, gathers data on how you interact with our app to continuously improve your experience. This includes, but is not limited to, information about the features you use, the frequency of usage, and the duration of your sessions. Our telemetry tool may collect information such as your IP address and operating system. This information is used to analyze user behavior and improve our services;",
|
||||
"- Communication regarding feedback (voluntary): Our telemetry tool may record and store communications, such as emails, email addresses, messages, feedback exchanged, for purposes such as quality assurance, customer service, and record-keeping.",
|
||||
"More specifically:",
|
||||
"a. Timestamps of connections to:",
|
||||
" - calculate peak times of service demand in order to plan the network capacity;",
|
||||
" - manage the number of concurrent active connections and handle abuse; and",
|
||||
" - troubleshoot our service.",
|
||||
"b. Amount of data transmitted to:",
|
||||
" - plan for new network capacity and server improvements.",
|
||||
"c. Service Data from NymVPN users, such as specific errors to:",
|
||||
" - make sure our VPN users do their job properly and without errors. This data pertains to interactions taken in NymVPN and can in principle not be used to uncover what you’re using the VPN service for.",
|
||||
"d. Connection events, such as the attempt to connect, disconnection, connection error, etc. to:",
|
||||
" - operate and provide VPN service with high quality.",
|
||||
"e. Application events, such as auto-connection, uninstall event, etc. to:",
|
||||
" - plan product development and analytics.",
|
||||
"f. Application information, such as name, version and source of the application, enabled/disabled features at the time of the event, network type, public internet service provider’s information, current VPN connection status, and related information (protocol and technology in use, current server, etc.), user preferences (e.g., notifications enabled/disabled, language, preferred connection settings).",
|
||||
"g. Account information: active/inactive subscriptions of products of Nym Technologies SA, current and past active/inactive plans, and trial information.",
|
||||
"h. Device information, such as the model of your device, operating system version, and similar non-identifying information. We may use this information to monitor, develop, and analyze the use of NymVPN services.",
|
||||
"i. Crash reports generated and sent by the user.",
|
||||
"j. App version or internal identifiers."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "V. COLLECTING PERSONAL DATA IN GENERAL",
|
||||
"newlines": [
|
||||
"Regardless of whether or not you have enabled telemetry for the abovementioned purposes, we may still use telemetry strictly for the purpose of providing you with a more stable and reliable service:",
|
||||
"- Bug and issue report and monitoring: Our telemetry tool may collect data to help us identify and address bugs, errors, and other technical issues within the App. ",
|
||||
"Issues and support tickets raised by you with us will be processed by us, any personal data you include in those may be processed as well.",
|
||||
"We do not process data regarding your use of NymVPN if you have not enabled telemetry since our use of time-bound access credentials that consist of so-called zero-knowledge proofs makes it impossible for us to correlate usage with you as a person."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VI. PURPOSES OF DATA PROCESSING",
|
||||
"newlines": [
|
||||
"We have one reason (purpose) for processing your personal data:",
|
||||
"- to operate NymVPN, including measuring its quality and security, providing support, and getting paid for that.",
|
||||
"The basis for this is the performance of a contract with you. Additionally, when you consent to the collection of telemetry data, an additional purpose comes into play, which is improving NymVPN and our business around it. The basis for that would be your consent."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VII. THE PERSONAL DATA CONTROLLER",
|
||||
"newlines": [
|
||||
"We are the controller of personal data with regard to the NymVPN service."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VIII. PAYMENT PROVIDERS",
|
||||
"newlines": [
|
||||
"We rely on our payment providers to handle your product purchases. It should be noted here that you buy time-bound access credentials that provide access to NymVPN, but not accounts. The account you may have with your bank or credit card provider and your actual usage of NymVPN is not shared with any payment providers. In principle we use the following payment methods:",
|
||||
"- Stripe (desktop apps);",
|
||||
"- Apple in-app purchases (via the debit card on-file or via Apple Pay) and similar mechanism for Google (for mobile apps).",
|
||||
"Additionally, we offer BTCPay Server, a self-hosted, open-source cryptocurrency payment processor (desktop apps), which therefore is not an external payment provider.",
|
||||
"We collect, among others, the following data when you enter a contract with us:",
|
||||
"- Name and email address;",
|
||||
"- Debit card number;",
|
||||
"- Contact information; and",
|
||||
"- Geographic information (from Stripe, Apple and Google customers).",
|
||||
"We strongly advise you to consult the website of the relevant payment provider for more information on their privacy practices."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IX. WITH WHOM WE SHARE YOUR PERSONAL DATA",
|
||||
"newlines": [
|
||||
"With third parties:",
|
||||
"We provide personal data only to parties who help us optimize our services, execute the agreement with you or to parties with whom we are legally obliged to share the data. This includes operators of exit nodes, which have a contractual obligation towards us to respect the confidentiality of your NymVPN traffic.",
|
||||
"We may share your personal data with our payment processors as stated in paragraph VII above.",
|
||||
"Additionally, we make use of data processors with whom we have entered into data processing agreements. These data processors remain our responsibility and are therefore not third parties, even though they may appear as such to you.",
|
||||
"Cross-border data transfer:",
|
||||
"Nym is based in Switzerland, which means that a third country relationship exists in relation to the European Union (the “EU”) and the European Economic Area (the “EEA”). The EU/EEA has deemed the Swiss data protection regulations to be adequate and vice versa. As part of the provision of services, personal data is transferred to the EU/EEA for further processing and vice versa. This means that your data will only be processed on the basis of special guarantees and that the third country in the EEA has an adequate level of data protection. For some of the third-party service providers, we may transfer your data to one of their databases outside Switzerland or the EEA, potentially including countries which may not have an adequate level of protection for your personal data. In such event, we enter into agreements with such third parties ensuring an adequate level of protection for your personal data.",
|
||||
"However, as noted earlier, in cases where the use of the NymVPN involves exit nodes outside the EEA this may result in processing of your data in a third country. This is inherent to the service and meets the derogation of article 17 sub b FADP.",
|
||||
"Sharing with authorities:",
|
||||
"It is possible that we will need to disclose your personal data when required by law or if we believe that disclosure is necessary to investigate, prevent, or take action regarding suspected or actual illegal activities or to assist government enforcement agencies, investigate and defend ourselves against any third-party claims or allegations, protect the security or integrity of NymVPN or exercise or protect the rights and safety of our users, personnel or others. We attempt to notify you about legal demands for your personal data when appropriate in our judgment and technically feasible, unless prohibited by law or court order or when the request is an emergency. We may dispute such demands when we believe, in our discretion, that the requests are overbroad, vague or lack proper authority, but we do not promise to challenge every demand."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "X. HOW LONG WE STORE YOUR PERSONAL DATA",
|
||||
"newlines": [
|
||||
"The following three retention policies apply:",
|
||||
"First of all, by nature of the service, when you use NymVPN the communications through NymVPN will pass through operators of exit nodes. We have contractually obliged these operators to respect the confidentiality of your communications. However, the nature of the NymVPN technology is such that we do not have the level of control over such operators that they can be considered processors that we can demand to be audited or to support us when you do an access request. As such they are third parties with a confidentiality obligation.",
|
||||
"Pursuant to the Swiss law the accounting books and records, and the accounting vouchers together with the annual report and the audit report will be retained for ten years. The retention period begins on expiry of the respective financial year.",
|
||||
"Stripe will generally keep personal data received from us for at least five years from the end of the business relationship with us or the date of the last transaction, whichever is later.",
|
||||
"When you enable Sentry, our telemetry tool, we retain some usage metrics for approximately 90 days to perform (historical) analyses. This data will be pseudonymized.",
|
||||
"Once the retention period expires, the personal data will be either deleted or anonymized."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XI. YOUR DATA PROTECTION RIGHTS",
|
||||
"newlines": [
|
||||
"We would like to make sure you are fully aware of all your data protection rights. If we hold personal data about you under the FADP, you have rights including:",
|
||||
"- The right to be informed – You have the right to be informed of the collection and processing of your personal data.",
|
||||
"- The right of access - You have the right to request us for copies of your personal data. We may charge you a small fee for this service.",
|
||||
"- The right to rectification - You have the right to request that we correct any information that you believe is inaccurate. You also have the right to request us to complete information you believe is incomplete.",
|
||||
"- The right to erasure - You have the right to request that we erase your personal data, under certain circumstances.",
|
||||
"- The right to restrict processing - You have the right to request us to restrict the processing of your personal information in certain circumstances.",
|
||||
"- The right to object to processing - You have the right to object to the processing of your personal data, under certain circumstances.",
|
||||
"We shall in general respond to your request within 30 days. We may ask you to verify your identity before executing your request. If your request is difficult to process, we may need more time to comply with your request and may delay the execution of your request."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XII. CHANGES TO OUR VPN STATEMENT",
|
||||
"newlines": [
|
||||
"We keep our VPN Statement under regular review and reserve the right to amend this VPN Statement without prior notification. If we change this VPN Statement, we will inform you on our website and via our newsletter."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIII. HOW TO CONTACT US",
|
||||
"newlines": [
|
||||
"If you have any questions about our VPN Statement, the personal data we hold of you, or you would like to exercise one of your data protection rights, please do not hesitate to contact us through:",
|
||||
"a. Our contact page available on our website: https://nymvpn.com/en/contact",
|
||||
"b. Our email address: legal@nymtech.net; or",
|
||||
"c. Our address: Nym Technologies SA, place Numa-Droz 2, 2000 Neuchâtel, Switzerland."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIV. CONTACT THE APPROPRIATE AUTHORITY",
|
||||
"newlines": [
|
||||
"Should you wish to report a complaint or if you feel that we have not addressed your concern in a satisfactory manner, you may contact the supervisory authority. The supervisory authority for data protection in Switzerland is the Federal Data Protection and Information Commissioner (“FDPIC”). For further information, please consult the contact form of the FDPIC: https://www.edoeb.admin.ch/edoeb/de/home/deredoeb/kontakt.html."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XV. GOVERNING LAW",
|
||||
"newlines": [
|
||||
"This NymVPN Statement is governed by the laws of the Federal Republic of Switzerland."
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"socialChannels": [
|
||||
{ "name": "Telegram", "link": "https://nym.com/go/telegram" },
|
||||
{ "name": "Twitter", "link": "https://nym.com/go/x" },
|
||||
{
|
||||
"name": "Discord",
|
||||
"link": "https://nym.com/go/discord"
|
||||
},
|
||||
{ "name": "GitHub", "link": "https://nym.com/go/github" },
|
||||
{ "name": "YouTube", "link": "https://nym.com/go/youtube" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"title": "NymVPN support",
|
||||
"description": "Start with our FAQs for answers. Reach us via email, social media, or our [Discord](https://nymtech.net/go/discord) / [Matrix](https://matrix.to/#/#NymVPN:nymtech.chat) channels for personalized assistance. We're happy to help!",
|
||||
"faqs-categories": [
|
||||
{
|
||||
"category": "General",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "What is NymVPN?",
|
||||
"description": "NymVPN is a privacy-focused network-protection product that combines Nym's secure mixnet technology with a decentralized WireGuard VPN for comprehensive online privacy across all use cases."
|
||||
},
|
||||
{
|
||||
"title": "What makes NymVPN different from traditional VPNs?",
|
||||
"description": "NymVPN distinguishes itself with its distinctive blend of a mixnet and a decentralized VPN. By design, and in contrast to traditional VPNs, NymVPN cannot access user data or browsing history, nor link traffic to personal information, such as email or payment details. NymVPN also distinguishes itself with a multi-hop routing by default. This combination offers unparalleled online privacy and security across all online use cases. Check our [NymVPN litepaper](https://nymvpn.com/nymVPN-litepaper.pdf) for more detailed information."
|
||||
},
|
||||
{
|
||||
"title": "What makes NymVPN different from other decentralized VPNs?",
|
||||
"description": "NymVPN distinguishes itself with its distinctive blend of a mixnet and a multi-hop decentralized VPN. It stands out by relying on a truly decentralized set of nodes run by worldwide-distributed operators, empowered to participate in the structuring of the network via a democractic community governance. NymVPN also ensures private payments thanks to zero-knowledge proof access enabled by zk-nyms. Check our [NymVPN litepaper](https://nymvpn.com/nymVPN-litepaper.pdf) for more detailed information."
|
||||
},
|
||||
{
|
||||
"title": "What makes NymVPN different from Tor and other onion/garlic routers?",
|
||||
"description": "Tor stands out in the decentralized privacy landscape. But relying on volunteer-run nodes, it can suffer from inconsistent reliability and be subject to Sybil attacks, compromising its integrity. NymVPN incentivization scheme for node operators addresses both these issues. Moreover, NymVPN defeats timing analysis, a Tor vulnerability, with its packet shuffling and users cover traffic to obscure communication patterns. This combination offers a cutting-edge solution for users seeking the highest level of privacy. Check our [NymVPN litepaper](https://nymvpn.com/nymVPN-litepaper.pdf) for more detailed information."
|
||||
},
|
||||
{
|
||||
"title": "Where can I find the NymVPN server list?",
|
||||
"description": "NymVPN operates exit servers across various global locations, ensuring widespread coverage. Explore the complete list of our exit servers here: [Nym Explorer](https://explorer.nymtech.net)."
|
||||
},
|
||||
{
|
||||
"title": "How can I contribute to the NymVPN network?",
|
||||
"description": "By using NymVPN, you help to enhance the network security. Your additional traffic helps dilute and complicate traffic analysis for potential adversaries – in essence, 'Privacy loves company.' To further strengthen the network, you can actively participate. Delegate NYM tokens to operators you trust, ensuring top-quality service. Alternatively, install our node binaries and become a node operator. Download our [Nym Wallet app](https://nymtech.net/download/wallet) for delegations or visit our [node operators page](https://nymtech.net/build/nodes)."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "App",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "What features does NymVPN offer?",
|
||||
"description": "The comprehensive list of features for NymVPN can be found on this page: [NymVPN features](https://nymvpn.com/features)."
|
||||
},
|
||||
{
|
||||
"title": "Do I get a new IP address every time I use NymVPN?",
|
||||
"description": "When you launch NymVPN, you get connected to a randomly select exit server, either globally or within the country you have selected. Nym cannot guarantee the attribution of a different IP address for every connection."
|
||||
},
|
||||
{
|
||||
"title": "When will the updated NymVPN be available?",
|
||||
"description": "To stay informed and get early access, we recommend [signing up to our waitlist](https://nymvpn.com). Keep an eye out for announcements and updates."
|
||||
},
|
||||
{
|
||||
"title": "What is the expected duration of the beta phase?",
|
||||
"description": "The expected duration of the beta phase for NymVPN will be announced in our official communications and updates. Stay tuned for more information on the beta timeline."
|
||||
},
|
||||
{
|
||||
"title": "How can I provide feedback or report issues during the beta?",
|
||||
"description": "You can provide feedback using your preferred format, whether it's through the in-app report feature, email, social media, or our [Discord](https://nymtech.net/go/discord) / [Matrix](https://matrix.to/#/#NymVPN:nymtech.chat) channels. Your input is valuable to us!"
|
||||
},
|
||||
{
|
||||
"title": "What use cases is NymVPN best suited for?",
|
||||
"description": "NymVPN is designed to support a wide range of online activities. For network-intensive use cases like streaming and browsing, we recommend using the 2-hop VPN mode. For use cases requiring advanced privacy, we recommend using the 5-hop mixnet mode."
|
||||
},
|
||||
{
|
||||
"title": "How do I download and install the NymVPN app?",
|
||||
"description": "NymVPN is still in development but will be accessible via the nymvpn.com website and application stores upon release. In the meantime, to get a feel for the mixnet technology, you can download the current NymConnect app from our corporate website [Download page](https://nymtech.net/download/nymconnect)."
|
||||
},
|
||||
{
|
||||
"title": "What devices and operating systems will NymVPN support?",
|
||||
"description": "NymVPN aims to support a wide range of devices and operating systems, including but not limited to Android, iOS, (GNU/)Linux, macOS and Windows. The specifics of supported devices and systems may evolve, so look out for updates on all the latest information."
|
||||
},
|
||||
{
|
||||
"title": "How many devices can use with NymVPN?",
|
||||
"description": "NymVPN aims to support multi-device setups. Stay tuned for announcements and updates on the specific details."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Legal",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "How does NymVPN handle user data and logging?",
|
||||
"description": "NymVPN is committed to respecting your privacy. Our design ensures that Nym can't access or view your online and browsing data. While we are finalizing our privacy policy, you can review our [NymVPN litepaper](https://nymvpn.com/nymVPN-litepaper.pdf) for more detailed information. Your privacy and security are our utmost concerns."
|
||||
},
|
||||
{
|
||||
"title": "What legal jurisdiction governs NymVPN's operations?",
|
||||
"description": "NymVPN's operations fall under the legal jurisdiction of Switzerland, a country known for its political neutrality. Switzerland is not a member of the European Union and is not part of the 14-Eyes intelligence-sharing network. The Swiss jurisdiction provides a strong foundation for protecting user privacy and data security, in accordance with Swiss data protection laws (nFADP) and the Swiss constitution."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Pricing and payments",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "How do I subscribe for NymVPN?",
|
||||
"description": "Stay tuned, we will open NymVPN to external subscriptions soon."
|
||||
},
|
||||
{
|
||||
"title": "What payment methods are accepted for NymVPN subscriptions?",
|
||||
"description": "NymVPN aims to provide convenient payment choices for our users. We will accept various payment methods, including debit/credit cards and cryptocurrency options like NYM or Bitcoin."
|
||||
},
|
||||
{
|
||||
"title": "Does NymVPN offer a money-back guarantee or a trial period?",
|
||||
"description": "We recommend visiting our website for the most up-to-date information regarding money-back guarantees and trial periods. These options may vary depending on Nym's jurisdiction and your location."
|
||||
},
|
||||
{
|
||||
"title": "How can I delete my NymVPN account?",
|
||||
"description": "There is no such thing as an account with NymVPN. Upon purchasing a subscription, a cryptographically-unlinkable credential (unattributable to any personal or payment information) is generated and acts as a proof of access to the network. To 'delete your account', unlink your device from NymVPN and safely delete the NymVPN credentials from your device."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "B2B",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "Is NymVPN suitable for businesses or organizations?",
|
||||
"description": "Please contact our Sales team at [contact@nymtech.net](mailto:contact@nymtech.net) to explore how NymVPN can meet the unique needs of your business or organization."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Other",
|
||||
"faqs": [
|
||||
{
|
||||
"title": "How can I reach NymVPN Customer Support?",
|
||||
"description": "All contact information can be found on our [Contact page](http://nymvpn.com/contact)."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"title": "Terms of use",
|
||||
"subtitle": "By using NymVPN, you consent to these Terms.",
|
||||
"content": [
|
||||
{
|
||||
"newlines": [
|
||||
"Welcome to NymVPN.",
|
||||
"The Terms of Use (hereinafter: the “Terms”) aims to establish the legal framework and conditions governing the utilization and provision of the NymVPN application (hereinafter: the “NymVPN”) and the associated services by individuals (hereinafter: the “User” or “you”).",
|
||||
"The NymVPN is owned and operated by Nym Technologies SA, place Numa-Droz 2, 2000 Neuchâtel, Switzerland (hereinafter: the “Nym”, “we” or “us”). "
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "I. ACCEPTANCE",
|
||||
"newlines": [
|
||||
"By downloading, installing, or using the NymVPN, you acknowledge that you have read and understood these Terms and agree to be bound by them and to comply with these Terms, our Privacy Policy https://nymvpn.com/en/privacy and all applicable laws and regulations. If you do not agree with these Terms, you should refrain from using the NymVPN or VPN Services.",
|
||||
"In particular, you acknowledge that you have read and understood the clauses in these Terms relating to: Intellectual Property; Disclaimer of Warranties; Limitation of Liability; Indemnification; Privacy Policy; and the manner in which we may make changes to these Terms.",
|
||||
"Your consent is given once you click on “Get started” on NymVPN and warrant that you read and understand the terms “NymVPN – TERMS OF USE” and agree to be bound by them.",
|
||||
"By giving your consent, you confirm that your level of English is sufficient to understand the meaning of the terms contained in the English version of the Terms as well as all the commitments, warranties, waivers and obligations contained in the English version of the Terms.",
|
||||
"If you are using the NymVPN on behalf of a business or other entity, you represent and warrant that you have the necessary authority to bind that business or entity to these Terms and that you are agreeing to these Terms on behalf of that business or entity."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "II. DESCRIPTION OF NYM VPN SERVICES",
|
||||
"newlines": [
|
||||
"The NymVPN provides virtual private network services (hereinafter: the “VPN Services”) designed to enhance online privacy and security by encrypting internet traffic, providing anonymity, and leveraging blockchain for secure authentication and record-keeping.",
|
||||
"If you subscribed to the VPN Services, subject to these Terms, Nym grants you a limited, non-exclusive, non-transferable, non-sublicensable and revocable license to (a) install the NymVPN on one electronic device and (b) use NymVPN for your own personal or commercial use solely to access and use the VPN Services. The license provided herein is effective until terminated. Such license automatically terminates if you fail to comply with these Terms. For clarity, the foregoing is not intended to prohibit you from installing the NymVPN on another device on which you also agreed to these Terms. Each instance of these Terms that you agree to in connection with downloading a NymVPN grants you the aforementioned rights in connection with the installation and use of the NymVPN on one device."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "III. SUBSCRIPTION AND PAYMENT",
|
||||
"newlines": [
|
||||
"Some features of the NymVPN and VPN Services require you to create credentials. You are responsible for maintaining the confidentiality of your credentials information and agree to notify us immediately of any unauthorized use of your account.",
|
||||
"In the same manner, some features of the NymVPN and VPN Services require payment. Payment details, fees, and subscription terms will be outlined in the NymVPN and are subject to change at our discretion.",
|
||||
"VPN Services are provided exclusively to individuals who are at least 13 years of age, and even then, only to minors who have obtained parental or legal guardian consent to open and maintain an account.",
|
||||
"VPN Services are exclusively to persons or legal entities. Accounts registered by “bots” or automated methods are not authorized and will be terminated."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IV. USER CONDUCT AND PROHIBITED ACTIONS",
|
||||
"newlines": [
|
||||
"You are solely responsible for all your actions performed through the NymVPN and VPN Services.",
|
||||
"You may solely make a legal use of the NymVPN and VPN Services and any illegal or inappropriate use of the NymVPN and VPN Services is banned. In particular, you agree to use the NymVPN and VPN Services lawfully and without any violation of these Terms or any applicable law and agree not to do any of the following actions in connection with your use of the NymVPN and VPN Services:"
|
||||
],
|
||||
"alphabetList": [
|
||||
"engage in any activity that is illegal, unlawful, or prohibited by laws applicable in your jurisdiction or internationally;",
|
||||
"attempt to gain unauthorized access to any accounts, networks, or systems connected to the NymVPN and VPN Services;",
|
||||
"infringe upon intellectual property rights, including but not limited to copyrights, trademarks, patents, trade secrets, or other proprietary rights of any party;",
|
||||
"introduce any viruses, trojans, worms, logic bombs, or other material that is malicious or technologically harmful;",
|
||||
"conduct hacking activities, interfere with, or disrupt the integrity or performance of the NymVPN and VPN Services, their networks, or servers;",
|
||||
"promote illegal activities or provide instructional information to other parties to commit illegal activities;",
|
||||
"have a multiple free accounts (e.g. creating bulk signups, creating and/or operating a large number of free accounts for a single organization or individual);",
|
||||
"engage in data mining, data scraping, data harvesting, or any other similar activity in relation to the NymVPN, its users, or its content without our express written consent;",
|
||||
"use the NymVPN and VPN Services for fraudulent or deceptive purposes, including phishing, scamming, or misrepresenting information or identity;",
|
||||
"violate the privacy of others or infringe on their rights, including but not limited to posting or sharing personal information without consent;",
|
||||
"engage in abusive, harassing, or offensive behavior towards other users, including hate speech, bullying, or any form of discrimination;",
|
||||
"misuse blockchain features of the NymVPN and VPN Services for any unlawful activities, such as tampering with blockchain records, attempting to reverse transactions, or engaging in blockchain-based attacks;",
|
||||
"use the NymVPN and VPN Services to aid or conduct military actions or for the purpose of surveillance, espionage, or any activity that compromises the privacy or security of individuals, organizations, or nations without proper legal authorization;",
|
||||
"use the NymVPN and VPN Services in breach of international sanctions or trade embargoes imposed by the United Nations or specific countries;",
|
||||
"access, share, download or upload illegal content, including but not limited to Child Sexual Abuse Material (CSAM) or content related to CSAM;",
|
||||
"post, share, or distribute content that is illegal, obscene, defamatory, libelous, threatening, or otherwise objectionable; and",
|
||||
"violate any terms and conditions laid out in these Terms or the Privacy Policy."
|
||||
]
|
||||
},
|
||||
{
|
||||
"newlines": [
|
||||
"Please note that this list is not exhaustive and additional actions may be considered inappropriate or unlawful."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "V. AVAILABILITY AND USE IN RESTRICTED OR PROHIBITED REGIONS",
|
||||
"newlines": [
|
||||
"The use of the VPN Services may be prohibited or restricted in certain regions. The use of the VPN Services is expressly prohibited in the countries or regions, where the use of VPN Services is either heavily restricted or prohibited.",
|
||||
"In addition, some governments actively censor the Internet, blocking certain VPN applications despite the fact that VPN use is legal in said jurisdictions.",
|
||||
"It is your responsibility to ensure compliance with the laws and regulations in your respective region. Users are encouraged to stay informed about their local laws governing VPN usage and should refrain from using this NymVPN and VPN Services if it is prohibited in their area. In regions where the use of VPN services is restricted, prohibited, or subject to specific law or regulations, you agree not to use this NymVPN and VPN Services in violation of such laws or regulations.",
|
||||
"By using this NymVPN, you affirm that you are not located in a region where the use of VPN services is prohibited or restricted. The parties expressly understand that Nym does not encourage the use of the NymVPN in any manner that violates local laws or regulations.",
|
||||
"In case of any conflict between the use of the NymVPN and local laws, you are prohibited from using the NymVPN, and by doing so, you acknowledge that you do it at your own risk and against these Terms."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VI. PRIVACY",
|
||||
"newlines": [
|
||||
"We value your privacy and employ blockchain technology to enhance security. Our Privacy Policy explains in detail to describe how we collect, use, and disclose your information. By using the NymVPN, you consent to our Privacy Policy https://nymvpn.com/en/privacy and acknowledge the utilization of blockchain technology."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VII. INTELLECTUAL PROPERTY",
|
||||
"newlines": [
|
||||
"The NymVPN and VPN Services and their original content, features, and functionality are and will remain the exclusive property of NYM. The NymVPN and VPN Services are protected by copyright, trademark, and other laws in accordance with these Terms.",
|
||||
"You will respect our property rights in the NymVPN and software used to provide the NymVPN and VPN Services (including, but not limited to, patents, trademarks, service marks, trade secrets, copyrights and other intellectual property rights).",
|
||||
"All intellectual property rights in the NymVPN and VPN Services not expressly granted herein are reserved by Nym. All copyright and other proprietary notices shall be retained on all reproductions. Any other use, including without limitation distribution, reproduction, modification, making available, communicate to the public, publicly perform, frame, download, display or transmission, in whole or in part, without the prior written consent of Nym is strictly prohibited.",
|
||||
"To the extent any portion of the NymVPN or related technology has been released by Nym under an open source license (“Nym OSS”), you may use, copy and modify the source code of such Nym OSS in accordance with the terms of the applicable open source software license."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "VIII. DISCLAIMER OF WARRANTIES",
|
||||
"newlines": [
|
||||
"THE NYMVPN AND VPN SERVICES ARE PROVIDED ON AN “AS IS” AND “AS AVAILABLE” AND “UNDER DEVELOPMENT” BASIS AND NYM EXPRESSLY DISCLAIMS ALL REPRESENTATIONS, WARRANTIES AND CONDITIONS (EXPRESS OR IMPLIED, ORAL OR WRITTEN), INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL CONTENT AVAILABLE ON THE NYMVPN ARE MADE AVAILABLE FOR INFORMATIONAL PURPOSES ONLY AND SHOULD NOT BE CONTRACTUAL OR BINDING IN ANY WAY FOR NYM. YOU SHOULD NOT RELY UPON THIS CONTENT IN ANY WAY. NYM DOES NOT GIVE ANY WARRANTY IN RELATION TO THE NYMVPN, THE VPN SERVICES, AND THE RELATED SOFTWARE, BLOCKCHAIN AND CONTENT, NOR WITH ANY INFORMATION PUBLISHED OR AVAILABLE ON THE NYMVPN, INCLUDING BUT NOT LIMITED TO ITS AVAILABILITY, ACCURACY OR LAWFULNESS. NYM SHALL HAVE NO OBLIGATION TO VERIFY, UPDATE OR CORRECT SUCH CONTENT OR INFORMATION. NYM DOES NOT REPRESENT OR WARRANT THAT THE NYMVPN OR VPN SERVICES WILL BE AVAILABLE AT ALL TIMES AND EXPRESSLY RESERVES THE RIGHT TO DISCONTINUE THE NYMVPN OR VPN SERVICES WITHOUT NOTICE. NYM DOES NOT REPRESENT OR WARRANT THAT THE USAGE OF THE NYMVPN OR VPN SERVICES WILL BE SECURE, TIMELY, UNINTERRUPTED, ERROR-FREE OR VIRUS-FREE, OR ANY DEFECTS IN THE NYMVPN WILL BE CORRECTED. NYM DOES NOT REPRESENT OR WARRANT THAT THE NYMVPN OR VPN SERVICES WILL MEET YOUR REQUIREMENTS OR THE QUALITY OF ANY PRODUCTS, SERVICES, INFORMATION, OR OTHER MATERIAL PURCHASED OR OBTAINED BY YOU THROUGH THE NYMVPN OR VPN SERVICES WILL MEET YOUR EXPECTATIONS. THE FOREGOING DISCLAIMER OF WARRANTIES WILL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. THE LAWS OF SOME JURISDICTIONS DO NOT ALLOW THE DISCLAIMER OF IMPLIED WARRANTIES, SO SOME OR ALL OF THE DISCLAIMERS IN THIS SECTION MAY NOT APPLY TO YOU. IF YOU ARE DISSATISFIED WITH ANY PORTION OF THE NYMVPN OR VPN SERVICES OR WITH THESE TERMS, YOUR SOLE AND EXCLUSIVE REMEDY IS TO DISCONTINUE USE OF THE NYMVPN AND VPN SERVICES.",
|
||||
"THE NYMVPN MIGHT BE SUBJECT TO TEMPORARY DOWNTIME. FROM TIME TO TIME, WE ALSO UPDATE OR MAINTAIN THE NYMVPN, WHICH WILL RESULT IN THE NYMVPN AND/OR THE VPN SERVICES NOT BEING AVAILABLE FOR A CERTAIN PERIOD OF TIME. WE DO NOT WARRANT THAT THE NYMVPN AND THE VPN SERVICES OPERATE UNINTERRUPTED OR ERROR FREE. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IX. LIMITATIONS OF LIABILITY",
|
||||
"newlines": [
|
||||
"THESE TERMS SET OUT THE FULL EXTENT OF OUR OBLIGATIONS AND LIABILITIES WITH RESPECT TO THE NYMVPN.",
|
||||
"YOU EXPRESSLY ACKNOWLEDGE AND AGREE THAT YOUR ACCESS TO AND USE OF THE NYMVPN AND THE VPN SERVICES ARE AT YOUR SOLE RISK. TO THE MAXIMUM EXTENT POSSIBLE BY LAW, THE NYM PARTIES SHALL NOT BE RESPONSIBLE OR LIABLE TO YOU OR ANY THIRD PARTY, UNDER ANY THEORY OF RESPONSIBILITY OR LIABILITY, FOR ANY INDIRECT, SPECIAL, EXEMPLARY, INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF DATA, USE, OR PROFITS; BUSINESS INTERRUPTIONS; OR ANY OTHER DAMAGES OR LOSSES), FOR ANY MULTIPLIER ON OR INCREASE TO DAMAGES, OR FOR ANY COSTS OR FEES (INCLUDING ATTORNEYS’ FEES), WHETHER UNDER THESE TERMS OR OTHERWISE, ARISING IN ANY WAY IN CONNECTION WITH YOUR ACCOUNT, THE NYMVPN, THE VPN SERVICES, OR THESE TERMS, WHETHER ARISING AT LAW, IN EQUITY, OR OTHERWISE, AND WHETHER BASED IN CONTRACT, STRICT LIABILITY, TORT (INCLUDING NEGLIGENCE OR OTHERWISE), COMMON LAW, STATUTE, EQUITY, OR OTHERWISE, EVEN IF THE NYM PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE, OR FOR ANY OTHER CLAIM, DEMAND, OR DAMAGES WHATSOEVER. THE FOREGOING DISCLAIMER OF CERTAIN DAMAGES AND LIMITATION OF LIABILITY APPLIES TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. THE LAWS OF SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO SOME OR ALL OF THE EXCLUSIONS AND LIMITATIONS SET FORTH ABOVE MAY NOT APPLY TO YOU. ",
|
||||
"WITHOUT LIMITATION OF THE FOREGOING, NYM SHALL NOT ACCEPT RESPONSIBILITY FOR ANY DAMAGE, LOSS, DELAY, OR INCONVENIENCE CAUSED BY CIRCUMSTANCES BEYOND OUR REASONABLE CONTROL. SUCH CIRCUMSTANCES INCLUDE BUT ARE NOT LIMITED TO WAR, THREAT OF WAR, RIOTS, CIVIL STRIFE, OR TERRORIST ACTIVITY, INDUSTRIAL DISPUTES, NATURAL OR NUCLEAR DISASTERS, FIRE, AIRPORT CLOSURES, BAD WEATHER CONDITIONS, INTERRUPTION OR FAILURE OF A UTILITY SERVICE OR THE ACTS OF ANY LOCAL OR NATIONAL GOVERNMENT.",
|
||||
"WITHOUT LIMITATION OF THE FOREGOING, AND TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF THE NYM PARTIES FOR ANY REASON WHATSOEVER ARISING OUT OF OR RELATED TO THE USE OF, OR INABILITY TO USE, THE NYMVPN OR VPN SERVICES SHALL NOT EXCEED CHF 100 OR THE AMOUNT YOU PAID US IN THE SIX MONTHS PRECEDING THE DATE OF THE CLAIM, IF ANY, FOR USE OF THE NYMVPN WHICHEVER AMOUNT IS GREATER. THIS LIABILITY, IF ANY, SHALL BE COMPLETE AND EXCLUSIVE."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "X. INDEMNIFICATION",
|
||||
"newlines": [
|
||||
"To the extent permitted under applicable law, you agree to defend, indemnify and hold harmless Nym, and any parents, subsidiaries, affiliates, or third-party contractors and each of their respective directors, officers, employees and agents (collectively, the “Nym Parties”) from and against all third party claims, damages, costs, liabilities, losses and expenses (including, but not limited to, court and attorneys’ fees) caused by, arising out of or related to (a) your use of, or inability to use, the NymVPN or the VPN Services; (b) your violation of these Terms or any other applicable terms, policies, warnings, warranties, or instructions provided by Nym or a third-party in relation to the NymVPN or the VPN Services; (c) your violation of any applicable law or any rights of any third-party. Nym reserves the right to assume the exclusive defense and control of any matter which is subject to indemnification under this section, and you agree to cooperate with any reasonable requests assisting Nym's defense of such matter. You may not settle or compromise any claim against the Nym Parties without Nym's written consent."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XI. RESERVATION OF RIGHTS",
|
||||
"newlines": [
|
||||
"Nym may block, terminate, or suspend your access or ability to use the NymVPN and/or VPN Services, in whole or in part, without notice and at any time, at the sole discretion of Nym, as well as close or interrupt the NymVPN and/or VPN Services. In particular without limiting the foregoing, Nym reserves the right to terminate your right to use the NymVPN and/or VPN Services if you violate these Terms or any other terms, laws or policies referenced herein, or if you otherwise create risk or possible legal exposure for Nym. Nym reserves the right to initiate legal proceedings against any person for fraudulent use of the NymVPN and/or the VPN Services and any other unlawful acts or acts or omissions in breach of these Terms.",
|
||||
"Nym may also restrict access to the NymVPN and/or VPN Services if the stability and security of the operation, the maintenance of the integrity of the network, in particular the prevention of serious disruptions to the network, the software or the stored data require such action. ",
|
||||
"You agree that any termination of your access to the NymVPN and/or VPN Services under any provision of these Terms may be effected without prior notice, and acknowledge and agree that Nym may immediately deactivate or delete your account and all related information and files in your account and/or bar any further access to such files or the NymVPN and/or VPN Services. Further, you agree that Nym will not be liable to you or any third party for any termination of your access to the NymVPN and/or VPN Services."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XII. NO WAIVER",
|
||||
"newlines": [
|
||||
"Nym’s failure to enforce a provision of these Terms does not constitute a waiver of its right to do so in the future with respect to that provision, any other provision, or these Terms as a whole."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIII. CONTACTING NYM AND COMPLAINTS",
|
||||
"newlines": [
|
||||
"Nym hopes to be able to answer any questions or concerns you have about your personal data. You have the right to make a complaint if you feel your personal data has been mishandled or if Nym has failed to meet your expectations. You are encouraged to contact Nym about any complaints or concerns, but you are entitled to complain directly to the relevant supervisory authority."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIV. CHANGES TO THE TERMS",
|
||||
"newlines": [
|
||||
"Nym may, at its sole discretion, change or modify these Terms from time to time and will post the most current version on the in-app features. If a modification reduces your rights, it will inform you immediately when you will use our NymVPN and you will have to accept the changes. Your continued use of NymVPN or VPN Services after the date any such changes or modifications become effective constitutes your acceptance of the new Terms. If you do not agree to abide by these or any future Terms, you will not access, browse, or use (or continue to access, browse, or use) the NymVPN or VPN Services."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XV. ENGLISH VERSION",
|
||||
"newlines": [
|
||||
"If there is an inconsistency between any of the provisions of this English language version and a translated version of these Terms, the provisions of this English language version shall prevail. Any translated versions of the Terms or the Privacy Policy are provided only for your convenience."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XVI. JURISDICTION AND GOVERNING LAW",
|
||||
"newlines": [
|
||||
"These Terms and any questions relating thereto shall be governed by the laws of Switzerland, to the exclusion of any rules of conflict resulting from private international law."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XVII. DISPUTE RESOLUTION BY ARBITRATION",
|
||||
"newlines": [
|
||||
"PLEASE READ THE FOLLOWING CLAUSE CAREFULLY BECAUSE IT CONTAINS CERTAIN PROVISIONS, SUCH AS A BINDING ARBITRATION CLAUSE AND CLASS ACTION WAIVER, WHICH AFFECT YOUR LEGAL RIGHTS. THIS CLAUSE REQUIRES YOU TO ARBITRATE CERTAIN DISPUTES AND CLAIMS WITH NYM AND LIMITS THE MANNER IN WHICH YOU CAN SEEK RELIEF FROM US. ",
|
||||
"Binding Arbitration. Except for any disputes, claims, suits, actions, causes of action, demands or proceedings (collectively, “Disputes”) in which either Party seeks injunctive or other equitable relief for the alleged unlawful use of intellectual property, including, without limitation, copyrights, trademarks, trade names, logos, trade secrets or patents, you and NYM (i) waive your and NYM’s respective rights to have any and all Disputes arising from or related to these T&Cs resolved in a court. Instead, you and NYM will arbitrate Disputes through binding arbitration (which is the referral of a Dispute to one or more persons charged with reviewing the Dispute and making a final and binding determination to resolve it instead of having the Dispute decided in court).",
|
||||
"No Class Arbitrations, Class Actions or Representative Actions. Any Dispute arising out of or related to these T&Cs is personal to you and NYM and will be resolved solely through individual arbitration and will not be brought as a class arbitration, class action or any other type of representative proceeding. There will be no class arbitration or arbitration in which an individual attempts to resolve a Dispute as a representative of another individual or group of individuals. Further, a Dispute cannot be brought as a class or other type of representative action, whether within or outside of arbitration, or on behalf of any other individual or group of individuals.",
|
||||
"Arbitration Rules. Any dispute, controversy or claim arising out of or relating to this Agreement, or the breach, termination or invalidity thereof, shall be settled by arbitration in accordance with the Swiss Rules of International Arbitration of the Swiss Arbitration Centre in force on the date on which the Notice of Arbitration is submitted in accordance with those Rules. The place of arbitration shall be in Neuchâtel, Switzerland. There shall only be one arbitrator. The language to be used in the proceedings shall be English."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XVIII. ASSIGNMENT",
|
||||
"newlines": [
|
||||
"You may not assign these Terms without the prior written consent of Nym, but Nym may assign or transfer these Terms, in whole or in part, without restriction. Any attempted assignment, delegation, or transfer by either party in violation hereof will be null and void. Subject to the foregoing, these Terms will be binding on the parties and their successors and assigns."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "XIX. CONTACT",
|
||||
"newlines": [
|
||||
"To ask questions or make comments on these Terms or to make a complaint about our compliance with applicable laws, please contact us through:"
|
||||
],
|
||||
"alphabetList": [
|
||||
"our contact form available on our website: https://nymvpn.com/en/contact;",
|
||||
"our email address: legal@nymtech.net; or",
|
||||
"our address: Nym Technologies SA, place Numa-Droz 2, 2000 Neuchâtel, Switzerland."
|
||||
]
|
||||
},
|
||||
{
|
||||
"newlines": [
|
||||
"We will use commercially reasonable efforts to acknowledge and investigate any legitimate complaint pursuant to these Terms."
|
||||
]
|
||||
},
|
||||
{
|
||||
"newlines": ["Terms of use version 1.0, December 20, 2023"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"pages": [
|
||||
{ "name": "Features", "link": "features" },
|
||||
{
|
||||
"name": "Download",
|
||||
"link": "download",
|
||||
"submenu": {
|
||||
"sections": [
|
||||
{
|
||||
"name": "Desktop",
|
||||
"items": [
|
||||
{ "name": "Linux", "link": "download/linux" },
|
||||
{ "name": "macOS", "link": "download/macos" },
|
||||
{ "name": "Windows", "link": "download/windows" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Mobile",
|
||||
"items": [
|
||||
{ "name": "Android", "link": "download/android" },
|
||||
{ "name": "iOS", "link": "download/ios" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{ "name": "Trust Center", "link": "trust-center" },
|
||||
{
|
||||
"name": "Support",
|
||||
"link": "https://support.nymvpn.com/hc/en-us"
|
||||
},
|
||||
{
|
||||
"name": "Resources",
|
||||
"submenu": [
|
||||
{ "name": "Blog", "link": "blog" },
|
||||
{
|
||||
"name": "Download the litepaper",
|
||||
"link": "nymVPN-litepaper.pdf",
|
||||
"isNewTab": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Visit nymtech.net",
|
||||
"link": "https://nymtech.net"
|
||||
}
|
||||
],
|
||||
"cta": {
|
||||
"id": "topnav_getnymvpn_button_clicked",
|
||||
"text": "Get app",
|
||||
"link": "/en/download"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
{
|
||||
"hero": {
|
||||
"title": "Trust center",
|
||||
"intro": [
|
||||
"Choosing a privacy provider means deciding who to trust with your personal data and online activity. At Nym, we work hard to earn that trust.",
|
||||
"Read on to learn who we are, how we operate, and how we protect your online data."
|
||||
]
|
||||
},
|
||||
"ctaTitle": "Start using NymVPN today",
|
||||
"relatedTopicsTitle": "Related topics",
|
||||
"features": [
|
||||
{
|
||||
"title": "Check out NymVPN features",
|
||||
"link": "features",
|
||||
"ctaText": "Learn more"
|
||||
}
|
||||
],
|
||||
"breadCrumbs": {
|
||||
"title": "Trust center",
|
||||
"slug": "trust-center"
|
||||
},
|
||||
"auditListItemKeys": {
|
||||
"company": "Company",
|
||||
"published": "Published",
|
||||
"authors": "Authors",
|
||||
"date": "Date"
|
||||
},
|
||||
"categories": [
|
||||
{
|
||||
"id": "security",
|
||||
"title": "Security",
|
||||
"intro": "NymVPN prioritizes security with an open-source approach and undergoes regular independent security audits by leading firms and cryptographers.",
|
||||
"articles": [
|
||||
{
|
||||
"id": "security-1",
|
||||
"title": "Open source code",
|
||||
"intro": "NymVPN is developed following an open-source approach and operates under the GPL v3 license.",
|
||||
"link": "https://github.com/nymtech",
|
||||
"isExternal": true
|
||||
},
|
||||
{
|
||||
"id": "security-2",
|
||||
"title": "Independently audited",
|
||||
"link": "security-audits",
|
||||
"intro": "Nym and NymVPN undergo regular audits conducted by leading security firms and cryptographers.",
|
||||
"isExternal": false,
|
||||
"content": [
|
||||
{
|
||||
"component": "AuditList",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Nym Mobile & Desktop, VPN, Infra & Cryptography (to be published)",
|
||||
"link": "https://cure53.de",
|
||||
"company": "Cure 53",
|
||||
"authors": "Dr.-Ing. M. Heiderich, Dr. A. Pirker, Dr. D. Bleichenbacher, L. Herrera, Dr. M. Conde, Dr. N. Kobeissi",
|
||||
"date": "July 2024"
|
||||
},
|
||||
{
|
||||
"title": "Nym DKG cryptographic review, Outfox implementation (to be published)",
|
||||
"link": "https://cryspen.com",
|
||||
"company": "Cryspen",
|
||||
"authors": "Dr. Karthikeyan Bhargavan, Dr. Franziskus Kiefer, Dr. Jonas Schneider-Bensch",
|
||||
"date": "2023-2024"
|
||||
},
|
||||
{
|
||||
"title": "Nym Mixnet and Vesting Contract (to be published)",
|
||||
"link": "https://www.oaksecurity.io",
|
||||
"company": "Oak Security",
|
||||
"authors": "Oak Security",
|
||||
"date": "January 2023"
|
||||
},
|
||||
{
|
||||
"title": "Nym Security Review (to be published)",
|
||||
"link": "https://www.aumasson.jp",
|
||||
"company": "Dr. JP Aumasson",
|
||||
"authors": "Dr. JP Aumasson",
|
||||
"date": "September 2021"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "science",
|
||||
"title": "Science",
|
||||
"intro": "NymVPN is built on cutting-edge technologies developed by our co-founders and peer-reviewed in top-tier publications. Continuous innovation is driven by our advisory board and university partnerships.",
|
||||
"articles": [
|
||||
{
|
||||
"id": "science-1",
|
||||
"title": "Peer-reviewed research",
|
||||
"link": "research",
|
||||
"intro": "Technologies powering Nym and NymVPN have been developed by our founders, employees, and advisors, and published in prominent peer-reviewed cryptography and computer science journals.",
|
||||
"content": [
|
||||
{
|
||||
"component": "DocumentList",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Decentralized Reliability Estimation for Mixnets",
|
||||
"link": "https://arxiv.org/pdf/2406.06760",
|
||||
"authors": "Claudia Diaz, Harry Halpin, Aggelos Kiayias",
|
||||
"published": "arXiv preprint",
|
||||
"date": "2024"
|
||||
},
|
||||
{
|
||||
"title": "MixMatch: Flow Matching for Mixnet Traffic",
|
||||
"link": "https://petsymposium.org/popets/2024/popets-2024-0050.pdf",
|
||||
"authors": "Lennart Oldenburg, Marc Juarez, Enrique Argones Rúa, Claudia Diaz",
|
||||
"published": "Proceedings on Privacy Enhancing Technologies (PoPETs)",
|
||||
"date": "2024"
|
||||
},
|
||||
{
|
||||
"title": "LARMix: Latency-Aware Routing in Mix Networks",
|
||||
"link": "https://www.ndss-symposium.org/wp-content/uploads/2024-221-paper.pdf",
|
||||
"authors": "Mahdi Rahimi, Piyush Kumar Sharma, Claudia Diaz",
|
||||
"published": "Network and Distributed System Security (NDSS) Symposium 2024",
|
||||
"date": "2024"
|
||||
},
|
||||
{
|
||||
"title": "Are continuous stop-and-go mixnets provably secure?",
|
||||
"link": "https://petsymposium.org/popets/2024/popets-2024-0136.pdf",
|
||||
"authors": "Debajyoti Das, Claudia Diaz, Aggelos Kiayias, Thomas Zacharias",
|
||||
"published": "Proceedings on Privacy Enhancing Technologies (PoPETs)",
|
||||
"date": "2024"
|
||||
},
|
||||
{
|
||||
"title": "Blending Different Latency Traffic With Beta Mixing",
|
||||
"link": "https://lirias.kuleuven.be/retrieve/742049",
|
||||
"authors": "Iness Ben Guirat, Debajyoti Das, Claudia Diaz",
|
||||
"published": "Proceedings on Privacy Enhancing Technologies (PoPETs)",
|
||||
"date": "2024"
|
||||
},
|
||||
{
|
||||
"title": "NymVPN litepaper - Protecting patterns of communication for all internet traffic",
|
||||
"link": "https://nymvpn.com/en/nymVPN-litepaper.pdf",
|
||||
"date": "2023"
|
||||
},
|
||||
{
|
||||
"title": "Compact and Divisible E-Cash with Threshold Issuance",
|
||||
"link": "https://petsymposium.org/2023/files/papers/issue4/popets-2023-0116.pdf",
|
||||
"authors": "Alfredo Rial, Ania M. Piotrowska",
|
||||
"published": "Proceedings on Privacy Enhancing Technologies, Volume 2023",
|
||||
"date": "2023"
|
||||
},
|
||||
{
|
||||
"title": "Traffic Analysis by Adversaries with Partial Visibility",
|
||||
"link": "https://www.esat.kuleuven.be/cosic/publications/article-3637.pdf",
|
||||
"authors": "Iness Ben Guirat, Claudia Diaz, Karim Eldefrawy, Hadas Zeilberger",
|
||||
"published": "European Symposium on Research in Computer Security (ESORICS'23)",
|
||||
"date": "2023"
|
||||
},
|
||||
{
|
||||
"title": "Decentralized Incentivized Mixnet",
|
||||
"link": "https://patentimages.storage.googleapis.com/c2/eb/e1/b7091a0478e53c/US20230066860A1.pdf",
|
||||
"authors": "Harry Halpin, Claudia Diaz",
|
||||
"published": "US Patent Application 17/681,701",
|
||||
"date": "2023"
|
||||
},
|
||||
{
|
||||
"title": "Security Analysis of Coconut, an Attribute-Based Credential Scheme with Threshold Issuance",
|
||||
"link": "https://eprint.iacr.org/2022/011.pdf",
|
||||
"authors": "Alfredo Rial, Ania Piotrowska",
|
||||
"published": "IACR Cryptology ePrint Archive, Volume 2022",
|
||||
"date": "2022"
|
||||
},
|
||||
{
|
||||
"title": "Mixnet optimization methods",
|
||||
"link": "https://petsymposium.org/popets/2022/popets-2022-0081.pdf",
|
||||
"authors": "Iness Ben Guirat, Claudia Diaz",
|
||||
"published": "Proceedings on Privacy Enhancing Technologies (PoPETs)",
|
||||
"date": "2022"
|
||||
},
|
||||
{
|
||||
"title": "Reward Sharing for Mixnets",
|
||||
"link": "https://nymtech.net/nym-cryptoecon-paper.pdf",
|
||||
"authors": "Claudia Diaz, Harry Halpin, Aggelos Kiayias",
|
||||
"published": "TBD",
|
||||
"date": "2022"
|
||||
},
|
||||
{
|
||||
"title": "Mix networks",
|
||||
"link": "https://link.springer.com/referenceworkentry/10.1007/978-3-642-27739-9_1754-1",
|
||||
"authors": "Claudia Diaz",
|
||||
"published": "Encyclopedia of Cryptography, Security and Privacy",
|
||||
"date": "2022"
|
||||
},
|
||||
{
|
||||
"title": "Mixim: Mixnet design decisions and empirical evaluation",
|
||||
"link": "https://dl.acm.org/doi/pdf/10.1145/3463676.3485613",
|
||||
"authors": "Iness Ben Guirat, Devashish Gosain, Claudia Diaz",
|
||||
"published": "WPES '21: Proceedings of the 20th Workshop on Workshop on Privacy in the Electronic Society",
|
||||
"date": "2022"
|
||||
},
|
||||
{
|
||||
"title": "Nym litepaper - The next generation of Privacy infrastructure",
|
||||
"link": "https://nymtech.net/nym_litepaper.pdf",
|
||||
"date": "2021"
|
||||
},
|
||||
{
|
||||
"title": "The Nym Network - The Next Generation of Privacy Infrastructure",
|
||||
"link": "https://nymtech.net/nym-whitepaper.pdf",
|
||||
"authors": "Claudia Diaz, Harry Halpin, Aggelos Kiayias",
|
||||
"published": "TBD",
|
||||
"date": "2021"
|
||||
},
|
||||
{
|
||||
"title": "VerLoc: Verifiable Localization in Decentralized Systems",
|
||||
"link": "https://www.esat.kuleuven.be/cosic/publications/article-3411.pdf",
|
||||
"authors": "Katharina Kohls, Claudia Diaz",
|
||||
"published": "TBD",
|
||||
"date": "2021"
|
||||
},
|
||||
|
||||
{
|
||||
"title": "Optimizing Anonymity and Performance in a Mix Network",
|
||||
"link": "https://dl.acm.org/doi/10.1007/978-3-031-08147-7_4",
|
||||
"authors": "Mathieu Jee, Ania M. Piotrowska, Harry Halpin, Ninoslav Marina ",
|
||||
"published": "Foundations and Practice of Security: 14th International Symposium, FPS 2021",
|
||||
"date": "2021"
|
||||
},
|
||||
{
|
||||
"title": "Studying the anonymity trilemma with a discrete-event mix network simulator",
|
||||
"link": "http://arxiv.org/pdf/2107.12172",
|
||||
"authors": "Ania M. Piotrowska",
|
||||
"published": "TBD",
|
||||
"date": "2021"
|
||||
},
|
||||
{
|
||||
"title": "Coconut: Threshold Issuance Selective Disclosure Credentials with Applications to Distributed Ledgers",
|
||||
"link": "https://arxiv.org/pdf/1802.07344",
|
||||
"authors": "Alberto Sonnino, Mustafa Al-Bassam, Shehar Bano, Sarah Meiklejohn, George Danezis",
|
||||
"published": "TBD",
|
||||
"date": "2020"
|
||||
},
|
||||
{
|
||||
"title": "Ouroboros: A Provably Secure Proof-of-Stake Blockchain Protocol (pdf)",
|
||||
"link": "https://eprint.iacr.org/2016/889.pdf",
|
||||
"authors": "Aggelos Kiayias, Alexander Russell, Bernardo David, Roman Oliynykov",
|
||||
"published": "TBD",
|
||||
"date": "2019"
|
||||
},
|
||||
{
|
||||
"title": "The Loopix Anonymity System",
|
||||
"link": "https://arxiv.org/pdf/1703.00536",
|
||||
"authors": "Ania Piotrowska, Jamie Hayes, Tariq Elahi, Sebastian Meiser, George Danezis",
|
||||
"published": "arXiv preprint",
|
||||
"date": "2017"
|
||||
},
|
||||
{
|
||||
"title": "NEXTLEAP: Decentralizing Identity with Privacy for Secure Messaging",
|
||||
"link": "https://inria.hal.science/hal-01673292/file/ares2017.pdf",
|
||||
"authors": "Harry Halpin",
|
||||
"published": "TBD",
|
||||
"date": "2017"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "science-2",
|
||||
"title": "Up-to-date cryptography",
|
||||
"intro": "NymVPN utilizes robust cryptographic primitives like AES128, ChaChaPoly, and BLAKE2 for enhanced security.",
|
||||
"link": "cryptography",
|
||||
"content": [
|
||||
{
|
||||
"component": "TextList",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"title": "In the Anonymous (5-hop mixnet) mode:",
|
||||
"alphabetList": [
|
||||
"AES128 for secure communication between clients and entry nodes, as well as for encryption of the Sphinx header;",
|
||||
"BLAKE3 for key derivation in Sphinx packet format;",
|
||||
"Lioness for encryption of Sphinx payload."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "In the Fast (2-hop WireGuard-based) mode:",
|
||||
"alphabetList": [
|
||||
"ChaCha20 for symmetric encryption;",
|
||||
"Poly1305 for authentication;",
|
||||
"BLAKE2s for hashing."
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "legal-and-policies",
|
||||
"title": "Legal and policies",
|
||||
"intro": "NymVPN operates transparently with our users and operators. Review our Terms of Use, Policy Statements, and additional policies for more details.",
|
||||
"articles": [
|
||||
{
|
||||
"id": "legal-1",
|
||||
"title": "Terms of Use",
|
||||
"link": "terms",
|
||||
"intro": "The relationship between you and NymVPN.",
|
||||
"isExternal": true
|
||||
},
|
||||
{
|
||||
"id": "legal-2",
|
||||
"title": "Operators T&Cs",
|
||||
"link": "https://nymtech.net/terms-and-conditions/operators/v1.0.0",
|
||||
"intro": "The relationship between node operators and Nym.",
|
||||
"isExternal": true
|
||||
},
|
||||
{
|
||||
"id": "legal-3",
|
||||
"title": "Website privacy statement",
|
||||
"link": "privacy?type=website",
|
||||
"intro": "How we handle personal information on the NymVPN website.",
|
||||
"isExternal": true
|
||||
},
|
||||
{
|
||||
"id": "legal-4",
|
||||
"title": "Apps privacy statement",
|
||||
"link": "privacy?type=apps",
|
||||
"intro": "How we handle personal information in the NymVPN applications.",
|
||||
"isExternal": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "transparency",
|
||||
"title": "Transparency",
|
||||
"intro": "NymVPN is a service offered by Nym Technologies SA, a Swiss company owned by Harry Halpin and Alexis Roussel, two of its co-founders. NymVPN adheres to the Swiss data protection law (nFADP).",
|
||||
"articles": [
|
||||
{
|
||||
"id": "transparency-1",
|
||||
"title": "Led by a world-class team",
|
||||
"link": "https://nymtech.net/about/team",
|
||||
"intro": "Nym Technologies SA is lead by renowned scientists and privacy advocates.",
|
||||
"isExternal": true
|
||||
},
|
||||
{
|
||||
"id": "transparency-2",
|
||||
"title": "Signals of Trustworthy VPNs",
|
||||
"intro": "NymVPN upholds transparency standards by publicly sharing its responses to the \"Signals of Trustworthy VPNs\" questionnaire developed by the Center for Democracy & Technology.",
|
||||
"link": "signals-of-trustworthy-vpns",
|
||||
"content": [
|
||||
{
|
||||
"component": "TextList",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Corporate accountability",
|
||||
"description": "",
|
||||
"content": [
|
||||
{
|
||||
"title": "Question 1: What is the public facing and full legal name of the VPN service and any parent or holding companies?",
|
||||
"newlines": [
|
||||
"NymVPN is operated by Nym Technologies SA, a Swiss company headquartered in Neuchâtel, Switzerland. The company is privately owned by its co-founders, Harry Halpin and Alexis Roussel, with no parent or holding companies. Other co-founders are minority stakeholders of the company.",
|
||||
"Neither Nym Technologies SA, Harry Halpin, Alexis Roussel have ownership or economic stakes in other VPN companies. Harry Halpin was previously President of the Board of the LEAP Encryption Access Project (a centralized VPN for human-rights activists), a position which he left.",
|
||||
"NymVPN is solely operated by Nym Technologies SA, without involvement from any other company or partner."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Question 2: Does the company, or other companies involved in the operation or ownership of the service, have any ownership in VPN review websites?",
|
||||
"newlines": ["No."]
|
||||
},
|
||||
{
|
||||
"title": "Question 3: What is the service’s business model (i.e., how does the VPN make money)?",
|
||||
"newlines": [
|
||||
"NymVPN generates revenue exclusively through VPN subscriptions, which include both dVPN and mixnet access. We do not engage in selling user information, and we do not use customer data (if any) for any purposes other than operating the VPN service.",
|
||||
"We are considering making enterprise versions of our mixnet for potential partners. Nym Technologies SA has received a small amount of revenue from integration of the mixnet with other projects, including:"
|
||||
],
|
||||
"alphabetList": [
|
||||
"a grant from the ZCash Community Grants Program, to integrate the mixnet with ZCash wallets;",
|
||||
"R&D grants from the Next Generation Internet program of the European Commission, to enable better mixnet packet formats and anonymous credential technology."
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Data-logging practices",
|
||||
"description": "",
|
||||
"content": [
|
||||
{
|
||||
"title": "Question 4: Does the service store any data or metadata generated during a VPN session (from connection to disconnection) after the session is terminated? If so, what data?",
|
||||
"newlines": [
|
||||
"User Device: During the alpha phase and for debugging purposes, some connection data may be recorded in the app logs and stored on the user’s device. These logs are regularly deleted. As the NymVPN apps become more stable, Nym aims to make these logs less verbose. Users can review the data via the Settings > Logs menu in their NymVPN app (note: These logs are stored locally on the user device and are not shared with Nym or any third parties).",
|
||||
"Nym Technologies SA: Users have the option to voluntarily share anonymized crash reports (via Sentry) to help improve NymVPN. These reports are designed to ensure they do not contain any identifying information about individual users. By design, no other data about the user’s online activities is accessible to Nym Technologies SA.",
|
||||
"Node operators: NymVPN is a decentralized VPN, with servers operated by independent operators. By design, entry gateway operators may have access to a user’s IP address (but not their online activity), and exit gateway operators may view online activity (but cannot link it to a user’s IP address). According to our [Node Operators and Validators Terms and Conditions](https://nymtech.net/terms-and-conditions/operators/v1.0.0), operators commit not to 'collect, monitor, record, log, store, retain, or pass on to any third party Nym Node information or any information or data relating to the activities of end users of NymVPN or the VPN Services'.",
|
||||
"For more details, please refer to our [Privacy Statement](https://nymvpn.com/en/privacy?type=apps)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Question 5: Does your company store (or share with others) any user browsing and/or network activity data, including DNS lookups and records of domain names and websites visited?",
|
||||
"newlines": [
|
||||
"See question 4.",
|
||||
"DNS lookups: NymVPN does not operate a DNS service. As a result, DNS lookups are handled by the default DNS provider or the one configured by the user."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Question 6: Do you have a clear process for responding to legitimate requests for data from law enforcement and courts?",
|
||||
"newlines": [
|
||||
"NymVPN is operated by Nym Technologies SA, a Swiss company, and adheres to Swiss legislation. We maintain legal counsel to deal with any law enforcement requests.",
|
||||
"By design, as a decentralized VPN service, NymVPN does not hold any data related to users’ online activities. While NymVPN does have access to users’ payment data, these are not correlated to their VPN accounts through “zk-nyms”-based onboarding (zero-knowledge proofs).",
|
||||
"As Nym is decentralized, it is possible that requests for data from law enforcement and courts will go to decentralized nodes in our network."
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Security practices",
|
||||
"description": "",
|
||||
"content": [
|
||||
{
|
||||
"title": "Question 7: What do you do to protect against unauthorized access to customer data flows over the VPN?",
|
||||
"newlines": [
|
||||
"Auditing: NymVPN is committed to providing best-in-class privacy and security benefits to its users. The NymVPN codebase is fully open source, licensed under GPLv3 and the Apache Software company, and is available for anyone to audit. In July 2024, NymVPN and other core Nym technologies were audited by the reputable pen-testing company [Cure53](https://cure53.de/). The audit report will be published once the main findings have been addressed. Nym Technologies has also undergone several other security audits related to its mixnet and cryptography. For more details, please visit the NymVPN Trust Center.",
|
||||
"Bug bounty / vulnerability disclosure program: As of September 2024, NymVPN is planning a vulnerability disclosure program for security researchers to report issues to be launched in Q4 2024. This program will go live once the Cure53 audit findings have been addressed and released.",
|
||||
"Cryptographic protocols: Guided by top security, privacy, and cryptography experts, NymVPN relies on state-of-the-art cryptographic protocols, including (for the mixnet mode):"
|
||||
],
|
||||
"alphabetList": [
|
||||
"AES128 for secure communication between clients and entry nodes, as well as for encryption of the Sphinx header;",
|
||||
"BLAKE3 for key derivation in Sphinx packet format;",
|
||||
"Lioness for encryption of Sphinx payload."
|
||||
]
|
||||
},
|
||||
{
|
||||
"newlines": ["And (for the WireGuard-based mode):"],
|
||||
"alphabetList": [
|
||||
"ChaCha20 for symmetric encryption;",
|
||||
"Poly1305 for authentication;",
|
||||
"BLAKE2s for hashing."
|
||||
]
|
||||
},
|
||||
{
|
||||
"newlines": [
|
||||
"Software updating: NymVPN end-user apps and operator binaries are updated weekly or bi-weekly to ensure regular patching and security improvements.",
|
||||
"Server control and physical security: By design, Nym Technologies SA does not operate the VPN servers, instead relying on independent node operators. Nym Technologies SA also ensures the use of modern, securely managed internal tools and enforces strict employee security policies, including Multi-Factor Authentication."
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Question 8: What other controls does the service use to protect user data?",
|
||||
"newlines": ["See question 7."]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Context",
|
||||
"description": "",
|
||||
"content": [
|
||||
{
|
||||
"newlines": [
|
||||
"Following discussions at the RightsCon human rights conference in 2018, the Center for Democracy and Technology (CDT, a reputable nonprofit organization dedicated to advancing civil rights and civil liberties in the digital age) and prominent VPN vendors recognized a significant lack of trust and transparency within the VPN industry.",
|
||||
"In response, the CDT developed a list of 8 standardized questions focused on (1) corporate accountability, (2) data logging practices, and (3) security practices, allowing VPN providers to demonstrate their commitment to trustworthiness and a positive reputation.",
|
||||
"In our commitment to full transparency regarding our product and operations, we are sharing our responses to the 8 questions in the [Signals of Trustworthy VPNs](https://cdt.org/vpns/) questionnaire."
|
||||
]
|
||||
},
|
||||
{
|
||||
"newlines": ["Last updated: September 12, 2024"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "transparency-3",
|
||||
"title": "Imprint",
|
||||
"intro": "NymVPN is operated by Nym Technologies SA, a Swiss company based in the canton of Neuchâtel.",
|
||||
"link": "imprint",
|
||||
"isExternal": true
|
||||
},
|
||||
{
|
||||
"id": "transparency-4",
|
||||
"title": "Compliant with Swiss data laws",
|
||||
"intro": "As a Swiss company, Nym Technologies SA fully complies with the New Federal Act on Data Protection (nFADP).",
|
||||
"link": "https://www.kmu.admin.ch/kmu/en/home/facts-and-trends/digitization/data-protection/new-federal-act-on-data-protection-nfadp.html",
|
||||
"isExternal": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "support-to-freedom-advocates",
|
||||
"title": "Support to freedom advocates",
|
||||
"intro": "Nym demonstrates its commitment to advancing the cause of digital privacy and security with its support to freedom advocates.",
|
||||
"articles": [
|
||||
{
|
||||
"id": "support-to-freedom-advocates-1",
|
||||
"title": "Tails",
|
||||
"intro": "We sponsor Tails, a portable operating system that safeguards against surveillance; Installed on a USB stick, it ensures privacy and routes internet traffic through Tor.",
|
||||
"link": "https://tails.net/sponsors/index.en.html",
|
||||
"isExternal": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "other",
|
||||
"title": "Other",
|
||||
"intro": "Nym provides regular reports on the status of servers operated by our community.",
|
||||
"articles": [
|
||||
{
|
||||
"id": "Other-1",
|
||||
"title": "Status of nodes",
|
||||
"link": "https://explorer.nymtech.net",
|
||||
"intro": "Nym's community operates nodes in 80+ countries with high uptime.",
|
||||
"isExternal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||