Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 275417c186 | |||
| 40a92e07d6 | |||
| e83a12bd91 | |||
| 381162554e | |||
| 7a740c06fd | |||
| e65285ac7b | |||
| 715a3bd687 | |||
| 858f1ac13c | |||
| 3ee1328626 | |||
| 36ac825b43 | |||
| 165f189115 | |||
| b5fcfbe2fe | |||
| 7a38f1f469 | |||
| 5faca46235 | |||
| d780ac55b1 | |||
| c5f7d066b0 | |||
| 8cc90be8c6 | |||
| aae96e7537 | |||
| 39b521bc1f | |||
| 7339695ce8 | |||
| 0e1c9853aa | |||
| 76b9c669d7 | |||
| 553cfd098b | |||
| 40e1243f3c | |||
| 50d2ca0a12 | |||
| 32d9baaf02 | |||
| 0179f7648c | |||
| 45c04d63e2 | |||
| 0f8ac1506b | |||
| efdf27d1e9 |
@@ -23,7 +23,12 @@ jobs:
|
||||
node-version: 18
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: Install project dependencies
|
||||
run: cd ../.. && yarn --network-timeout 100000
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
@@ -31,10 +31,20 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: |
|
||||
export WASM_PACK_VERSION="v0.12.1"
|
||||
curl -LO https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
tar xvzf wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz -C $HOME/.cargo/bin --strip-components=1
|
||||
rm wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
|
||||
- name: Install the Apple developer certificate for code signing
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
@@ -78,6 +88,8 @@ jobs:
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
@@ -103,9 +115,10 @@ jobs:
|
||||
- id: release-info
|
||||
name: Prepare release info
|
||||
run: |
|
||||
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
|
||||
echo "version=$semver" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=nym-connect_$version_x64.dmg" >> "$GITHUB_OUTPUT"
|
||||
ref=${{ github.ref_name }}
|
||||
semver="${ref##nym-connect-}" && semver="${semver##v}"
|
||||
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=nym-connect_${version}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
|
||||
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/dmg/nym-connect_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
push-release-data:
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
@@ -61,6 +61,8 @@ jobs:
|
||||
env:
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -80,11 +82,11 @@ jobs:
|
||||
- id: release-info
|
||||
name: Prepare release info
|
||||
run: |
|
||||
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
|
||||
echo "version=$semver" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=nym-connect_$version_amd64.AppImage" >> "$GITHUB_OUTPUT"
|
||||
ref=${{ github.ref_name }}
|
||||
semver="${ref##nym-connect-}" && semver="${semver##v}"
|
||||
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=nym-connect_${version}_amd64.AppImage" >> "$GITHUB_OUTPUT"
|
||||
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/appimage/nym-connect_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/push-release-data.yml
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
@@ -79,6 +79,8 @@ jobs:
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
@@ -99,9 +101,10 @@ jobs:
|
||||
- id: release-info
|
||||
name: Prepare release info
|
||||
run: |
|
||||
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
|
||||
echo "version=$semver" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=nym-connect_$version_x64_en-US.msi" >> "$GITHUB_OUTPUT"
|
||||
ref=${{ github.ref_name }}
|
||||
semver="${ref##nym-connect-}" && semver="${semver##v}"
|
||||
echo "version=${semver}" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=nym-connect_${version}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
|
||||
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/msi/nym-connect_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
push-release-data:
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
name: Publish Nym Connect - desktop (MacOS)
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
required: true
|
||||
description: Release tag (nym-connect-s-v*)
|
||||
type: string
|
||||
default: 'nym-connect-s-v1.0.0'
|
||||
push:
|
||||
tags:
|
||||
- nym-connect-s-v*
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-latest]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install the Apple developer certificate for code signing
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
# import certificate and provisioning profile from secrets
|
||||
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
|
||||
|
||||
# create temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
|
||||
# import certificate to keychain
|
||||
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Prepare for build
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }}
|
||||
run: ./scripts/pre_medium_build.sh
|
||||
|
||||
- name: Install app dependencies and build it
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
NYM_CONNECT_ENABLE_MEDIUM: 1
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect-s_1.0.0_x64.dmg
|
||||
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect-s_1*_x64.dmg
|
||||
retention-days: 30
|
||||
|
||||
- name: Clean up keychain
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/dmg/*.dmg
|
||||
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
|
||||
@@ -1,85 +0,0 @@
|
||||
name: Publish NymConnect S - desktop (Ubuntu)
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
required: true
|
||||
description: Release tag (nym-connect-s-v*)
|
||||
type: string
|
||||
default: 'nym-connect-s-v1.0.0'
|
||||
push:
|
||||
tags:
|
||||
- nym-connect-s-v*
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [custom-runner-linux]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Tauri dependencies
|
||||
run: >
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Prepare for build
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }}
|
||||
run: ./scripts/pre_medium_build.sh
|
||||
|
||||
- name: Build app
|
||||
run: yarn build
|
||||
env:
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
NYM_CONNECT_ENABLE_MEDIUM: 1
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect-s.AppImage.tar.gz
|
||||
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect-s_1*_amd64.AppImage
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||
@@ -1,104 +0,0 @@
|
||||
name: Publish Nym Connect - desktop (Windows 10)
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
required: true
|
||||
description: Release tag (nym-connect-s-v*)
|
||||
type: string
|
||||
default: 'nym-connect-s-v1.0.0'
|
||||
push:
|
||||
tags:
|
||||
- nym-connect-s-v*
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [windows10]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- name: Clean up first
|
||||
continue-on-error: true
|
||||
working-directory: .
|
||||
run: |
|
||||
cd ..
|
||||
del /s /q /A:H nym
|
||||
rmdir /s /q nym
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Import signing certificate
|
||||
env:
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
||||
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
||||
Remove-Item -path certificate -include tempCert.txt
|
||||
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
shell: bash
|
||||
run: yarn --network-timeout 100000
|
||||
|
||||
- name: Prepare for build
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }}
|
||||
run: ./scripts/pre_medium_build.sh
|
||||
|
||||
- name: Build and sign it
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
NYM_CONNECT_ENABLE_MEDIUM: 1
|
||||
run: yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect-s_1.0.0_x64_en-US.msi
|
||||
path: nym-connect/desktop/target/release/bundle/msi/nym-connect-s_1*_x64_en-US.msi
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[book]
|
||||
title = "Nym Developer Portal"
|
||||
authors = ["Max Hampshire"]
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
@@ -47,10 +47,10 @@ assets_version = "2.0.0" # do not edit: managed by `mdbook-admonish install`
|
||||
# variables preprocessor: import variables into files
|
||||
# https://gitlab.com/tglman/mdbook-variables/
|
||||
[preprocessor.variables.variables]
|
||||
# code prerequisites versions
|
||||
minimum_rust_version = "1.66"
|
||||
# TODO remove this in place of develop in next release
|
||||
platform_release_version = "v1.1.21"
|
||||
# vars for links: TODO think on how to streamline updating
|
||||
platform_release_version = "v1.1.25"
|
||||
wallet_release_version = "v1.2.7"
|
||||
|
||||
[preprocessor.last-changed]
|
||||
command = "mdbook-last-changed"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[book]
|
||||
title = "Nym Docs"
|
||||
authors = ["Max Hampshire"]
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
description = "Nym technical documentation"
|
||||
language = "en"
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian, spanish next
|
||||
@@ -49,8 +49,8 @@ assets_version = "2.0.0" # do not edit: managed by `mdbook-admonish install`
|
||||
[preprocessor.variables.variables]
|
||||
minimum_rust_version = "1.66"
|
||||
# vars for links: TODO think on how to streamline updating
|
||||
platform_release_version = "v1.1.22"
|
||||
wallet_release_version = "v1.2.5"
|
||||
platform_release_version = "v1.1.25"
|
||||
wallet_release_version = "v1.2.7"
|
||||
|
||||
[preprocessor.last-changed]
|
||||
command = "mdbook-last-changed"
|
||||
|
||||
@@ -153,8 +153,6 @@ Follow these steps to upgrade your binary and update its config file:
|
||||
* re-run `init` with the same values as you used initially. **This will just update the config file, it will not overwrite existing keys**.
|
||||
* restart your gateway process with the new binary.
|
||||
|
||||
> Do **not** use the `upgrade` command: there is a known error with the command that will be fixed in a subsequent release.
|
||||
|
||||
#### Step 2: updating your node information in the smart contract
|
||||
Follow these steps to update the information about your node which is publically avaliable from the [Nym API](https://validator.nymtech.net/api/swagger/index.html) and information displayed on the [mixnet explorer](https://explorer.nymtech.net).
|
||||
|
||||
|
||||
@@ -191,8 +191,6 @@ Follow these steps to upgrade your mix node binary and update its config file:
|
||||
* re-run `init` with the same values as you used initially. **This will just update the config file, it will not overwrite existing keys**.
|
||||
* restart your mix node process with the new binary.
|
||||
|
||||
> Do **not** use the `upgrade` command: there is a known error with the command that will be fixed in a subsequent release.
|
||||
|
||||
#### Step 2: updating your node information in the smart contract
|
||||
Follow these steps to update the information about your mix node which is publically avaliable from the [Nym API](https://validator.nymtech.net/api/swagger/index.html) and information displayed on the [mixnet explorer](https://explorer.nymtech.net).
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<!-- cmdrun ../../../../target/release/nym-network-requester --version | grep "Build Version" | cut -b 21-26 -->
|
||||
```
|
||||
|
||||
|
||||
## Network Requester Whitelist
|
||||
If you have access to a server, you can run the network requester, which allows Nym users to send outbound requests from their local machine through the mixnet to a server, which then makes the request on their behalf, shielding them (and their metadata) from clearnet, untrusted and unknown infrastructure, such as email or message client servers.
|
||||
|
||||
@@ -65,6 +64,34 @@ p2pify.com
|
||||
2001:67c:4e8::/48
|
||||
2001:b28:f23c::/48
|
||||
2a0a:f280::/32
|
||||
|
||||
# nym matrix server
|
||||
nymtech.chat
|
||||
|
||||
# generic matrix server backends
|
||||
vector.im
|
||||
matrix.org
|
||||
|
||||
# monero desktop - mainnet
|
||||
212.83.175.67
|
||||
212.83.172.165
|
||||
176.9.0.187
|
||||
88.198.163.90
|
||||
95.217.25.101
|
||||
136.244.105.131
|
||||
104.238.221.81
|
||||
66.85.74.134
|
||||
88.99.173.38
|
||||
51.79.173.165
|
||||
|
||||
# monero desktop - stagenet
|
||||
162.210.173.150
|
||||
176.9.0.187
|
||||
88.99.173.38
|
||||
51.79.173.165
|
||||
|
||||
# alephium
|
||||
alephium.org
|
||||
```
|
||||
|
||||
## Network Requester Directory
|
||||
@@ -193,25 +220,32 @@ sudo ufw enable
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
Finally open your requester's p2p port, as well as ports for ssh and incoming traffic connections:
|
||||
Finally open your requester's ssh port to incoming administration connections:
|
||||
|
||||
```
|
||||
sudo ufw allow 22,9000/tcp
|
||||
sudo ufw allow 22/tcp
|
||||
# check the status of the firewall
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
For more information about your requester's port configuration, check the [requester port reference table](./network-requester-setup.md#requester-port-reference) below.
|
||||
|
||||
## Using your network requester
|
||||
|
||||
The next thing to do is use your requester, share its address with friends (or whoever you want to help privacy-enhance their app traffic). Is this safe to do? If it was an open proxy, this would be unsafe, because any Nym user could make network requests to any system on the internet.
|
||||
|
||||
To make things a bit less stressful for administrators, the Network Requester drops all incoming requests by default. In order for it to make requests, you need to add specific domains to the `allowed.list` file at `$HOME/.nym/service-providers/network-requester/allowed.list`.
|
||||
|
||||
### Global vs local allow lists
|
||||
Your Network Requester will check for a domain against 2 lists before allowing traffic through for a particular domain or IP.
|
||||
|
||||
* The first list is the default list on the [nymtech.net server](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt). Your Requester will not check against this list every time, but instead will keep a record of accepted domains in memory.
|
||||
|
||||
* The second is the local `allowed.list` file.
|
||||
|
||||
### Supporting custom domains with your network requester
|
||||
It is easy to add new domains and services to your network requester - simply find out which endpoints (both URLs and raw IP addresses are supported) you need to whitelist, and then add these endpoints to your `allowed.list`.
|
||||
|
||||
> In order to keep things more organised, you can now use comments in the `allow.list` like the example at the top of this page.
|
||||
|
||||
How to go about this? Have a look in your nym-network-requester config directory:
|
||||
|
||||
```
|
||||
@@ -249,7 +283,3 @@ This command should return the following:
|
||||
### Requester port reference
|
||||
|
||||
All network-requester-specific port configuration can be found in `$HOME/.nym/service-providers/network-requester/<YOUR_ID>/config/config.toml`. If you do edit any port configs, remember to restart your client and requester processes.
|
||||
|
||||
| Default port | Use |
|
||||
|--------------|---------------------------|
|
||||
| 9000 | Listen for Client traffic |
|
||||
|
||||
@@ -56,14 +56,19 @@ If you're integrating mixnet functionality into an existing app and want to inte
|
||||
### Anonymous replies with SURBs
|
||||
Both functions used to send messages through the mixnet (`send_str` and `send_bytes`) send a pre-determined number of SURBs along with their messages by default.
|
||||
|
||||
The number of SURBs is set [here](https://github.com/nymtech/nym/blob/release/{{platform_release_version}}/sdk/rust/nym-sdk/src/mixnet/client.rs#L35):
|
||||
The number of SURBs is set [here](https://github.com/nymtech/nym/blob/release/{{platform_release_version}}/sdk/rust/nym-sdk/src/mixnet/client.rs#L34):
|
||||
|
||||
```rust,noplayground
|
||||
{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:30}}
|
||||
{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:34}}
|
||||
```
|
||||
|
||||
You can read more about how SURBs function under the hood [here](../architecture/traffic-flow.md#private-replies-using-surbs).
|
||||
|
||||
In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to:
|
||||
|
||||
```rust,noplayground
|
||||
{{#include ../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}}
|
||||
```
|
||||
|
||||
### Importing and using a custom network topology
|
||||
If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or peforming research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html) (`examples/custom_topology_provider.rs`).
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v1.1.15] (2023-07-25)
|
||||
|
||||
- NC Desktop - remove sentry DSN from code ([#3694])
|
||||
- NC - Add Alephium wallet in the supported app list ([#3681])
|
||||
|
||||
[#3694]: https://github.com/nymtech/nym/issues/3694
|
||||
[#3681]: https://github.com/nymtech/nym/issues/3681
|
||||
|
||||
## [v1.1.14] (2023-07-04)
|
||||
|
||||
- Nym connect fails to start when encountering an old config version ([#3588])
|
||||
|
||||
Generated
+302
-16
@@ -8,6 +8,15 @@ version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
@@ -88,6 +97,9 @@ name = "anyhow"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
@@ -193,6 +205,21 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide 0.7.1",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.1.1"
|
||||
@@ -1238,6 +1265,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debugid"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"uuid 1.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.6.1"
|
||||
@@ -1377,9 +1414,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.6"
|
||||
version = "0.15.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0"
|
||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
@@ -1532,6 +1569,12 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
@@ -1640,6 +1683,18 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "findshlibs"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fix-path-env"
|
||||
version = "0.1.0"
|
||||
@@ -1656,7 +1711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1985,6 +2040,12 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.15.12"
|
||||
@@ -2217,7 +2278,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"indexmap 1.9.2",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@@ -2256,6 +2317,12 @@ dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.7.0"
|
||||
@@ -2391,6 +2458,17 @@ dependencies = [
|
||||
"digest 0.10.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"match_cfg",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html5ever"
|
||||
version = "0.25.2"
|
||||
@@ -2618,6 +2696,16 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "infer"
|
||||
version = "0.7.0"
|
||||
@@ -3025,6 +3113,12 @@ dependencies = [
|
||||
"tendril",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "match_cfg"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
@@ -3082,6 +3176,15 @@ dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.6"
|
||||
@@ -3429,6 +3532,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
"dirs 4.0.0",
|
||||
"dotenvy",
|
||||
"eyre",
|
||||
"fern",
|
||||
"fix-path-env",
|
||||
@@ -3449,6 +3553,8 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"rust-embed",
|
||||
"sentry",
|
||||
"sentry-log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
@@ -3462,6 +3568,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"toml 0.7.4",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"yaml-rust",
|
||||
@@ -4076,6 +4183,15 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
@@ -4165,6 +4281,17 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.5.0"
|
||||
@@ -4530,7 +4657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590"
|
||||
dependencies = [
|
||||
"base64 0.21.2",
|
||||
"indexmap",
|
||||
"indexmap 1.9.2",
|
||||
"line-wrap",
|
||||
"quick-xml 0.28.1",
|
||||
"serde",
|
||||
@@ -4546,7 +4673,7 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5017,6 +5144,12 @@ dependencies = [
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
@@ -5129,7 +5262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"indexmap",
|
||||
"indexmap 1.9.2",
|
||||
"schemars_derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -5263,6 +5396,136 @@ dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01b0ad16faa5d12372f914ed40d00bda21a6d1bdcc99264c5e5e1c9495cf3654"
|
||||
dependencies = [
|
||||
"httpdate",
|
||||
"native-tls",
|
||||
"reqwest",
|
||||
"sentry-anyhow",
|
||||
"sentry-backtrace",
|
||||
"sentry-contexts",
|
||||
"sentry-core",
|
||||
"sentry-debug-images",
|
||||
"sentry-panic",
|
||||
"sentry-tracing",
|
||||
"tokio",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-anyhow"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f3a571f02f9982af445af829c4837fe4857568a431bd2bed9f7cf88de4a6c44"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"sentry-backtrace",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-backtrace"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11f2ee8f147bb5f22ac59b5c35754a759b9a6f6722402e2a14750b2a63fc59bd"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-contexts"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcd133362c745151eeba0ac61e3ba8350f034e9fe7509877d08059fe1d7720c6"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"libc",
|
||||
"os_info",
|
||||
"rustc_version",
|
||||
"sentry-core",
|
||||
"uname",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-core"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7163491708804a74446642ff2c80b3acd668d4b9e9f497f85621f3d250fd012b"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rand 0.8.5",
|
||||
"sentry-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-debug-images"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a5003d7ff08aa3b2b76994080b183e8cfa06c083e280737c9cee02ca1c70f5e"
|
||||
dependencies = [
|
||||
"findshlibs",
|
||||
"once_cell",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-log"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2558fc4a85326e6063711b45ce82ed6b18cdacd0732580c1567da914ac1df33e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-panic"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4dfe8371c9b2e126a8b64f6fefa54cef716ff2a50e63b5558a48b899265bccd"
|
||||
dependencies = [
|
||||
"sentry-backtrace",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-tracing"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aca8b88978677a27ee1a91beafe4052306c474c06f582321fde72d2e2cc2f7f"
|
||||
dependencies = [
|
||||
"sentry-backtrace",
|
||||
"sentry-core",
|
||||
"tracing-core",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-types"
|
||||
version = "0.31.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e7a88e0c1922d19b3efee12a8215f6a8a806e442e665ada71cc222cab72985f"
|
||||
dependencies = [
|
||||
"debugid",
|
||||
"getrandom 0.2.10",
|
||||
"hex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"time",
|
||||
"url",
|
||||
"uuid 1.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.158"
|
||||
@@ -5345,9 +5608,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
|
||||
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -5677,7 +5940,7 @@ dependencies = [
|
||||
"futures-util",
|
||||
"hashlink 0.7.0",
|
||||
"hex",
|
||||
"indexmap",
|
||||
"indexmap 1.9.2",
|
||||
"itoa 1.0.6",
|
||||
"libc",
|
||||
"libsqlite3-sys",
|
||||
@@ -5723,7 +5986,7 @@ dependencies = [
|
||||
"futures-util",
|
||||
"hashlink 0.8.1",
|
||||
"hex",
|
||||
"indexmap",
|
||||
"indexmap 1.9.2",
|
||||
"itoa 1.0.6",
|
||||
"libc",
|
||||
"libsqlite3-sys",
|
||||
@@ -6580,20 +6843,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
|
||||
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.19.10"
|
||||
version = "0.19.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
|
||||
checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.0.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@@ -6750,6 +7013,15 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uname"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
@@ -6805,6 +7077,19 @@ version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9"
|
||||
dependencies = [
|
||||
"base64 0.21.2",
|
||||
"log",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
@@ -6842,6 +7127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
||||
dependencies = [
|
||||
"getrandom 0.2.10",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nym/nym-connect",
|
||||
"version": "1.1.13",
|
||||
"version": "1.1.15",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@@ -115,4 +115,4 @@
|
||||
"webpack-merge": "^5.8.0",
|
||||
"yaml-loader": "^0.8.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-connect"
|
||||
version = "1.1.13"
|
||||
version = "1.1.15"
|
||||
description = "nym-connect"
|
||||
authors = ["Nym Technologies SA"]
|
||||
license = ""
|
||||
@@ -43,7 +43,10 @@ time = { version = "0.3.17", features = ["local-offset"] }
|
||||
tokio = { version = "1.24.1", features = ["sync", "time"] }
|
||||
url = "2.2"
|
||||
yaml-rust = "0.4"
|
||||
|
||||
toml = "0.7"
|
||||
sentry = { version = "0.31.5", features = [ "anyhow" ] }
|
||||
sentry-log = "0.31.5"
|
||||
dotenvy = "0.15.7"
|
||||
|
||||
nym-client-core = { path = "../../../common/client-core" }
|
||||
nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
if env::var_os("NYM_CONNECT_ENABLE_MEDIUM").is_some() {
|
||||
println!("cargo:rustc-cfg=medium_enabled");
|
||||
}
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
mod constants;
|
||||
|
||||
use constants::{SENTRY_DSN_JS, SENTRY_DSN_RUST};
|
||||
|
||||
fn main() {
|
||||
// set these env vars at compile time
|
||||
if let Ok(dsn) = env::var(SENTRY_DSN_RUST) {
|
||||
println!("cargo:rustc-env={}={}", SENTRY_DSN_RUST, dsn);
|
||||
}
|
||||
if let Ok(dsn) = env::var(SENTRY_DSN_JS) {
|
||||
println!("cargo:rustc-env={}={}", SENTRY_DSN_JS, dsn);
|
||||
}
|
||||
tauri_build::build();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ mod old_config_v1_1_20_2;
|
||||
mod persistence;
|
||||
mod template;
|
||||
mod upgrade;
|
||||
mod user_data;
|
||||
|
||||
pub use user_data::PrivacyLevel;
|
||||
pub use user_data::UserData;
|
||||
|
||||
static SOCKS5_CONFIG_ID: &str = "nym-connect";
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
use eyre::{eyre, Context, Result};
|
||||
use log::error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fs, str};
|
||||
use tauri::api::path::data_dir;
|
||||
|
||||
const DATA_DIR: &str = "nym-connect";
|
||||
const DATA_FILE: &str = "user-data.toml";
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Default)]
|
||||
pub enum PrivacyLevel {
|
||||
#[default]
|
||||
High,
|
||||
Medium,
|
||||
}
|
||||
|
||||
// User data is read from and write on disk
|
||||
// Linux: $XDG_DATA_HOME or $HOME/.local/share/
|
||||
// macOS: $HOME/Library/Application Support
|
||||
// Windows: {FOLDERID_RoamingAppData}
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct UserData {
|
||||
pub monitoring: Option<bool>,
|
||||
pub privacy_level: Option<PrivacyLevel>,
|
||||
}
|
||||
|
||||
fn create_directory_path() -> Result<()> {
|
||||
let mut data_dir = data_dir().ok_or(eyre!("Failed to retrieve data directory"))?;
|
||||
data_dir.push(DATA_DIR);
|
||||
|
||||
fs::create_dir_all(&data_dir).context(format!(
|
||||
"Failed to create user data directory path {}",
|
||||
data_dir.display()
|
||||
))
|
||||
}
|
||||
|
||||
impl UserData {
|
||||
pub fn read() -> Result<Self> {
|
||||
// create the full directory path if it is missing
|
||||
create_directory_path()?;
|
||||
|
||||
let mut data_path = data_dir().ok_or(eyre!("Failed to retrieve data directory"))?;
|
||||
|
||||
data_path.push(DATA_DIR);
|
||||
data_path.push(DATA_FILE);
|
||||
let content = fs::read(&data_path)
|
||||
.context(format!("Failed to read user data {}", data_path.display()))?;
|
||||
|
||||
toml::from_str::<UserData>(str::from_utf8(&content)?).map_err(|e| {
|
||||
error!("{}", e);
|
||||
eyre!("{e}")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write(&self) -> Result<()> {
|
||||
// create the full directory path if it is missing
|
||||
create_directory_path()?;
|
||||
|
||||
let mut data_path = data_dir().ok_or(eyre!("Failed to retrieve data directory"))?;
|
||||
|
||||
data_path.push(DATA_DIR);
|
||||
data_path.push(DATA_FILE);
|
||||
let toml = toml::to_string(&self)?;
|
||||
fs::write(data_path, toml)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// env var keys
|
||||
pub const SENTRY_DSN_RUST: &str = "SENTRY_DSN_RUST";
|
||||
pub const SENTRY_DSN_JS: &str = "SENTRY_DSN_JS";
|
||||
@@ -70,6 +70,8 @@ pub enum BackendError {
|
||||
NewWindowError,
|
||||
#[error("unable to parse the specified gateway")]
|
||||
UnableToParseGateway,
|
||||
#[error("unable to write user data to disk")]
|
||||
UserDataWriteError,
|
||||
|
||||
#[error("unable to load keys: {source}")]
|
||||
UnableToLoadKeys {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use fern::colors::{Color, ColoredLevelConfig};
|
||||
use log::Level;
|
||||
use sentry::Level as SentryLevel;
|
||||
use serde::Serialize;
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
use std::str::FromStr;
|
||||
@@ -22,7 +24,10 @@ fn formatted_time() -> String {
|
||||
_now.format(&format).unwrap()
|
||||
}
|
||||
|
||||
pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerError> {
|
||||
pub fn setup_logging(
|
||||
app_handle: tauri::AppHandle,
|
||||
monitoring: bool,
|
||||
) -> Result<(), log::SetLoggerError> {
|
||||
let colors = ColoredLevelConfig::new()
|
||||
.trace(Color::Magenta)
|
||||
.debug(Color::Blue)
|
||||
@@ -61,6 +66,21 @@ pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerE
|
||||
level: record.level().into(),
|
||||
};
|
||||
app_handle.emit_all("log://log", msg).unwrap();
|
||||
}))
|
||||
.chain(fern::Output::call(move |record| {
|
||||
if !monitoring {
|
||||
return;
|
||||
}
|
||||
let level = match record.level() {
|
||||
Level::Error => SentryLevel::Error,
|
||||
Level::Warn => SentryLevel::Warning,
|
||||
Level::Info => SentryLevel::Info,
|
||||
_ => SentryLevel::Debug,
|
||||
};
|
||||
// only send error and warn logs to sentry
|
||||
if let Level::Error | Level::Warn = record.level() {
|
||||
sentry::capture_message(&record.args().to_string(), level);
|
||||
};
|
||||
}));
|
||||
|
||||
base_config
|
||||
|
||||
@@ -3,50 +3,75 @@
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
|
||||
use nym_config::defaults::setup_env;
|
||||
use tauri::Manager;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::config::UserData;
|
||||
use crate::menu::{create_tray_menu, tray_menu_event_handler};
|
||||
use crate::state::{is_medium_enabled, State};
|
||||
use crate::state::State;
|
||||
use crate::window::window_toggle;
|
||||
|
||||
mod config;
|
||||
mod constants;
|
||||
mod error;
|
||||
mod events;
|
||||
mod logging;
|
||||
mod menu;
|
||||
mod models;
|
||||
mod monitoring;
|
||||
mod operations;
|
||||
mod state;
|
||||
mod tasks;
|
||||
mod window;
|
||||
|
||||
fn main() {
|
||||
if is_medium_enabled() {
|
||||
println!("medium mode enabled");
|
||||
std::env::set_var("NYM_CONNECT_DISABLE_COVER", "1");
|
||||
std::env::set_var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS", "1");
|
||||
std::env::set_var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS", "1");
|
||||
}
|
||||
dotenvy::dotenv().ok();
|
||||
setup_env(None);
|
||||
println!("Starting up...");
|
||||
|
||||
// As per breaking change description here
|
||||
// https://github.com/tauri-apps/tauri/blob/feac1d193c6d618e49916ad0707201f43d5cdd36/tooling/bundler/CHANGELOG.md
|
||||
if let Err(error) = fix_path_env::fix() {
|
||||
log::warn!("Failed to fix PATH: {error}");
|
||||
println!("Failed to fix PATH: {error}");
|
||||
}
|
||||
|
||||
let user_data = UserData::read().unwrap_or_else(|e| {
|
||||
println!("{}", e);
|
||||
println!("Fallback to default");
|
||||
UserData::default()
|
||||
});
|
||||
|
||||
let monitoring = user_data.monitoring.unwrap_or(false);
|
||||
let mut _sentry_guard;
|
||||
|
||||
if monitoring {
|
||||
match monitoring::init() {
|
||||
Ok(guard) => {
|
||||
println!("Monitoring and error reporting enabled");
|
||||
|
||||
// we must keep the sentry guard in scope during app lifetime
|
||||
_sentry_guard = guard;
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Unable to init monitoring: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let context = tauri::generate_context!();
|
||||
tauri::Builder::default()
|
||||
.manage(Arc::new(RwLock::new(State::new())))
|
||||
.manage(Arc::new(RwLock::new(State::new(user_data))))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
crate::operations::config::get_config_file_location,
|
||||
crate::operations::config::get_config_id,
|
||||
crate::operations::common::get_env,
|
||||
crate::operations::common::get_user_data,
|
||||
crate::operations::common::set_monitoring,
|
||||
crate::operations::common::set_privacy_level,
|
||||
crate::operations::connection::connect::get_gateway,
|
||||
crate::operations::connection::connect::get_service_provider,
|
||||
crate::operations::connection::connect::set_gateway,
|
||||
@@ -57,7 +82,6 @@ fn main() {
|
||||
crate::operations::connection::status::get_connection_status,
|
||||
crate::operations::connection::status::get_gateway_connection_status,
|
||||
crate::operations::connection::status::start_connection_health_check_task,
|
||||
crate::operations::connection::status::is_medium_mode_enabled,
|
||||
crate::operations::directory::get_services,
|
||||
crate::operations::directory::get_gateways_detailed,
|
||||
crate::operations::export::export_keys,
|
||||
@@ -83,7 +107,7 @@ fn main() {
|
||||
);
|
||||
}
|
||||
})
|
||||
.setup(|app| Ok(crate::logging::setup_logging(app.app_handle())?))
|
||||
.setup(move |app| Ok(crate::logging::setup_logging(app.app_handle(), monitoring)?))
|
||||
.system_tray(create_tray_menu())
|
||||
.on_system_tray_event(tray_menu_event_handler)
|
||||
.run(context)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
use std::env;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use sentry::ClientInitGuard;
|
||||
|
||||
use crate::constants::{SENTRY_DSN_JS, SENTRY_DSN_RUST};
|
||||
|
||||
pub fn init() -> Result<ClientInitGuard> {
|
||||
// if these env vars were set at compile time, use their value
|
||||
if let Some(v) = option_env!("SENTRY_DSN_RUST") {
|
||||
env::set_var(SENTRY_DSN_RUST, v);
|
||||
}
|
||||
if let Some(v) = option_env!("SENTRY_DSN_JS") {
|
||||
env::set_var(SENTRY_DSN_JS, v);
|
||||
}
|
||||
|
||||
let dsn = env::var(SENTRY_DSN_RUST).context(format!("{} env var not set", SENTRY_DSN_RUST))?;
|
||||
println!("using DSN {dsn}");
|
||||
let guard = sentry::init((
|
||||
dsn,
|
||||
sentry::ClientOptions {
|
||||
release: sentry::release_name!(),
|
||||
sample_rate: 1.0, // TODO lower this in prod
|
||||
traces_sample_rate: 1.0,
|
||||
..Default::default() // TODO add data scrubbing
|
||||
// see https://docs.sentry.io/platforms/rust/data-management/sensitive-data/
|
||||
},
|
||||
));
|
||||
|
||||
sentry::configure_scope(|scope| {
|
||||
scope.set_user(Some(sentry::User {
|
||||
id: Some("nym".into()),
|
||||
..Default::default()
|
||||
}));
|
||||
});
|
||||
|
||||
Ok(guard)
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
use crate::config::PrivacyLevel;
|
||||
use crate::error::Result;
|
||||
use crate::{config::UserData, state::State};
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_env(variable: String) -> Option<String> {
|
||||
@@ -7,3 +12,27 @@ pub async fn get_env(variable: String) -> Option<String> {
|
||||
|
||||
var
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_user_data(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<UserData> {
|
||||
let guard = state.read().await;
|
||||
Ok(guard.get_user_data().clone())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn set_monitoring(
|
||||
enabled: bool,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<()> {
|
||||
let mut guard = state.write().await;
|
||||
guard.set_monitoring(enabled)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn set_privacy_level(
|
||||
privacy_level: PrivacyLevel,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<()> {
|
||||
let mut guard = state.write().await;
|
||||
guard.set_privacy_level(privacy_level)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ pub async fn start_connecting(
|
||||
window: tauri::Window<tauri::Wry>,
|
||||
) -> Result<ConnectResult> {
|
||||
log::trace!("Start connecting");
|
||||
|
||||
let (msg_receiver, exit_status_receiver) = {
|
||||
let mut state_w = state.write().await;
|
||||
state_w.start_connecting(&window).await?
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::models::{ConnectionStatusKind, ConnectivityTestResult, GatewayConnectionStatusKind};
|
||||
use crate::state::{is_medium_enabled, State};
|
||||
use crate::state::State;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_connection_status(
|
||||
@@ -42,8 +42,3 @@ pub fn start_connection_health_check_task(
|
||||
) {
|
||||
tasks::start_connection_check(state.inner().clone(), window);
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn is_medium_mode_enabled(_state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<bool> {
|
||||
Ok(is_medium_enabled())
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::config::PrivacyLevel;
|
||||
use crate::error::Result;
|
||||
use crate::models::{
|
||||
DirectoryService, DirectoryServiceProvider, HarbourMasterService, PagedResult,
|
||||
};
|
||||
use crate::state::is_medium_enabled;
|
||||
use crate::state::State;
|
||||
use nym_api_requests::models::GatewayBondAnnotated;
|
||||
use nym_contracts_common::types::Percent;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
static SERVICE_PROVIDER_WELLKNOWN_URL: &str =
|
||||
"https://nymtech.net/.wellknown/connect/service-providers.json";
|
||||
@@ -20,21 +23,20 @@ static HARBOUR_MASTER_URL: &str = "https://harbourmaster.nymtech.net/v1/services
|
||||
static GATEWAYS_DETAILED_URL: &str =
|
||||
"https://validator.nymtech.net/api/v1/status/gateways/detailed";
|
||||
|
||||
fn get_services_url() -> &'static str {
|
||||
if is_medium_enabled() {
|
||||
return SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM;
|
||||
}
|
||||
SERVICE_PROVIDER_WELLKNOWN_URL
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_services() -> Result<Vec<DirectoryServiceProvider>> {
|
||||
pub async fn get_services(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Vec<DirectoryServiceProvider>> {
|
||||
log::trace!("Fetching services");
|
||||
let all_services = fetch_services().await?;
|
||||
|
||||
let guard = state.read().await;
|
||||
let privacy_level = guard.get_user_data().privacy_level.unwrap_or_default();
|
||||
|
||||
let all_services = fetch_services(&privacy_level).await?;
|
||||
log::trace!("Received: {:#?}", all_services);
|
||||
|
||||
// Early return if we're running with medium toggle enabled
|
||||
if is_medium_enabled() {
|
||||
if let PrivacyLevel::Medium = privacy_level {
|
||||
return Ok(all_services.into_iter().flat_map(|sp| sp.items).collect());
|
||||
}
|
||||
|
||||
@@ -100,8 +102,12 @@ fn filter_out_poor_gateways(
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn fetch_services() -> Result<Vec<DirectoryService>> {
|
||||
let services_url = get_services_url();
|
||||
async fn fetch_services(privacy_level: &PrivacyLevel) -> Result<Vec<DirectoryService>> {
|
||||
let services_url = match privacy_level {
|
||||
PrivacyLevel::Medium => SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM,
|
||||
_ => SERVICE_PROVIDER_WELLKNOWN_URL,
|
||||
};
|
||||
|
||||
let services_res = reqwest::get(services_url)
|
||||
.await?
|
||||
.json::<Vec<DirectoryService>>()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use futures::SinkExt;
|
||||
use log::error;
|
||||
use nym_client_core::error::ClientCoreStatusMessage;
|
||||
use nym_socks5_client_core::{Socks5ControlMessage, Socks5ControlMessageSender};
|
||||
use std::time::Duration;
|
||||
@@ -7,6 +8,8 @@ use tauri::Manager;
|
||||
use tokio::time::Instant;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::config::PrivacyLevel;
|
||||
use crate::config::UserData;
|
||||
use crate::{
|
||||
config::{self, socks5_config_id_appended_with},
|
||||
error::{BackendError, Result},
|
||||
@@ -65,10 +68,13 @@ pub struct State {
|
||||
/// The latest end-to-end connectivity test result. The first test is initiated on connection
|
||||
/// established. Additional tests can be triggered.
|
||||
connectivity_test_result: ConnectivityTestResult,
|
||||
|
||||
/// User data saved on disk, like user settings
|
||||
user_data: UserData,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(user_data: UserData) -> Self {
|
||||
State {
|
||||
status: ConnectionStatusKind::Disconnected,
|
||||
service_provider: None,
|
||||
@@ -76,6 +82,7 @@ impl State {
|
||||
socks5_client_sender: None,
|
||||
gateway_connectivity: GatewayConnectivity::Good,
|
||||
connectivity_test_result: ConnectivityTestResult::NotAvailable,
|
||||
user_data,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +100,26 @@ impl State {
|
||||
self.gateway_connectivity
|
||||
}
|
||||
|
||||
pub fn get_user_data(&self) -> &UserData {
|
||||
&self.user_data
|
||||
}
|
||||
|
||||
pub fn set_monitoring(&mut self, enabled: bool) -> Result<()> {
|
||||
self.user_data.monitoring = Some(enabled);
|
||||
self.user_data.write().map_err(|e| {
|
||||
error!("Failed to write user data to disk {e}");
|
||||
BackendError::UserDataWriteError
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_privacy_level(&mut self, privacy_level: PrivacyLevel) -> Result<()> {
|
||||
self.user_data.privacy_level = Some(privacy_level);
|
||||
self.user_data.write().map_err(|e| {
|
||||
error!("Failed to write user data to disk {e}");
|
||||
BackendError::UserDataWriteError
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_gateway_connectivity(&mut self, gateway_connectivity: GatewayConnectivity) {
|
||||
self.gateway_connectivity = gateway_connectivity
|
||||
}
|
||||
@@ -200,8 +227,9 @@ impl State {
|
||||
&mut self,
|
||||
) -> Result<(nym_task::StatusReceiver, ExitStatusReceiver)> {
|
||||
let id = self.get_config_id()?;
|
||||
let privacy_level = self.user_data.privacy_level.unwrap_or_default();
|
||||
let (control_tx, msg_rx, exit_status_rx, used_gateway) =
|
||||
tasks::start_nym_socks5_client(&id).await?;
|
||||
tasks::start_nym_socks5_client(&id, &privacy_level).await?;
|
||||
self.socks5_client_sender = Some(control_tx);
|
||||
self.gateway = Some(used_gateway.gateway_id);
|
||||
Ok((msg_rx, exit_status_rx))
|
||||
@@ -244,7 +272,3 @@ impl State {
|
||||
self.set_state(ConnectionStatusKind::Disconnected, window);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_medium_enabled() -> bool {
|
||||
cfg!(medium_enabled) || std::env::var("NYM_CONNECT_ENABLE_MEDIUM").is_ok()
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::sync::Arc;
|
||||
use tap::TapFallible;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::config::{Config, PrivacyLevel};
|
||||
use crate::{
|
||||
error::Result,
|
||||
events::{self, emit_event, emit_status_event},
|
||||
@@ -30,23 +30,20 @@ pub enum Socks5ExitStatusMessage {
|
||||
Failed(Box<dyn std::error::Error + Send>),
|
||||
}
|
||||
|
||||
fn override_config_from_env(config: &mut Config) {
|
||||
fn override_config_from_env(config: &mut Config, privacy_level: &PrivacyLevel) {
|
||||
// Disable both the loop cover traffic that runs in the background as well as the Poisson
|
||||
// process that injects cover traffic into the traffic stream.
|
||||
if std::env::var("NYM_CONNECT_DISABLE_COVER").is_ok() {
|
||||
if let PrivacyLevel::Medium = privacy_level {
|
||||
log::info!("Running in Medium privacy level");
|
||||
log::warn!("Disabling cover traffic");
|
||||
config.core.base.set_no_cover_traffic_with_keepalive();
|
||||
}
|
||||
|
||||
if std::env::var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS").is_ok() {
|
||||
log::warn!("Enabling mixed size packets");
|
||||
config
|
||||
.core
|
||||
.base
|
||||
.set_secondary_packet_size(Some(PacketSize::ExtendedPacket16));
|
||||
}
|
||||
|
||||
if std::env::var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS").is_ok() {
|
||||
log::warn!("Disabling per-hop delay");
|
||||
config.core.base.set_no_per_hop_delays();
|
||||
}
|
||||
@@ -55,6 +52,7 @@ fn override_config_from_env(config: &mut Config) {
|
||||
/// The main SOCKS5 client task. It loads the configuration from file determined by the `id`.
|
||||
pub async fn start_nym_socks5_client(
|
||||
id: &str,
|
||||
privacy_level: &PrivacyLevel,
|
||||
) -> Result<(
|
||||
Socks5ControlMessageSender,
|
||||
nym_task::StatusReceiver,
|
||||
@@ -65,7 +63,7 @@ pub async fn start_nym_socks5_client(
|
||||
let mut config = Config::read_from_default_path(id)
|
||||
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
|
||||
|
||||
override_config_from_env(&mut config);
|
||||
override_config_from_env(&mut config, privacy_level);
|
||||
|
||||
log::trace!("Configuration used: {:#?}", config);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "nym-connect",
|
||||
"version": "1.1.14"
|
||||
"version": "1.1.15"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
@@ -86,4 +86,4 @@
|
||||
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ const ConnectionStatusContent: FCWithChildren<{
|
||||
serviceProvider?: ServiceProvider;
|
||||
gatewayError: boolean;
|
||||
}> = ({ status, serviceProvider, gatewayError }) => {
|
||||
const { speedMode } = useClientContext();
|
||||
const { userData } = useClientContext();
|
||||
|
||||
if (gatewayError) {
|
||||
return (
|
||||
@@ -49,10 +49,10 @@ const ConnectionStatusContent: FCWithChildren<{
|
||||
</Typography>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
{speedMode === 'medium' && (
|
||||
{userData?.privacy_level === 'Medium' && (
|
||||
<Stack alignItems="center" color="warning.main">
|
||||
<Typography variant="caption" color="grey.400">
|
||||
Speedy mode activated
|
||||
Speed boost activated
|
||||
</Typography>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
@@ -3,23 +3,24 @@ import { DateTime } from 'luxon';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { Error } from 'src/types/error';
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { useEvents } from 'src/hooks/events';
|
||||
import { UserDefinedGateway, UserDefinedSPAddress } from 'src/types/service-provider';
|
||||
import { getItemFromStorage, setItemInStorage } from 'src/utils';
|
||||
import { ConnectionStatusKind, GatewayPerformance, SpeedMode } from '../types';
|
||||
import { ConnectionStatusKind, GatewayPerformance, PrivacyLevel, UserData } from '../types';
|
||||
import { ConnectionStatsItem } from '../components/ConnectionStats';
|
||||
import { ServiceProvider } from '../types/directory';
|
||||
import initSentry from '../sentry';
|
||||
|
||||
const FORAGE_GATEWAY_KEY = 'nym-connect-user-gateway';
|
||||
const FORAGE_SP_KEY = 'nym-connect-user-sp';
|
||||
const FORAGE_MONITORING_ENABLED = 'nym-connect-monitoring-enabled';
|
||||
|
||||
type ModeType = 'light' | 'dark';
|
||||
|
||||
export type TClientContext = {
|
||||
mode: ModeType;
|
||||
appVersion?: string;
|
||||
userData?: UserData;
|
||||
connectionStatus: ConnectionStatusKind;
|
||||
connectionStats?: ConnectionStatsItem[];
|
||||
connectedSince?: DateTime;
|
||||
@@ -32,7 +33,6 @@ export type TClientContext = {
|
||||
serviceProviders?: ServiceProvider[];
|
||||
setMode: (mode: ModeType) => void;
|
||||
clearError: () => void;
|
||||
monitoringEnabled: boolean;
|
||||
setConnectionStatus: (connectionStatus: ConnectionStatusKind) => void;
|
||||
setConnectionStats: (connectionStats: ConnectionStatsItem[] | undefined) => void;
|
||||
setConnectedSince: (connectedSince: DateTime | undefined) => void;
|
||||
@@ -43,7 +43,7 @@ export type TClientContext = {
|
||||
setUserDefinedGateway: React.Dispatch<React.SetStateAction<UserDefinedGateway>>;
|
||||
setUserDefinedSPAddress: React.Dispatch<React.SetStateAction<UserDefinedSPAddress>>;
|
||||
setMonitoring: (value: boolean) => Promise<void>;
|
||||
speedMode: SpeedMode;
|
||||
setPrivacyLevel: (value: PrivacyLevel) => Promise<void>;
|
||||
};
|
||||
|
||||
export const ClientContext = createContext({} as TClientContext);
|
||||
@@ -67,19 +67,26 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
isActive: false,
|
||||
address: undefined,
|
||||
});
|
||||
const [monitoringEnabled, setMonitoringEnabled] = useState(false);
|
||||
const [speedMode, setspeedMode] = useState<SpeedMode>('slow');
|
||||
const [userData, setUserData] = useState<UserData>();
|
||||
|
||||
const getAppVersion = async () => {
|
||||
const version = await getVersion();
|
||||
return version;
|
||||
};
|
||||
|
||||
const getUserData = async () => {
|
||||
const data = await invoke<UserData>('get_user_data');
|
||||
if (!data.privacy_level) {
|
||||
data.privacy_level = 'High';
|
||||
}
|
||||
setUserData(data);
|
||||
return data;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const initSentryClient = async () => {
|
||||
const monitoring = await getItemFromStorage({ key: FORAGE_MONITORING_ENABLED });
|
||||
setMonitoringEnabled(Boolean(monitoring));
|
||||
if (monitoring === true) {
|
||||
const data = await getUserData();
|
||||
if (data.monitoring) {
|
||||
await initSentry();
|
||||
}
|
||||
};
|
||||
@@ -87,17 +94,6 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
initSentryClient();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const initSpeedMode = async () => {
|
||||
const isEnabled = await invoke<boolean>('is_medium_mode_enabled');
|
||||
if (isEnabled) {
|
||||
setspeedMode('medium');
|
||||
}
|
||||
};
|
||||
|
||||
initSpeedMode();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setItemInStorage({ key: FORAGE_GATEWAY_KEY, value: userDefinedGateway });
|
||||
}, [userDefinedGateway]);
|
||||
@@ -124,7 +120,10 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
};
|
||||
|
||||
useEvents({
|
||||
onError: (e) => setError(e),
|
||||
onError: (e) => {
|
||||
setError(e);
|
||||
Sentry.captureException(e);
|
||||
},
|
||||
onGatewayPerformanceChange: (performance) => setGatewayPerformance(performance),
|
||||
onStatusChange: (status) => setConnectionStatus(status),
|
||||
});
|
||||
@@ -147,6 +146,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
} catch (e) {
|
||||
setError({ title: 'Could not connect', message: e as string });
|
||||
console.log(e);
|
||||
Sentry.captureException(e);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -155,6 +155,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
await invoke('start_disconnecting');
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
Sentry.captureException(e);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -197,8 +198,15 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
const clearError = () => setError(undefined);
|
||||
|
||||
const setMonitoring = async (value: boolean) => {
|
||||
setMonitoringEnabled(value);
|
||||
await setItemInStorage({ key: FORAGE_MONITORING_ENABLED, value });
|
||||
await invoke('set_monitoring', { enabled: value });
|
||||
// refresh user data
|
||||
await getUserData();
|
||||
};
|
||||
|
||||
const setPrivacyLevel = async (value: PrivacyLevel) => {
|
||||
await invoke('set_privacy_level', { privacyLevel: value });
|
||||
// refresh user data
|
||||
await getUserData();
|
||||
};
|
||||
|
||||
const contextValue = useMemo(
|
||||
@@ -216,7 +224,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
selectedProvider,
|
||||
serviceProviders,
|
||||
connectedSince,
|
||||
monitoringEnabled,
|
||||
userData,
|
||||
setConnectedSince,
|
||||
setSerivceProvider,
|
||||
startConnecting,
|
||||
@@ -228,7 +236,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
setUserDefinedGateway,
|
||||
setUserDefinedSPAddress,
|
||||
setMonitoring,
|
||||
speedMode,
|
||||
setPrivacyLevel,
|
||||
}),
|
||||
[
|
||||
mode,
|
||||
@@ -244,8 +252,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
selectedProvider,
|
||||
userDefinedGateway,
|
||||
userDefinedSPAddress,
|
||||
monitoringEnabled,
|
||||
speedMode,
|
||||
userData,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ const mockValues: TClientContext = {
|
||||
showInfoModal: false,
|
||||
userDefinedGateway: { isActive: false, gateway: '' },
|
||||
userDefinedSPAddress: { isActive: false, address: '' },
|
||||
monitoringEnabled: false,
|
||||
speedMode: 'slow',
|
||||
userData: { monitoring: false, privacy_level: 'High' },
|
||||
setShowInfoModal: () => {},
|
||||
setMode: () => {},
|
||||
clearError: () => {},
|
||||
@@ -25,6 +24,7 @@ const mockValues: TClientContext = {
|
||||
setUserDefinedGateway: () => {},
|
||||
setUserDefinedSPAddress: () => {},
|
||||
setMonitoring: async () => {},
|
||||
setPrivacyLevel: async () => {},
|
||||
};
|
||||
|
||||
export const MockProvider: FCWithChildren<{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { listen, UnlistenFn } from '@tauri-apps/api/event';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { ConnectionStatusKind, GatewayPerformance } from 'src/types';
|
||||
import { Error } from 'src/types/error';
|
||||
import { TauriEvent } from 'src/types/event';
|
||||
@@ -29,7 +30,10 @@ export const useEvents = ({
|
||||
.then((result) => {
|
||||
unlisten.push(result);
|
||||
})
|
||||
.catch((e) => console.log(e));
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
Sentry.captureException(e);
|
||||
});
|
||||
|
||||
listen('socks5-event', (e: TauriEvent) => {
|
||||
console.log(e);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { forage } from '@tauri-apps/tauri-forage';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useClientContext } from 'src/context/main';
|
||||
import { useTauriEvents } from 'src/utils';
|
||||
@@ -28,12 +29,14 @@ export const ConnectionPage = () => {
|
||||
// eslint-disable-next-line default-case
|
||||
switch (currentStatus) {
|
||||
case 'disconnected':
|
||||
Sentry.captureMessage('start connect', 'info');
|
||||
await context.setSerivceProvider();
|
||||
await context.startConnecting();
|
||||
context.setConnectedSince(DateTime.now());
|
||||
context.setShowInfoModal(true);
|
||||
break;
|
||||
case 'connected':
|
||||
Sentry.captureMessage('start disconnect', 'info');
|
||||
await context.startDisconnecting();
|
||||
context.setConnectedSince(undefined);
|
||||
break;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Box } from '@mui/system';
|
||||
|
||||
const appsSchema = {
|
||||
messagingApps: ['Matrix', 'Telegram', 'Keybase'],
|
||||
wallets: ['Monero', 'Blockstream', 'Electrum'],
|
||||
wallets: ['Monero', 'Blockstream', 'Electrum', 'Alephium'],
|
||||
};
|
||||
|
||||
export const CompatibleApps = () => (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Apps, HelpOutline, Settings, BugReport } from '@mui/icons-material';
|
||||
import { Apps, HelpOutline, Settings, BugReport, PrivacyTip } from '@mui/icons-material';
|
||||
import { Stack, Link, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { AppVersion } from 'src/components/AppVersion';
|
||||
@@ -7,6 +7,7 @@ import { AppVersion } from 'src/components/AppVersion';
|
||||
const menuSchema = [
|
||||
{ title: 'Supported apps', icon: Apps, path: 'apps' },
|
||||
{ title: 'How to connect guide', icon: HelpOutline, path: 'guide' },
|
||||
{ title: 'Privacy level', icon: PrivacyTip, path: 'privacy-level' },
|
||||
{ title: 'Please help us improve the app', icon: BugReport, path: 'monitoring' },
|
||||
{ title: 'Settings', icon: Settings, path: 'settings' },
|
||||
];
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Box, FormControl, FormControlLabel, FormHelperText, Stack, Switch, Typo
|
||||
import { useClientContext } from 'src/context/main';
|
||||
|
||||
export const MonitoringSettings = () => {
|
||||
const { monitoringEnabled, setMonitoring } = useClientContext();
|
||||
const [enabled, setEnabled] = useState(monitoringEnabled);
|
||||
const { userData, setMonitoring } = useClientContext();
|
||||
const [enabled, setEnabled] = useState(userData?.monitoring || false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -25,7 +25,13 @@ export const MonitoringSettings = () => {
|
||||
<FormControl fullWidth>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch checked={enabled} onChange={handleChange} disabled={loading} size="small" sx={{ ml: 1 }} />
|
||||
<Switch
|
||||
checked={enabled}
|
||||
onChange={handleChange}
|
||||
disabled={loading}
|
||||
size="small"
|
||||
sx={{ ml: 1, mr: 1 }}
|
||||
/>
|
||||
}
|
||||
label="Enable"
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import React, { ChangeEvent, useState } from 'react';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { Box, FormControl, FormControlLabel, FormHelperText, Stack, Switch, Typography } from '@mui/material';
|
||||
import { useClientContext } from 'src/context/main';
|
||||
|
||||
export const PrivacyLevelSettings = () => {
|
||||
const { userData, setPrivacyLevel } = useClientContext();
|
||||
const [speedBoost, setSpeedBoost] = useState(userData?.privacy_level !== 'High');
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setLoading(true);
|
||||
setSpeedBoost(e.target.checked);
|
||||
Sentry.captureMessage(`privacy level switched to ${e.target.checked ? 'Medium' : 'High'}`, 'info');
|
||||
await setPrivacyLevel(e.target.checked ? 'Medium' : 'High');
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box height="100%">
|
||||
<Stack justifyContent="space-between" height="100%">
|
||||
<Box>
|
||||
<Typography fontWeight="bold" variant="body2" mb={2}>
|
||||
Speed boost
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={speedBoost}
|
||||
onChange={handleChange}
|
||||
disabled={loading}
|
||||
size="small"
|
||||
sx={{ ml: 1, mr: 1 }}
|
||||
/>
|
||||
}
|
||||
label="Enable"
|
||||
/>
|
||||
<FormHelperText sx={{ m: 0, my: 2 }}>
|
||||
By activating this option, the connection speed will be relatively faster in exchange of relaxing some
|
||||
protections
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -9,14 +9,15 @@ import { SettingsMenu } from 'src/pages/menu/settings';
|
||||
import { GatewaySettings } from 'src/pages/menu/settings/GatewaySettings';
|
||||
import { ServiceProviderSettings } from 'src/pages/menu/settings/ServiceProviderSettings';
|
||||
import { MonitoringSettings } from '../pages/menu/settings/MonitoringSettings';
|
||||
import { PrivacyLevelSettings } from '../pages/menu/settings/PrivacyLevelSettings';
|
||||
import { useClientContext } from '../context/main';
|
||||
|
||||
const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);
|
||||
|
||||
export const AppRoutes = () => {
|
||||
const { monitoringEnabled } = useClientContext();
|
||||
const { userData } = useClientContext();
|
||||
|
||||
const RoutesContainer = monitoringEnabled ? SentryRoutes : Routes;
|
||||
const RoutesContainer = userData?.monitoring ? SentryRoutes : Routes;
|
||||
|
||||
return (
|
||||
<RoutesContainer>
|
||||
@@ -25,6 +26,7 @@ export const AppRoutes = () => {
|
||||
<Route index element={<Menu />} />
|
||||
<Route path="apps" element={<CompatibleApps />} />
|
||||
<Route path="guide" element={<HelpGuide />} />
|
||||
<Route path="privacy-level" element={<PrivacyLevelSettings />} />
|
||||
<Route path="monitoring" element={<MonitoringSettings />} />
|
||||
<Route path="settings">
|
||||
<Route index element={<SettingsMenu />} />
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
import React from 'react';
|
||||
import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from 'react-router-dom';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { CaptureConsole } from '@sentry/integrations';
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
|
||||
const SENTRY_DSN = 'https://625e2658da4945a7a253f3ee04413a31@o967446.ingest.sentry.io/4505306292289536';
|
||||
const SENTRY_DSN = 'SENTRY_DSN_JS';
|
||||
|
||||
async function initSentry() {
|
||||
console.log('⚠ performance monitoring and error reporting enabled');
|
||||
console.log('initializing sentry');
|
||||
|
||||
const dsn = await invoke<string | undefined>('get_env', { variable: SENTRY_DSN });
|
||||
|
||||
if (!dsn) {
|
||||
console.warn(`unable to initialize sentry, ${SENTRY_DSN} env var not set`);
|
||||
return;
|
||||
}
|
||||
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN,
|
||||
dsn,
|
||||
integrations: [
|
||||
new Sentry.BrowserTracing({
|
||||
// Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export type SpeedMode = 'fast' | 'medium' | 'slow';
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './rust';
|
||||
export * from './connection';
|
||||
export * from './common';
|
||||
export * from './user-data';
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export type PrivacyLevel = 'High' | 'Medium';
|
||||
|
||||
export type UserData = {
|
||||
monitoring?: boolean;
|
||||
privacy_level?: PrivacyLevel;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
use nym_sdk::mixnet::{
|
||||
AnonymousSenderTag, MixnetClientBuilder, ReconstructedMessage, StoragePaths,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
nym_bin_common::logging::setup_logging();
|
||||
|
||||
// Specify some config options
|
||||
let config_dir = PathBuf::from("/tmp/surb-example");
|
||||
let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap();
|
||||
|
||||
// Create the client with a storage backend, and enable it by giving it some paths. If keys
|
||||
// exists at these paths, they will be loaded, otherwise they will be generated.
|
||||
let client = MixnetClientBuilder::new_with_default_storage(storage_paths)
|
||||
.await
|
||||
.unwrap()
|
||||
.build()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Now we connect to the mixnet, using keys now stored in the paths provided.
|
||||
let mut client = client.connect_to_mixnet().await.unwrap();
|
||||
|
||||
// Be able to get our client address
|
||||
let our_address = client.nym_address();
|
||||
println!("\nOur client nym address is: {our_address}");
|
||||
|
||||
// Send a message through the mixnet to ourselves using our nym address
|
||||
client.send_str(*our_address, "hello there").await;
|
||||
|
||||
// we're going to parse the sender_tag (AnonymousSenderTag) from the incoming message and use it to 'reply' to ourselves instead of our Nym address.
|
||||
// we know there will be a sender_tag since the sdk sends SURBs along with messages by default.
|
||||
println!("Waiting for message\n");
|
||||
|
||||
// get the actual message - discard the empty vec sent along with a potential SURB topup request
|
||||
let mut message: Vec<ReconstructedMessage> = Vec::new();
|
||||
while let Some(new_message) = client.wait_for_messages().await {
|
||||
if new_message.is_empty() {
|
||||
continue;
|
||||
}
|
||||
message = new_message;
|
||||
break;
|
||||
}
|
||||
|
||||
let mut parsed = String::new();
|
||||
if let Some(r) = message.first() {
|
||||
parsed = String::from_utf8(r.message.clone()).unwrap();
|
||||
}
|
||||
// parse sender_tag: we will use this to reply to sender without needing their Nym address
|
||||
let return_recipient: AnonymousSenderTag = message[0].sender_tag.unwrap();
|
||||
println!(
|
||||
"\nReceived the following message: {} \nfrom sender with surb bucket {}",
|
||||
parsed, return_recipient
|
||||
);
|
||||
|
||||
// reply to self with it: note we use `send_str_reply` instead of `send_str`
|
||||
println!("Replying with using SURBs");
|
||||
client.send_str_reply(return_recipient, "hi an0n!").await;
|
||||
|
||||
println!("Waiting for message (once you see it, ctrl-c to exit)\n");
|
||||
client
|
||||
.on_messages(|msg| println!("\nReceived: {}", String::from_utf8_lossy(&msg.message)))
|
||||
.await;
|
||||
}
|
||||
Reference in New Issue
Block a user