Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd516d4633 | |||
| a12ade1ecf | |||
| 458a2c5e42 | |||
| ecaa970380 | |||
| 42e3064cbb | |||
| 0d5f594a69 | |||
| 826db30d2b | |||
| 2c731cf048 | |||
| 9a1f28bd43 | |||
| b9493004aa | |||
| b27f806c40 | |||
| 08aaa8813e | |||
| dd9f4f24f1 | |||
| f6c2cab531 | |||
| f4dd9a915d |
@@ -1,16 +1,10 @@
|
||||
name: build-upload-binaries
|
||||
name: ci-build-upload-binaries
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
add_tokio_unstable:
|
||||
description: 'True to add RUSTFLAGS="--cfg tokio_unstable"'
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
NETWORK: mainnet
|
||||
pull_request:
|
||||
paths:
|
||||
- 'mixnode/**'
|
||||
|
||||
jobs:
|
||||
publish-nym:
|
||||
@@ -22,40 +16,49 @@ jobs:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: "--cfg tokio_unstable"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools
|
||||
continue-on-error: true
|
||||
|
||||
- name: Sets env vars for tokio if set in manual dispatch inputs
|
||||
- name: Prepare build output directory
|
||||
shell: bash
|
||||
env:
|
||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
||||
run: |
|
||||
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
|
||||
rm -rf ci-builds || true
|
||||
mkdir -p $OUTPUT_DIR
|
||||
echo $OUTPUT_DIR
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt update && sudo apt install libudev-dev
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Build all binaries
|
||||
- name: Build mixnode binary
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --release
|
||||
args: --release --features cpucycles --package nym-mixnode
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-binaries-artifacts
|
||||
path: |
|
||||
target/release/nym-client
|
||||
target/release/nym-gateway
|
||||
target/release/nym-mixnode
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
retention-days: 30
|
||||
- name: Prepare build output
|
||||
shell: bash
|
||||
env:
|
||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
||||
run: |
|
||||
cp target/release/nym-mixnode $OUTPUT_DIR
|
||||
|
||||
- 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: "-avzr"
|
||||
SOURCE: "ci-builds/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
@@ -5,6 +5,7 @@ authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej St
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-client-websocket-requests"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ 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"
|
||||
rust-version = "1.56"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "async-file-watcher"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-bandwidth-controller"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ version = "1.1.15"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-gateway-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-mixnet-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-coconut-interface"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Crutch library until there is proper SerDe support for coconut structs"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bs58 = "0.4.0"
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-cli-commands"
|
||||
version = "1.0.0"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-config"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -17,4 +18,4 @@ url = { workspace = true }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
[features]
|
||||
default = ["dirs"]
|
||||
default = ["dirs"]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-coconut-bandwidth-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -12,4 +13,4 @@ cw2 = { workspace = true, optional = true }
|
||||
nym-multisig-contract-common = { path = "../multisig-contract" }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
schema = ["cw2"]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-coconut-dkg-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -14,4 +15,4 @@ contracts-common = { path = "../contracts-common", package = "nym-contracts-comm
|
||||
nym-multisig-contract-common = { path = "../multisig-contract" }
|
||||
|
||||
[features]
|
||||
schema = []
|
||||
schema = []
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-ephemera-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -13,4 +14,4 @@ cw-utils = { workspace = true }
|
||||
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
|
||||
|
||||
[features]
|
||||
schema = []
|
||||
schema = []
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-group-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-multisig-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-name-service-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -16,4 +17,4 @@ serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
schema = ["cw2"]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-service-provider-directory-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -15,4 +16,4 @@ nym-contracts-common = { path = "../contracts-common", version = "0.5.0" }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
schema = ["cw2"]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-credential-storage"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-credential-utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-credentials"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-dkg"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
resolver = "2"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-execute"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "ledger"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -10,4 +11,4 @@ bip32 = "0.5.1"
|
||||
k256 = { workspace = true }
|
||||
ledger-transport = "0.10.0"
|
||||
ledger-transport-hid = "0.10.0"
|
||||
thiserror = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-mixnode-common"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-node-tester-utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-nonexhaustive-delayqueue"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-coconut"
|
||||
version = "0.5.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>", "Ania Piotrowska <ania@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-socks5-client-core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-ordered-buffer"
|
||||
version = "0.1.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-socks5-proxy-helpers"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-socks5-requests"
|
||||
version = "0.1.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
name = "nym-statistics-common"
|
||||
version = "1.0.1"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-store-cipher"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -20,4 +21,4 @@ getrandom = { version = "0.2", features = ["js"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
json = ["serde_json"]
|
||||
json = ["serde_json"]
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Nym common types"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
rust-version = "1.58"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.21.4"
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "wasm-storage"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -17,4 +18,4 @@ indexed_db_futures = { version = " 0.3.0"}
|
||||
thiserror = { workspace = true }
|
||||
|
||||
nym-store-cipher = { path = "../../store-cipher", features = ["json"] }
|
||||
wasm-utils = { path = "../utils", default-features = false }
|
||||
wasm-utils = { path = "../utils", default-features = false }
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "wasm-utils"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -104,8 +104,16 @@ unlicensed = "deny"
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||
allow = [
|
||||
#"MIT",
|
||||
#"Apache-2.0",
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
"BSD-2-Clause",
|
||||
"BSD-3-Clause",
|
||||
"ISC",
|
||||
"0BSD",
|
||||
"MPL-2.0",
|
||||
"CC0-1.0",
|
||||
"Unicode-DFS-2016",
|
||||
"OpenSSL",
|
||||
]
|
||||
# List of explicitly disallowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
@@ -143,22 +151,22 @@ exceptions = [
|
||||
# Some crates don't have (easily) machine readable licensing information,
|
||||
# adding a clarification entry for it allows you to manually specify the
|
||||
# licensing information
|
||||
#[[licenses.clarify]]
|
||||
[[licenses.clarify]]
|
||||
# The name of the crate the clarification applies to
|
||||
#name = "ring"
|
||||
name = "ring"
|
||||
# The optional version constraint for the crate
|
||||
#version = "*"
|
||||
version = "*"
|
||||
# The SPDX expression for the license requirements of the crate
|
||||
#expression = "MIT AND ISC AND OpenSSL"
|
||||
expression = "MIT AND ISC AND OpenSSL"
|
||||
# One or more files in the crate's source used as the "source of truth" for
|
||||
# the license expression. If the contents match, the clarification will be used
|
||||
# when running the license check, otherwise the clarification will be ignored
|
||||
# and the crate will be checked normally, which may produce warnings or errors
|
||||
# depending on the rest of your configuration
|
||||
#license-files = [
|
||||
license-files = [
|
||||
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
||||
#{ path = "LICENSE", hash = 0xbd0eed23 }
|
||||
#]
|
||||
{ path = "LICENSE", hash = 0xbd0eed23 }
|
||||
]
|
||||
|
||||
[licenses.private]
|
||||
# If true, ignores workspace crates that aren't published, or are only
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "explorer-api"
|
||||
version = "1.1.32"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-explorer-api-requests"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common" }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-explorer-client"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-gateway"
|
||||
license = "GPL-3"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.32"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
|
||||
@@ -6,6 +6,7 @@ name = "nym-gateway-requests"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-mixnode"
|
||||
license = "GPL-3"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.34"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
@@ -35,6 +35,7 @@ serde_json = { workspace = true }
|
||||
sysinfo = "0.27.7"
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
console-subscriber = { version = "0.2", optional = true }
|
||||
toml = "0.5.8"
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
cfg-if = "1.0.0"
|
||||
@@ -83,6 +84,9 @@ cpucycles = [
|
||||
"nym-bin-common/tracing",
|
||||
]
|
||||
|
||||
# build with RUSTFLAGS="--cfg tokio_unstable"
|
||||
tokio-console = ["console-subscriber", "tokio/tracing"]
|
||||
|
||||
[package.metadata.deb]
|
||||
name = "nym-mixnode"
|
||||
maintainer-scripts = "debian"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use ::nym_config::defaults::setup_env;
|
||||
use clap::{crate_name, crate_version, Parser};
|
||||
use lazy_static::lazy_static;
|
||||
use log::info;
|
||||
use log::{error, info};
|
||||
use nym_bin_common::bin_info;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
@@ -53,6 +53,12 @@ fn test_function() {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "tokio-console")] {
|
||||
console_subscriber::init();
|
||||
}
|
||||
}
|
||||
|
||||
let args = Cli::parse();
|
||||
setup_env(args.config_env_file.as_ref());
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.34"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-api-requests"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license = "GPL-3"
|
||||
license = "GPL-3.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -39,10 +39,17 @@ For example on Linux the path would be `~/.config/nym-vpn/config.toml`
|
||||
|
||||
# path to the env config file if you provide one
|
||||
env_config_file = "$HOME/.config/nym-vpn/qa.env"
|
||||
```
|
||||
|
||||
# pick a gateway and exit router accordingly to the selected env
|
||||
entry_gateway = "xxx"
|
||||
exit_router = "xxx"
|
||||
## Optional config
|
||||
|
||||
In the config file `nym-vpn/config.toml`
|
||||
|
||||
```toml
|
||||
env_config_file = "$HOME/.config/nym-vpn/qa.env"
|
||||
|
||||
# set the entry node location to use, as two letter country code
|
||||
entry_node_location = "FR"
|
||||
```
|
||||
|
||||
## Dev
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="text-[12px]">
|
||||
<html lang="en" class="text-[14px]">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
|
||||
@@ -5267,6 +5267,7 @@ dependencies = [
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signature 1.4.0",
|
||||
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 974 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 25 KiB |
@@ -1,6 +1,7 @@
|
||||
use tauri::State;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::country::COUNTRIES;
|
||||
use crate::states::app::Country;
|
||||
use crate::{
|
||||
error::{CmdError, CmdErrorSource},
|
||||
@@ -12,29 +13,8 @@ use crate::{
|
||||
#[tauri::command]
|
||||
pub fn get_node_countries() -> Result<Vec<Country>, CmdError> {
|
||||
debug!("get_node_countries");
|
||||
let countries: Vec<Country> = vec![
|
||||
Country {
|
||||
name: "United States".to_string(),
|
||||
code: "US".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "France".to_string(),
|
||||
code: "FR".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "Switzerland".to_string(),
|
||||
code: "CH".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "Sweden".to_string(),
|
||||
code: "SE".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "Germany".to_string(),
|
||||
code: "DE".to_string(),
|
||||
},
|
||||
];
|
||||
Ok(countries)
|
||||
// TODO fetch the list of countries from some API
|
||||
Ok(COUNTRIES.clone())
|
||||
}
|
||||
|
||||
#[instrument(skip(state))]
|
||||
@@ -97,3 +77,25 @@ pub async fn set_ui_theme(
|
||||
.map_err(|e| CmdError::new(CmdErrorSource::InternalError, e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(data_state))]
|
||||
#[tauri::command]
|
||||
pub async fn set_entry_location_selector(
|
||||
data_state: State<'_, SharedAppData>,
|
||||
entry_selector: bool,
|
||||
) -> Result<(), CmdError> {
|
||||
debug!("set_entry_location_selector");
|
||||
|
||||
let mut app_data_store = data_state.lock().await;
|
||||
let mut app_data = app_data_store
|
||||
.read()
|
||||
.await
|
||||
.map_err(|e| CmdError::new(CmdErrorSource::InternalError, e.to_string()))?;
|
||||
app_data.entry_location_selector = Some(entry_selector);
|
||||
app_data_store.data = app_data;
|
||||
app_data_store
|
||||
.write()
|
||||
.await
|
||||
.map_err(|e| CmdError::new(CmdErrorSource::InternalError, e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use futures::SinkExt;
|
||||
use nym_vpn_lib::gateway_client::{EntryPoint, ExitPoint};
|
||||
use nym_vpn_lib::{NymVpnCtrlMessage, NymVpnHandle};
|
||||
use tauri::{Manager, State};
|
||||
use tracing::{debug, error, info, instrument, trace};
|
||||
@@ -16,6 +17,8 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
const DEFAULT_NODE_LOCATION: &str = "DE";
|
||||
|
||||
#[instrument(skip_all)]
|
||||
#[tauri::command]
|
||||
pub async fn get_connection_state(
|
||||
@@ -67,23 +70,48 @@ pub async fn connect(
|
||||
)
|
||||
.ok();
|
||||
|
||||
let app_config = config_store.lock().await.read().await.map_err(|e| {
|
||||
CmdError::new(
|
||||
CmdErrorSource::InternalError,
|
||||
format!("failed to read app config: {}", e),
|
||||
)
|
||||
})?;
|
||||
let mut vpn_config = create_vpn_config(&app_config);
|
||||
{
|
||||
let app_state = state.lock().await;
|
||||
if let VpnMode::TwoHop = app_state.vpn_mode {
|
||||
info!("2-hop mode enabled");
|
||||
vpn_config.enable_two_hop = true;
|
||||
} else {
|
||||
info!("5-hop mode enabled");
|
||||
let app_state = state.lock().await;
|
||||
|
||||
// get entry node location from app config file
|
||||
let app_config = config_store
|
||||
.lock()
|
||||
.await
|
||||
.read()
|
||||
.await
|
||||
.map_err(|e| CmdError::new(CmdErrorSource::InternalError, e.to_string()))?;
|
||||
let entry_location = app_config
|
||||
.entry_node_location
|
||||
.clone()
|
||||
.unwrap_or_else(|| DEFAULT_NODE_LOCATION.to_string());
|
||||
// !! release config_store mutex
|
||||
drop(app_config);
|
||||
|
||||
debug!("using entry node location: {}", entry_location);
|
||||
let entry_point = EntryPoint::Location(entry_location);
|
||||
let exit_point = match app_state.exit_node_location {
|
||||
Some(ref exit_node_location) => {
|
||||
debug!("exit node location set, using: {}", exit_node_location.code);
|
||||
ExitPoint::Location(exit_node_location.code.clone())
|
||||
}
|
||||
_ => {
|
||||
debug!(
|
||||
"exit node location not set, using default: {}",
|
||||
DEFAULT_NODE_LOCATION
|
||||
);
|
||||
ExitPoint::Location(DEFAULT_NODE_LOCATION.into())
|
||||
}
|
||||
};
|
||||
|
||||
let mut vpn_config = create_vpn_config(entry_point, exit_point);
|
||||
if let VpnMode::TwoHop = app_state.vpn_mode {
|
||||
info!("2-hop mode enabled");
|
||||
vpn_config.enable_two_hop = true;
|
||||
} else {
|
||||
info!("5-hop mode enabled");
|
||||
}
|
||||
// vpn_config.disable_routing = true;
|
||||
// !! release app_state mutex
|
||||
drop(app_state);
|
||||
|
||||
// spawn the VPN client and start a new connection
|
||||
let NymVpnHandle {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::State;
|
||||
use tracing::{debug, instrument};
|
||||
@@ -14,6 +15,11 @@ pub enum NodeType {
|
||||
Exit,
|
||||
}
|
||||
|
||||
static DEFAULT_NODE_LOCATION: Lazy<Country> = Lazy::new(|| Country {
|
||||
code: "DE".to_string(),
|
||||
name: "Germany".to_string(),
|
||||
});
|
||||
|
||||
#[instrument(skip(app_state, data_state))]
|
||||
#[tauri::command]
|
||||
pub async fn set_node_location(
|
||||
@@ -57,3 +63,10 @@ pub async fn set_node_location(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
#[tauri::command]
|
||||
pub async fn get_default_node_location() -> Result<Country, CmdError> {
|
||||
debug!("get_default_node_location");
|
||||
Ok(DEFAULT_NODE_LOCATION.clone())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::states::app::Country;
|
||||
|
||||
// TODO use hardcoded country list for now
|
||||
pub static COUNTRIES: Lazy<Vec<Country>> = Lazy::new(|| {
|
||||
vec![
|
||||
Country {
|
||||
name: "Ireland".to_string(),
|
||||
code: "IE".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "Germany".to_string(),
|
||||
code: "DE".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "Japan".to_string(),
|
||||
code: "JP".to_string(),
|
||||
},
|
||||
Country {
|
||||
name: "Great Britain".to_string(),
|
||||
code: "GB".to_string(),
|
||||
},
|
||||
]
|
||||
});
|
||||
@@ -6,8 +6,6 @@ use serde::{Deserialize, Serialize};
|
||||
pub struct AppConfig {
|
||||
/// Path pointing to an env configuration file describing the network
|
||||
pub env_config_file: Option<PathBuf>,
|
||||
/// Mixnet public ID of the entry gateway
|
||||
pub entry_gateway: String,
|
||||
/// Mixnet recipient address
|
||||
pub exit_router: String,
|
||||
/// Country code (two letters format, eg. FR)
|
||||
pub entry_node_location: Option<String>,
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ pub struct AppData {
|
||||
pub monitoring: Option<bool>,
|
||||
pub autoconnect: Option<bool>,
|
||||
pub killswitch: Option<bool>,
|
||||
pub entry_location_selector: Option<bool>,
|
||||
pub ui_theme: Option<UiTheme>,
|
||||
pub vpn_mode: Option<VpnMode>,
|
||||
pub entry_node: Option<NodeConfig>,
|
||||
|
||||
@@ -16,6 +16,7 @@ use nym_vpn_lib::nym_config;
|
||||
use crate::fs::{config::AppConfig, data::AppData, storage::AppStorage};
|
||||
|
||||
mod commands;
|
||||
mod country;
|
||||
mod error;
|
||||
mod fs;
|
||||
mod states;
|
||||
@@ -63,6 +64,8 @@ async fn main() -> Result<()> {
|
||||
&app_config_store.full_path.display()
|
||||
);
|
||||
|
||||
let app_data = app_data_store.read().await?;
|
||||
debug!("app_data: {app_data:?}");
|
||||
let app_config = app_config_store.read().await?;
|
||||
debug!("app_config: {app_config:?}");
|
||||
|
||||
@@ -88,7 +91,7 @@ async fn main() -> Result<()> {
|
||||
info!("Starting tauri app");
|
||||
|
||||
tauri::Builder::default()
|
||||
.manage(Arc::new(Mutex::new(AppState::default())))
|
||||
.manage(Arc::new(Mutex::new(AppState::from(&app_data))))
|
||||
.manage(Arc::new(Mutex::new(app_data_store)))
|
||||
.manage(Arc::new(Mutex::new(app_config_store)))
|
||||
.setup(|_app| {
|
||||
@@ -104,8 +107,10 @@ async fn main() -> Result<()> {
|
||||
app_data::get_app_data,
|
||||
app_data::set_app_data,
|
||||
app_data::set_ui_theme,
|
||||
app_data::set_entry_location_selector,
|
||||
app_data::get_node_countries,
|
||||
node_location::set_node_location,
|
||||
node_location::get_default_node_location,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -4,6 +4,8 @@ use serde::{Deserialize, Serialize};
|
||||
use time::OffsetDateTime;
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::fs::data::AppData;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, TS)]
|
||||
#[ts(export)]
|
||||
pub struct NodeConfig {
|
||||
@@ -51,6 +53,17 @@ pub struct AppState {
|
||||
pub vpn_ctrl_tx: Option<UnboundedSender<NymVpnCtrlMessage>>,
|
||||
}
|
||||
|
||||
impl From<&AppData> for AppState {
|
||||
fn from(app_data: &AppData) -> Self {
|
||||
AppState {
|
||||
entry_node_location: app_data.entry_node_location.clone(),
|
||||
exit_node_location: app_data.exit_node_location.clone(),
|
||||
vpn_mode: app_data.vpn_mode.clone().unwrap_or_default(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, TS)]
|
||||
#[ts(export)]
|
||||
pub struct Country {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::fs::config::AppConfig;
|
||||
use crate::states::{app::ConnectionState, SharedAppState};
|
||||
use anyhow::Result;
|
||||
use futures::channel::oneshot::Receiver as OneshotReceiver;
|
||||
use futures::StreamExt;
|
||||
use nym_vpn_lib::gateway_client::Config as GatewayClientConfig;
|
||||
use nym_vpn_lib::gateway_client::{Config as GatewayClientConfig, EntryPoint, ExitPoint};
|
||||
use nym_vpn_lib::nym_config::OptionalSet;
|
||||
use nym_vpn_lib::{NymVpn, NymVpnExitError, NymVpnExitStatusMessage, StatusReceiver};
|
||||
use tauri::Manager;
|
||||
@@ -166,8 +165,8 @@ fn setup_gateway_client_config(private_key: Option<&str>) -> GatewayClientConfig
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub fn create_vpn_config(app_config: &AppConfig) -> NymVpn {
|
||||
let mut nym_vpn = NymVpn::new(&app_config.entry_gateway, &app_config.exit_router);
|
||||
pub fn create_vpn_config(entry_point: EntryPoint, exit_point: ExitPoint) -> NymVpn {
|
||||
let mut nym_vpn = NymVpn::new(entry_point, exit_point);
|
||||
nym_vpn.gateway_config = setup_gateway_client_config(None);
|
||||
nym_vpn
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"withGlobalTauri": false
|
||||
},
|
||||
"package": {
|
||||
"productName": "nym-vpn-ui",
|
||||
"productName": "nym-vpn",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
"tauri": {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Country } from './types';
|
||||
|
||||
export const routes = {
|
||||
root: '/',
|
||||
settings: '/settings',
|
||||
@@ -10,5 +8,4 @@ export const routes = {
|
||||
export const AppName = 'NymVPN';
|
||||
export const ConnectionEvent = 'connection-state';
|
||||
export const ProgressEvent = 'connection-progress';
|
||||
//putting this here for now until decided how default country is determined
|
||||
export const QuickConnectCountry: Country = { name: 'Germany', code: 'DE' };
|
||||
export const QuickConnectPrefix = 'Fastest';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { mockIPC, mockWindows } from '@tauri-apps/api/mocks';
|
||||
import { emit } from '@tauri-apps/api/event';
|
||||
import { AppDataFromBackend, ConnectionState, Country } from '../types';
|
||||
import { ConnectionEvent, QuickConnectCountry } from '../constants';
|
||||
import { ConnectionEvent } from '../constants';
|
||||
|
||||
export function mockTauriIPC() {
|
||||
mockWindows('main');
|
||||
@@ -56,21 +56,37 @@ export function mockTauriIPC() {
|
||||
);
|
||||
}
|
||||
|
||||
if (cmd === 'get_default_node_location') {
|
||||
return new Promise<Country>((resolve) =>
|
||||
resolve({
|
||||
name: 'France',
|
||||
code: 'FR',
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (cmd === 'get_app_data') {
|
||||
return new Promise<AppDataFromBackend>((resolve) =>
|
||||
resolve({
|
||||
monitoring: false,
|
||||
autoconnect: false,
|
||||
killswitch: false,
|
||||
entry_location_selector: false,
|
||||
ui_theme: 'Dark',
|
||||
vpn_mode: 'TwoHop',
|
||||
entry_node: {
|
||||
country: QuickConnectCountry,
|
||||
id: QuickConnectCountry.code,
|
||||
country: {
|
||||
name: 'France',
|
||||
code: 'FR',
|
||||
},
|
||||
id: 'nodeOne',
|
||||
},
|
||||
exit_node: {
|
||||
country: QuickConnectCountry,
|
||||
id: QuickConnectCountry.code,
|
||||
country: {
|
||||
name: 'France',
|
||||
code: 'FR',
|
||||
},
|
||||
id: 'nodeTwo',
|
||||
},
|
||||
entry_node_location: null,
|
||||
exit_node_location: null,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"loading": "Loading..",
|
||||
"none-found": "No results found!",
|
||||
"none-found": "No results found. Please try another search",
|
||||
"selected": "Selected",
|
||||
"search-country": "Search country",
|
||||
"quick-connect": "Quick connect"
|
||||
"search-country": "Search country"
|
||||
}
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"entry-selector": "Entry location selector"
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ function ConnectionStatus() {
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="h-64 flex flex-col justify-center items-center gap-y-2">
|
||||
<div className="h-72 flex flex-col justify-center items-center gap-y-2">
|
||||
<div className="flex flex-1 items-end">
|
||||
<div
|
||||
className={clsx([
|
||||
@@ -66,22 +66,26 @@ function ConnectionStatus() {
|
||||
{getStatusText(state.state)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-1">
|
||||
{state.loading && state.progressMessages.length > 0 && (
|
||||
<p className="text-dim-gray dark:text-mercury-mist font-bold">
|
||||
{t(
|
||||
`connection-progress.${
|
||||
state.progressMessages[state.progressMessages.length - 1]
|
||||
}`,
|
||||
{
|
||||
ns: 'backendMessages',
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<div className="w-full flex flex-col flex-1 items-center overflow-hidden">
|
||||
{state.loading && state.progressMessages.length > 0 && !state.error && (
|
||||
<div className="w-4/5 h-2/3 overflow-scroll break-words text-center">
|
||||
<p className="text-dim-gray dark:text-mercury-mist font-bold">
|
||||
{t(
|
||||
`connection-progress.${
|
||||
state.progressMessages[state.progressMessages.length - 1]
|
||||
}`,
|
||||
{
|
||||
ns: 'backendMessages',
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{state.state === 'Connected' && <ConnectionTimer />}
|
||||
{state.error && (
|
||||
<p className="text-teaberry font-bold">{state.error}</p>
|
||||
<div className="w-4/5 h-2/3 overflow-scroll break-words text-center">
|
||||
<p className="text-teaberry font-bold">{state.error}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,14 +5,15 @@ import clsx from 'clsx';
|
||||
import { Button } from '@mui/base';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useMainDispatch, useMainState } from '../../contexts';
|
||||
import { StateDispatch } from '../../types';
|
||||
import { QuickConnectCountry, routes } from '../../constants';
|
||||
import { CmdError, StateDispatch } from '../../types';
|
||||
import { routes } from '../../constants';
|
||||
import NetworkModeSelect from './NetworkModeSelect';
|
||||
import ConnectionStatus from './ConnectionStatus';
|
||||
import HopSelect from './HopSelect';
|
||||
|
||||
function Home() {
|
||||
const { state, loading, exitNodeLocation } = useMainState();
|
||||
const { state, loading, exitNodeLocation, defaultNodeLocation } =
|
||||
useMainState();
|
||||
const dispatch = useMainDispatch() as StateDispatch;
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation('home');
|
||||
@@ -25,9 +26,9 @@ function Home() {
|
||||
console.log('disconnect result');
|
||||
console.log(result);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
dispatch({ type: 'set-error', error: e });
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(`backend error: ${e.source} - ${e.message}`);
|
||||
dispatch({ type: 'set-error', error: e.message });
|
||||
});
|
||||
} else if (state === 'Disconnected') {
|
||||
dispatch({ type: 'connect' });
|
||||
@@ -36,9 +37,9 @@ function Home() {
|
||||
console.log('connect result');
|
||||
console.log(result);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
dispatch({ type: 'set-error', error: e });
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(`backend error: ${e.source} - ${e.message}`);
|
||||
dispatch({ type: 'set-error', error: e.message });
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -70,14 +71,22 @@ function Home() {
|
||||
<div className="h-full flex flex-col p-4">
|
||||
<ConnectionStatus />
|
||||
<div className="flex grow flex-col justify-between gap-y-2">
|
||||
<div className="flex flex-col justify-between">
|
||||
<div className="flex flex-col justify-between gap-y-4">
|
||||
<NetworkModeSelect />
|
||||
<div className="py-2"></div>
|
||||
<HopSelect
|
||||
country={exitNodeLocation ?? QuickConnectCountry}
|
||||
onClick={() => navigate(routes.exitNodeLocation)}
|
||||
nodeHop="exit"
|
||||
/>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="mt-3 font-semibold text-lg">
|
||||
{t('select-node-title')}
|
||||
</div>
|
||||
<HopSelect
|
||||
country={exitNodeLocation || defaultNodeLocation}
|
||||
onClick={() => {
|
||||
if (state === 'Disconnected') {
|
||||
navigate(routes.exitNodeLocation);
|
||||
}
|
||||
}}
|
||||
nodeHop="exit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className={clsx([
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import clsx from 'clsx';
|
||||
import { Country, NodeHop } from '../../types';
|
||||
import { useMainState } from '../../contexts';
|
||||
|
||||
interface HopSelectProps {
|
||||
country: Country;
|
||||
@@ -12,38 +14,41 @@ export default function HopSelect({
|
||||
country,
|
||||
onClick,
|
||||
}: HopSelectProps) {
|
||||
const { state } = useMainState();
|
||||
const { t } = useTranslation('home');
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="my-3 font-semibold text-lg">Connect to</div>
|
||||
<div
|
||||
className={clsx([
|
||||
state === 'Disconnected' ? 'cursor-pointer' : 'cursor-not-allowed',
|
||||
'w-full flex flex-row justify-between items-center py-3 px-4',
|
||||
'text-baltic-sea dark:text-mercury-pinkish',
|
||||
'border-cement-feet dark:border-gun-powder border-2 rounded-lg',
|
||||
'relative',
|
||||
])}
|
||||
onKeyDown={onClick}
|
||||
role="presentation"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div
|
||||
className="relative w-full flex flex-row justify-center cursor-pointer"
|
||||
onKeyDown={onClick}
|
||||
role="presentation"
|
||||
onClick={onClick}
|
||||
className={clsx([
|
||||
'absolute left-3 -top-3 px-1',
|
||||
'bg-blanc-nacre dark:bg-baltic-sea text-sm',
|
||||
])}
|
||||
>
|
||||
<input
|
||||
readOnly={true}
|
||||
type="text"
|
||||
id="floating_outlined"
|
||||
value={country.name}
|
||||
className="dark:bg-baltic-sea cursor-pointer pl-11 dark:placeholder-white border border-gun-powder block px-2.5 pb-4 pt-4 w-full text-sm text-gray-900 bg-transparent rounded-lg border-1 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"
|
||||
/>
|
||||
{nodeHop === 'entry' ? t('first-hop') : t('last-hop')}
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-3">
|
||||
<img
|
||||
src={`./flags/${country.code.toLowerCase()}.svg`}
|
||||
className="h-8 scale-75 pointer-events-none absolute fill-current top-1/2 transform -translate-y-1/2 left-2"
|
||||
className="h-8 scale-90 pointer-events-none fill-current"
|
||||
alt={country.code}
|
||||
/>
|
||||
<span className="font-icon scale-125 pointer-events-none absolute fill-current top-1/4 transform -translate-x-1/2 right-2">
|
||||
arrow_right
|
||||
</span>
|
||||
<label
|
||||
htmlFor="floating_outlined"
|
||||
className="dark:text-white bg-blanc-nacre dark:bg-baltic-sea absolute text-sm text-gray-500 dark:text-gray-400 ml-4 duration-300 transform -translate-y-4 scale-75 top-2 z-10 origin-[0] dark:bg-gray-900 px-2 peer-placeholder-shown:px-2 peer-placeholder-shown:text-blue-600 peer-placeholder-shown:dark:text-blue-500 peer-placeholder-shown:top-2 peer-placeholder-shown:scale-75 peer-placeholder-shown:-translate-y-4 rtl:peer-placeholder-shown:translate-x-1/4 rtl:peer-placeholder-shown:left-auto start-1"
|
||||
>
|
||||
{nodeHop === 'entry' ? t('first-hop') : t('last-hop')}
|
||||
</label>
|
||||
<div className="text-base">{country.name}</div>
|
||||
</div>
|
||||
</>
|
||||
<span className="font-icon scale-150 pointer-events-none">
|
||||
arrow_right
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -55,11 +55,11 @@ function NetworkModeSelect() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div>
|
||||
<RadioGroup value={selected} onChange={handleSelect}>
|
||||
<RadioGroup.Label
|
||||
as="div"
|
||||
className="font-semibold text-lg text-baltic-sea dark:text-white mb-4"
|
||||
className="font-semibold text-lg text-baltic-sea dark:text-white mb-5"
|
||||
>
|
||||
{t('select-network-label')}
|
||||
</RadioGroup.Label>
|
||||
@@ -102,7 +102,7 @@ function NetworkModeSelect() {
|
||||
</RadioGroup.Label>
|
||||
<RadioGroup.Description
|
||||
as="span"
|
||||
className="text-base text-ciment-feet dark:text-mercury-mist"
|
||||
className="text-base text-cement-feet dark:text-mercury-mist"
|
||||
>
|
||||
<span>{mode.desc}</span>
|
||||
</RadioGroup.Description>
|
||||
|
||||
@@ -12,14 +12,14 @@ export default function CountryList({
|
||||
}: CountryListProps) {
|
||||
const { t } = useTranslation('nodeLocation');
|
||||
return (
|
||||
<ul className="flex flex-col w-full items-stretch p-1">
|
||||
<ul className="flex flex-col w-full items-stretch gap-4">
|
||||
{countries && countries.length > 0 ? (
|
||||
countries.map((country) => (
|
||||
<li key={country.code} className="list-none w-full">
|
||||
<div
|
||||
role="presentation"
|
||||
onKeyDown={() => onClick(country.name, country.code)}
|
||||
className="flex flex-row justify-between dark:hover:bg-baltic-sea-jaguar hover:bg-coal-mine-light rounded-lg cursor-pointer"
|
||||
className="flex flex-row justify-between dark:hover:bg-gun-powder hover:dark:bg-opacity-80 hover:bg-cement-feet hover:bg-opacity-20 rounded-lg cursor-pointer px-3"
|
||||
onClick={() => onClick(country.name, country.code)}
|
||||
>
|
||||
<div className="flex flex-row items-center m-1 gap-3 p-1 cursor-pointer">
|
||||
@@ -32,14 +32,14 @@ export default function CountryList({
|
||||
{country.name}
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4 flex items-center text-mercury-mist text-xs cursor-pointer">
|
||||
<div className="p-4 flex items-center text-mercury-mist text-sm cursor-pointer">
|
||||
{isSelected(country.code) ? t('selected') : ''}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))
|
||||
) : (
|
||||
<p>{t('none-found')}</p>
|
||||
<p className="flex justify-center">{t('none-found')}</p>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
|
||||
@@ -11,28 +11,22 @@ import QuickConnect from './QuickConnect';
|
||||
|
||||
function NodeLocation({ node }: { node: NodeHop }) {
|
||||
const { t } = useTranslation('nodeLocation');
|
||||
const [countries, setCountries] = useState<Country[]>([]);
|
||||
const { entryNodeLocation, exitNodeLocation, countries } = useMainState();
|
||||
const [search, setSearch] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [foundCountries, setFoundCountries] = useState<Country[]>([]);
|
||||
const [foundCountries, setFoundCountries] = useState<Country[]>(countries);
|
||||
|
||||
const { entryNodeLocation, exitNodeLocation } = useMainState();
|
||||
const dispatch = useMainDispatch() as StateDispatch;
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
//request backend to update countries cache
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
const getNodeCountries = async () => {
|
||||
const countries = await invoke<Country[]>('get_node_countries');
|
||||
setTimeout(() => {
|
||||
setCountries(countries);
|
||||
setFoundCountries(countries);
|
||||
setLoading(false);
|
||||
}, 1000);
|
||||
dispatch({ type: 'set-countries', countries });
|
||||
};
|
||||
getNodeCountries().catch(console.error);
|
||||
}, []);
|
||||
}, [dispatch]);
|
||||
|
||||
const filter = (e: InputEvent) => {
|
||||
const keyword = e.target.value;
|
||||
@@ -72,26 +66,20 @@ function NodeLocation({ node }: { node: NodeHop }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="h-70 flex flex-col justify-center items-center gap-y-2 p-1">
|
||||
<QuickConnect onClick={handleCountrySelection} />
|
||||
<SearchBox
|
||||
value={search}
|
||||
onChange={filter}
|
||||
placeholder={t('search-country')}
|
||||
/>
|
||||
<span className="mt-3" />
|
||||
{!loading ? (
|
||||
<CountryList
|
||||
countries={foundCountries}
|
||||
onClick={handleCountrySelection}
|
||||
isSelected={isCountrySelected}
|
||||
/>
|
||||
) : (
|
||||
<div>{t('loading')}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="h-full flex flex-col p-4">
|
||||
<div className="h-70 flex flex-col justify-center items-center gap-y-2">
|
||||
<QuickConnect onClick={handleCountrySelection} />
|
||||
<SearchBox
|
||||
value={search}
|
||||
onChange={filter}
|
||||
placeholder={t('search-country')}
|
||||
/>
|
||||
<span className="mt-3" />
|
||||
<CountryList
|
||||
countries={foundCountries}
|
||||
onClick={handleCountrySelection}
|
||||
isSelected={isCountrySelected}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { QuickConnectCountry } from '../../constants';
|
||||
import { useMainState } from '../../contexts';
|
||||
import { QuickConnectPrefix } from '../../constants';
|
||||
|
||||
interface QuickConnectProps {
|
||||
onClick: (name: string, code: string) => void;
|
||||
}
|
||||
|
||||
export default function QuickConnect({ onClick }: QuickConnectProps) {
|
||||
const { t } = useTranslation('nodeLocation');
|
||||
const { defaultNodeLocation } = useMainState();
|
||||
|
||||
return (
|
||||
<div
|
||||
role="presentation"
|
||||
onKeyDown={() =>
|
||||
onClick(QuickConnectCountry.name, QuickConnectCountry.code)
|
||||
onClick(defaultNodeLocation.name, defaultNodeLocation.code)
|
||||
}
|
||||
className="flex flex-row w-full py-8 cursor-pointer"
|
||||
className="flex px-1 flex-row items-center w-full py-8 cursor-pointer"
|
||||
onClick={() =>
|
||||
onClick(QuickConnectCountry.name, QuickConnectCountry.code)
|
||||
onClick(defaultNodeLocation.name, defaultNodeLocation.code)
|
||||
}
|
||||
>
|
||||
<span className="font-icon px-4 cursor-pointer">bolt</span>
|
||||
<div className="cursor-pointer">{`${t('quick-connect')} (${
|
||||
QuickConnectCountry.name
|
||||
})`}</div>
|
||||
<span className="font-icon text-2xl px-4 cursor-pointer">bolt</span>
|
||||
<div className="cursor-pointer">{`${QuickConnectPrefix} ${defaultNodeLocation.name}`}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import clsx from 'clsx';
|
||||
import { InputEvent } from '../../types';
|
||||
|
||||
interface SearchProps {
|
||||
@@ -12,24 +13,30 @@ export default function SearchBox({
|
||||
placeholder,
|
||||
}: SearchProps) {
|
||||
return (
|
||||
<div className="relative w-full flex flex-row justify-center px-1.5">
|
||||
<div className="w-full relative flex flex-row items-center px-4 mb-2">
|
||||
<input
|
||||
type="text"
|
||||
id="floating_outlined"
|
||||
id="country_search"
|
||||
value={value}
|
||||
className="dark:bg-baltic-sea pl-9 dark:placeholder-white border border-gun-powder block px-2.5 pb-4 pt-4 w-full text-sm text-gray-900 bg-transparent rounded-lg border-1 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"
|
||||
className={clsx([
|
||||
'bg-blanc-nacre dark:bg-baltic-sea focus:outline-none focus:ring-0',
|
||||
'w-full flex flex-row justify-between items-center py-3 px-4 pl-11',
|
||||
'text-baltic-sea dark:text-mercury-pinkish',
|
||||
'placeholder:text-cement-feet placeholder:dark:text-mercury-mist',
|
||||
'border-cement-feet dark:border-gun-powder border-2 rounded-lg',
|
||||
'relative text-base',
|
||||
])}
|
||||
placeholder={placeholder}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<span className="font-icon scale-125 pointer-events-none absolute fill-current top-1/2 transform -translate-y-1/2 left-4">
|
||||
<span
|
||||
className={clsx([
|
||||
'font-icon text-2xl absolute left-7',
|
||||
'text-baltic-sea dark:text-laughing-jack',
|
||||
])}
|
||||
>
|
||||
search
|
||||
</span>
|
||||
<label
|
||||
htmlFor="floating_outlined"
|
||||
className="dark:text-white dark:bg-baltic-sea absolute text-sm text-gray-500 dark:text-gray-400 ml-4 duration-300 transform -translate-y-4 scale-75 top-2 z-10 origin-[0] bg-blanc-nacre dark:bg-gray-900 px-2 peer-placeholder-shown:px-2 peer-placeholder-shown:text-blue-600 peer-placeholder-shown:dark:text-blue-500 peer-placeholder-shown:top-2 peer-placeholder-shown:scale-75 peer-placeholder-shown:-translate-y-4 rtl:peer-placeholder-shown:translate-x-1/4 rtl:peer-placeholder-shown:left-auto start-1"
|
||||
>
|
||||
Search
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@ function Settings() {
|
||||
const state = useMainState();
|
||||
const dispatch = useMainDispatch() as StateDispatch;
|
||||
|
||||
const [enabled, setEnabled] = useState(state.uiTheme === 'Dark');
|
||||
const [darkModeEnabled, setDarkModeEnabled] = useState(
|
||||
state.uiTheme === 'Dark',
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setEnabled(state.uiTheme === 'Dark');
|
||||
}, [state.uiTheme]);
|
||||
setDarkModeEnabled(state.uiTheme === 'Dark');
|
||||
}, [state]);
|
||||
|
||||
const handleThemeChange = async (darkMode: boolean) => {
|
||||
if (darkMode && state.uiTheme === 'Light') {
|
||||
@@ -29,24 +31,26 @@ function Settings() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col p-4">
|
||||
<div className="h-full flex flex-col p-4 gap-4">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<p className="text-lg text-baltic-sea dark:text-mercury-pinkish">
|
||||
Dark Mode
|
||||
</p>
|
||||
<Switch
|
||||
checked={enabled}
|
||||
checked={darkModeEnabled}
|
||||
onChange={handleThemeChange}
|
||||
className={clsx([
|
||||
enabled ? 'bg-melon' : 'bg-mercury-pinkish dark:bg-gun-powder',
|
||||
darkModeEnabled
|
||||
? 'bg-melon'
|
||||
: 'bg-mercury-pinkish dark:bg-gun-powder',
|
||||
'relative inline-flex h-6 w-11 items-center rounded-full',
|
||||
])}
|
||||
>
|
||||
<span className="sr-only">Dark mode</span>
|
||||
<span
|
||||
className={clsx([
|
||||
enabled ? 'translate-x-6' : 'translate-x-1',
|
||||
'inline-block h-4 w-4 transform rounded-full bg-ciment-feet dark:bg-white transition',
|
||||
darkModeEnabled ? 'translate-x-6' : 'translate-x-1',
|
||||
'inline-block h-4 w-4 transform rounded-full bg-cement-feet dark:bg-white transition',
|
||||
])}
|
||||
/>
|
||||
</Switch>
|
||||
|
||||
@@ -13,6 +13,7 @@ export type StateAction =
|
||||
| { type: 'set-partial-state'; partialState: Partial<AppState> }
|
||||
| { type: 'change-connection-state'; state: ConnectionState }
|
||||
| { type: 'set-vpn-mode'; mode: VpnMode }
|
||||
| { type: 'set-entry-selector'; entrySelector: boolean }
|
||||
| { type: 'set-error'; error: string }
|
||||
| { type: 'reset-error' }
|
||||
| { type: 'new-progress-message'; message: ConnectProgressMsg }
|
||||
@@ -23,17 +24,25 @@ export type StateAction =
|
||||
| { type: 'set-disconnected' }
|
||||
| { type: 'reset' }
|
||||
| { type: 'set-ui-theme'; theme: UiTheme }
|
||||
| { type: 'set-node-location'; payload: { hop: NodeHop; country: Country } };
|
||||
| { type: 'set-countries'; countries: Country[] }
|
||||
| { type: 'set-node-location'; payload: { hop: NodeHop; country: Country } }
|
||||
| { type: 'set-default-node-location'; country: Country };
|
||||
|
||||
export const initialState: AppState = {
|
||||
state: 'Disconnected',
|
||||
loading: false,
|
||||
vpnMode: 'Mixnet',
|
||||
vpnMode: 'TwoHop',
|
||||
entrySelector: false,
|
||||
tunnel: { name: 'nym', id: 'nym' },
|
||||
uiTheme: 'Light',
|
||||
progressMessages: [],
|
||||
entryNodeLocation: null,
|
||||
exitNodeLocation: null,
|
||||
defaultNodeLocation: {
|
||||
name: 'France',
|
||||
code: 'FR',
|
||||
},
|
||||
countries: [],
|
||||
};
|
||||
|
||||
export function reducer(state: AppState, action: StateAction): AppState {
|
||||
@@ -54,6 +63,16 @@ export function reducer(state: AppState, action: StateAction): AppState {
|
||||
...state,
|
||||
vpnMode: action.mode,
|
||||
};
|
||||
case 'set-entry-selector':
|
||||
return {
|
||||
...state,
|
||||
entrySelector: action.entrySelector,
|
||||
};
|
||||
case 'set-countries':
|
||||
return {
|
||||
...state,
|
||||
countries: action.countries,
|
||||
};
|
||||
case 'set-partial-state': {
|
||||
return { ...state, ...action.partialState };
|
||||
}
|
||||
@@ -121,6 +140,11 @@ export function reducer(state: AppState, action: StateAction): AppState {
|
||||
...state,
|
||||
uiTheme: action.theme,
|
||||
};
|
||||
case 'set-default-node-location':
|
||||
return {
|
||||
...state,
|
||||
defaultNodeLocation: action.country,
|
||||
};
|
||||
case 'reset':
|
||||
return initialState;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import React, { useEffect, useReducer } from 'react';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { MainDispatchContext, MainStateContext } from '../contexts';
|
||||
import { AppDataFromBackend, CmdError, ConnectionState } from '../types';
|
||||
import { QuickConnectCountry } from '../constants';
|
||||
import {
|
||||
AppDataFromBackend,
|
||||
CmdError,
|
||||
ConnectionState,
|
||||
Country,
|
||||
} from '../types';
|
||||
import { initialState, reducer } from './main';
|
||||
import { useTauriEvents } from './useTauriEvents';
|
||||
|
||||
@@ -26,12 +30,53 @@ export function MainStateProvider({ children }: Props) {
|
||||
return await invoke<number | undefined>('get_connection_start_time');
|
||||
};
|
||||
|
||||
getInitialConnectionState().then((state) =>
|
||||
dispatch({ type: 'change-connection-state', state }),
|
||||
);
|
||||
getSessionStartTime().then((startTime) =>
|
||||
dispatch({ type: 'set-connection-start-time', startTime }),
|
||||
);
|
||||
// init country list
|
||||
const getCountries = async () => {
|
||||
return await invoke<Country[]>('get_node_countries');
|
||||
};
|
||||
|
||||
// init default node location
|
||||
const getDefaultNodeLocation = async () => {
|
||||
return await invoke<Country>('get_default_node_location');
|
||||
};
|
||||
|
||||
getInitialConnectionState()
|
||||
.then((state) => dispatch({ type: 'change-connection-state', state }))
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(
|
||||
`command [get_connection_state] returned an error: ${e.source} - ${e.message}`,
|
||||
);
|
||||
});
|
||||
|
||||
getSessionStartTime()
|
||||
.then((startTime) =>
|
||||
dispatch({ type: 'set-connection-start-time', startTime }),
|
||||
)
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(
|
||||
`command [get_connection_start_time] returned an error: ${e.source} - ${e.message}`,
|
||||
);
|
||||
});
|
||||
|
||||
getCountries()
|
||||
.then((countries) => {
|
||||
dispatch({ type: 'set-countries', countries });
|
||||
})
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(
|
||||
`command [get_node_countries] returned an error: ${e.source} - ${e.message}`,
|
||||
);
|
||||
});
|
||||
|
||||
getDefaultNodeLocation()
|
||||
.then((country) => {
|
||||
dispatch({ type: 'set-default-node-location', country });
|
||||
})
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(
|
||||
`command [get_default_node_location] returned an error: ${e.source} - ${e.message}`,
|
||||
);
|
||||
});
|
||||
}, []);
|
||||
|
||||
// get saved on disk app data and restore state from it
|
||||
@@ -42,20 +87,28 @@ export function MainStateProvider({ children }: Props) {
|
||||
|
||||
getAppData()
|
||||
.then((data) => {
|
||||
console.log('app data read from disk:');
|
||||
console.log(data);
|
||||
const partialState: Partial<typeof initialState> = {
|
||||
entrySelector: data.entry_location_selector || false,
|
||||
uiTheme: data.ui_theme || 'Light',
|
||||
vpnMode: data.vpn_mode || 'TwoHop',
|
||||
};
|
||||
if (data.entry_node_location) {
|
||||
partialState.entryNodeLocation = data.entry_node_location;
|
||||
}
|
||||
if (data.exit_node_location) {
|
||||
partialState.exitNodeLocation = data.exit_node_location;
|
||||
}
|
||||
dispatch({
|
||||
type: 'set-partial-state',
|
||||
partialState: {
|
||||
uiTheme: data.ui_theme || 'Light',
|
||||
vpnMode: data.vpn_mode || 'TwoHop',
|
||||
entryNodeLocation: data.entry_node_location || QuickConnectCountry,
|
||||
exitNodeLocation: data.exit_node_location || QuickConnectCountry,
|
||||
},
|
||||
partialState,
|
||||
});
|
||||
})
|
||||
.catch((err: CmdError) => {
|
||||
// TODO handle error properly
|
||||
console.log(err);
|
||||
.catch((e: CmdError) => {
|
||||
console.warn(
|
||||
`command [get_app_data] returned an error: ${e.source} - ${e.message}`,
|
||||
);
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface AppDataFromBackend {
|
||||
monitoring: boolean | null;
|
||||
autoconnect: boolean | null;
|
||||
killswitch: boolean | null;
|
||||
entry_location_selector: boolean | null;
|
||||
ui_theme: UiTheme | null;
|
||||
vpn_mode: VpnMode | null;
|
||||
entry_node: NodeConfig | null;
|
||||
|
||||
@@ -26,8 +26,11 @@ export type AppState = {
|
||||
vpnMode: VpnMode;
|
||||
tunnel: TunnelConfig;
|
||||
uiTheme: 'Light' | 'Dark';
|
||||
entrySelector: boolean;
|
||||
entryNodeLocation: Country | null;
|
||||
exitNodeLocation: Country | null;
|
||||
defaultNodeLocation: Country;
|
||||
countries: Country[];
|
||||
};
|
||||
|
||||
export type ConnectionEventPayload = {
|
||||
|
||||
@@ -62,7 +62,7 @@ export default {
|
||||
'dim-gray': '#696571',
|
||||
// [L] network mode desc text
|
||||
// [L] node location select outline
|
||||
'ciment-feet': '#79747E',
|
||||
'cement-feet': '#79747E',
|
||||
// [D] node location select outline
|
||||
'gun-powder': '#49454F',
|
||||
// [D] top-bar icon
|
||||
|
||||
@@ -3,6 +3,7 @@ name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.58"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
hex-literal = "0.3.3"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-socks5-listener"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "nym-sdk"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||