Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa833310da | |||
| 17ed80018f | |||
| cdfcb065b7 | |||
| fd1c0ae62b | |||
| bd7399091b | |||
| 00fad44e2e | |||
| ea33c332ee | |||
| b39f8af8d0 | |||
| a400463b7e | |||
| 82928af64c | |||
| c5891f546c | |||
| 580b677489 | |||
| 2093789c5c | |||
| d09864b99f | |||
| f6e8278592 | |||
| b085a8a636 | |||
| e6ce531aeb | |||
| 1a860eb3f5 | |||
| 09cfd9ff05 | |||
| 2c88ca137a | |||
| ca3bfc859a | |||
| 529db99b8e | |||
| fd4f083742 | |||
| 06256e512d | |||
| 6b4e915cd6 | |||
| 19cdb7f629 | |||
| 029f8904fe | |||
| 5f852e04a0 | |||
| 365b955c90 | |||
| f14a87809e | |||
| a18eec2fe5 | |||
| 3c99644420 | |||
| d6e6369389 | |||
| eff1f383c3 | |||
| a192e0d745 | |||
| 6168ac9e9b | |||
| f7d96042de | |||
| 353ccbe258 | |||
| 6b74a1f091 | |||
| 2f191f50ee | |||
| 0de1196f85 | |||
| 78c1cc05e1 | |||
| ee8101db04 | |||
| cd6c68907c | |||
| 452e9ed637 | |||
| eeeb8052b6 | |||
| bc79ee0cad | |||
| aa5cbd06d4 | |||
| 15cdf579b2 | |||
| caf9429431 | |||
| 708782fdf9 | |||
| 3fc11d8bef | |||
| 2eadda2295 | |||
| 9434cb266b | |||
| 8f49db1150 | |||
| c45e8da43d | |||
| 12cc49a734 | |||
| 7e56a9e88c | |||
| 9790009eac | |||
| 379d593daf | |||
| ce75b99b6f | |||
| bcb7c41fd7 | |||
| bb091ce47f | |||
| effed4d7d6 | |||
| d480ddb133 | |||
| b119820591 | |||
| e128949dc2 | |||
| 9499b987e5 | |||
| d6ac786295 | |||
| 4d09d9c3db | |||
| 8c9044adf3 | |||
| 472085ca52 | |||
| 2f089e80ff |
@@ -0,0 +1,105 @@
|
|||||||
|
name: Build and upload binaries to CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'clients/**'
|
||||||
|
- 'common/**'
|
||||||
|
- 'contracts/**'
|
||||||
|
- 'explorer-api/**'
|
||||||
|
- 'gateway/**'
|
||||||
|
- 'integrations/**'
|
||||||
|
- 'mixnode/**'
|
||||||
|
- 'sdk/rust/nym-sdk/**'
|
||||||
|
- 'service-providers/**'
|
||||||
|
- 'nym-api/**'
|
||||||
|
- 'nym-outfox/**'
|
||||||
|
- 'tools/nym-cli/**'
|
||||||
|
- 'tools/ts-rs-cli/**'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'clients/**'
|
||||||
|
- 'common/**'
|
||||||
|
- 'contracts/**'
|
||||||
|
- 'explorer-api/**'
|
||||||
|
- 'gateway/**'
|
||||||
|
- 'integrations/**'
|
||||||
|
- 'mixnode/**'
|
||||||
|
- 'sdk/rust/nym-sdk/**'
|
||||||
|
- 'service-providers/**'
|
||||||
|
- 'nym-api/**'
|
||||||
|
- 'nym-outfox/**'
|
||||||
|
- 'tools/nym-cli/**'
|
||||||
|
- 'tools/ts-rs-cli/**'
|
||||||
|
|
||||||
|
env:
|
||||||
|
NETWORK: mainnet
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-nym:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: [ubuntu-20.04]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
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: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Build all binaries
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --workspace --release
|
||||||
|
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
target: wasm32-unknown-unknown
|
||||||
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
|
||||||
|
- name: Build release contracts
|
||||||
|
run: make wasm
|
||||||
|
|
||||||
|
- name: Prepare build output
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
rm -rf ci-builds || true
|
||||||
|
mkdir ci-builds
|
||||||
|
|
||||||
|
cp target/release/nym-client ci-builds
|
||||||
|
cp target/release/nym-gateway ci-builds
|
||||||
|
cp target/release/nym-mixnode ci-builds
|
||||||
|
cp target/release/nym-socks5-client ci-builds
|
||||||
|
cp target/release/nym-api ci-builds
|
||||||
|
cp target/release/nym-network-requester ci-builds
|
||||||
|
cp target/release/nym-network-statistics ci-builds
|
||||||
|
cp target/release/nym-cli ci-builds
|
||||||
|
|
||||||
|
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm ci-builds
|
||||||
|
cp contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm ci-builds
|
||||||
|
|
||||||
|
- name: Deploy branch to CI www
|
||||||
|
continue-on-error: true
|
||||||
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
|
ARGS: "-rltgoDzvO --delete"
|
||||||
|
SOURCE: "ci-builds/"
|
||||||
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ env.GITHUB_REF_NAME }}/
|
||||||
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: Tests for validator API
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "nym-api/tests/**"
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: nym-api/tests
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: validator api tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Node v18
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18.1.0
|
||||||
|
|
||||||
|
- name: Install yarn
|
||||||
|
run: yarn install
|
||||||
|
|
||||||
|
- name: Run yarn
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
- name: Launch tests
|
||||||
|
run: yarn test:qa
|
||||||
|
working-directory: nym-api/tests
|
||||||
+23
-8
@@ -4,18 +4,33 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
# [Unreleased]
|
# [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- remove coconut feature and unify builds ([#2890])
|
||||||
|
- native-client: is now capable of listening for requests on sockets different than `127.0.0.1` ([#2939]). This can be specified via `--host` flag during `init` or `run`. Alternatively a custom `host` can be set in `config.toml` file under `socket` section.
|
||||||
|
|
||||||
|
[#2890]: https://github.com/nymtech/nym/pull/2890
|
||||||
|
[#2939]: https://github.com/nymtech/nym/pull/2939
|
||||||
|
|
||||||
|
# [v1.1.8] (2023-01-31)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- dkg rerun from scratch and dkg-specific epochs ([#2839])
|
- Rust SDK - Support SURBS (anonymous send + storage) ([#2754])
|
||||||
- nym-sdk: add support for surb storage ([#2870])
|
- dkg rerun from scratch and dkg-specific epochs ([#2810])
|
||||||
- nym-sdk: enable reply-SURBs by default ([#2874])
|
- Rename `'initial_supply'` field to `'total_supply'` in the circulating supply endpoint ([#2931])
|
||||||
- remove coconut feature and unify builds ([#2890])
|
- Circulating supply api endpoint (read the note inside before testing/deploying) ([#1902])
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- nym-api: an `--id` flag is now always explicitly required ([#2873])
|
||||||
|
|
||||||
|
[#2754]: https://github.com/nymtech/nym/issues/2754
|
||||||
|
[#2810]: https://github.com/nymtech/nym/issues/2810
|
||||||
|
[#2931]: https://github.com/nymtech/nym/issues/2931
|
||||||
|
[#1902]: https://github.com/nymtech/nym/issues/1902
|
||||||
|
[#2873]: https://github.com/nymtech/nym/issues/2873
|
||||||
|
|
||||||
[#2839]: https://github.com/nymtech/nym/pull/2839
|
|
||||||
[#2870]: https://github.com/nymtech/nym/pull/2870
|
|
||||||
[#2874]: https://github.com/nymtech/nym/pull/2874
|
|
||||||
[#2890]: https://github.com/nymtech/nym/pull/2890
|
|
||||||
|
|
||||||
# [v1.1.7] (2023-01-24)
|
# [v1.1.7] (2023-01-24)
|
||||||
|
|
||||||
|
|||||||
Generated
+11
-10
@@ -701,7 +701,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "client-core"
|
name = "client-core"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"client-connections",
|
"client-connections",
|
||||||
@@ -1891,7 +1891,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "explorer-api"
|
name = "explorer-api"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap 4.1.3",
|
"clap 4.1.3",
|
||||||
@@ -3314,6 +3314,7 @@ dependencies = [
|
|||||||
"cw4",
|
"cw4",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3437,7 +3438,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-api"
|
name = "nym-api"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -3535,7 +3536,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-cli"
|
name = "nym-cli"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
@@ -3593,7 +3594,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"build-information",
|
"build-information",
|
||||||
"clap 4.1.3",
|
"clap 4.1.3",
|
||||||
@@ -3633,7 +3634,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-gateway"
|
name = "nym-gateway"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -3685,7 +3686,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-mixnode"
|
name = "nym-mixnode"
|
||||||
version = "1.1.8"
|
version = "1.1.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"atty",
|
"atty",
|
||||||
@@ -3730,7 +3731,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-network-requester"
|
name = "nym-network-requester"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"clap 4.1.3",
|
"clap 4.1.3",
|
||||||
@@ -3762,7 +3763,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-network-statistics"
|
name = "nym-network-statistics"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
"log",
|
"log",
|
||||||
@@ -3819,7 +3820,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"build-information",
|
"build-information",
|
||||||
"clap 4.1.3",
|
"clap 4.1.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "client-core"
|
name = "client-core"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.66"
|
rust-version = "1.66"
|
||||||
|
|||||||
@@ -546,35 +546,35 @@ impl<T: NymConfig> Default for Client<T> {
|
|||||||
|
|
||||||
impl<T: NymConfig> Client<T> {
|
impl<T: NymConfig> Client<T> {
|
||||||
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("private_identity.pem")
|
T::default_data_directory(id).join("private_identity.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("public_identity.pem")
|
T::default_data_directory(id).join("public_identity.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_private_encryption_key_file(id: &str) -> PathBuf {
|
fn default_private_encryption_key_file(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("private_encryption.pem")
|
T::default_data_directory(id).join("private_encryption.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_public_encryption_key_file(id: &str) -> PathBuf {
|
fn default_public_encryption_key_file(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("public_encryption.pem")
|
T::default_data_directory(id).join("public_encryption.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_gateway_shared_key_file(id: &str) -> PathBuf {
|
fn default_gateway_shared_key_file(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("gateway_shared.pem")
|
T::default_data_directory(id).join("gateway_shared.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_ack_key_file(id: &str) -> PathBuf {
|
fn default_ack_key_file(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("ack_key.pem")
|
T::default_data_directory(id).join("ack_key.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_reply_surb_database_path(id: &str) -> PathBuf {
|
fn default_reply_surb_database_path(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join("persistent_reply_store.sqlite")
|
T::default_data_directory(id).join("persistent_reply_store.sqlite")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_database_path(id: &str) -> PathBuf {
|
fn default_database_path(id: &str) -> PathBuf {
|
||||||
T::default_data_directory(Some(id)).join(DB_FILE_NAME)
|
T::default_data_directory(id).join(DB_FILE_NAME)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig
|
|||||||
where
|
where
|
||||||
T: NymConfig + ClientCoreConfigTrait,
|
T: NymConfig + ClientCoreConfigTrait,
|
||||||
{
|
{
|
||||||
T::load_from_file(Some(id))
|
T::load_from_file(id)
|
||||||
.map(|existing_config| existing_config.get_gateway_endpoint().clone())
|
.map(|existing_config| existing_config.get_gateway_endpoint().clone())
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
description = "Implementation of the Nym Client"
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
|||||||
use config::{NymConfig, OptionalSet};
|
use config::{NymConfig, OptionalSet};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
@@ -104,6 +105,11 @@ impl Config {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_host(mut self, host: IpAddr) -> Self {
|
||||||
|
self.socket.host = host;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_port(mut self, port: u16) -> Self {
|
pub fn with_port(mut self, port: u16) -> Self {
|
||||||
self.socket.listening_port = port;
|
self.socket.listening_port = port;
|
||||||
self
|
self
|
||||||
@@ -130,6 +136,10 @@ impl Config {
|
|||||||
self.socket.socket_type
|
self.socket.socket_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_listening_ip(&self) -> IpAddr {
|
||||||
|
self.socket.host
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_listening_port(&self) -> u16 {
|
pub fn get_listening_port(&self) -> u16 {
|
||||||
self.socket.listening_port
|
self.socket.listening_port
|
||||||
}
|
}
|
||||||
@@ -180,9 +190,10 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(default, deny_unknown_fields)]
|
||||||
pub struct Socket {
|
pub struct Socket {
|
||||||
socket_type: SocketType,
|
socket_type: SocketType,
|
||||||
|
host: IpAddr,
|
||||||
listening_port: u16,
|
listening_port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +201,7 @@ impl Default for Socket {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Socket {
|
Socket {
|
||||||
socket_type: SocketType::WebSocket,
|
socket_type: SocketType::WebSocket,
|
||||||
|
host: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
|
||||||
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
|
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ socket_type = '{{ socket.socket_type }}'
|
|||||||
# will be listening for incoming requests
|
# will be listening for incoming requests
|
||||||
listening_port = {{ socket.listening_port }}
|
listening_port = {{ socket.listening_port }}
|
||||||
|
|
||||||
|
# if applicable (for the case of 'WebSocket'), the ip address on which the client
|
||||||
|
# will be listening for incoming requests
|
||||||
|
host = '{{ socket.host }}'
|
||||||
|
|
||||||
##### logging configuration options #####
|
##### logging configuration options #####
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ impl SocketClient {
|
|||||||
reply_controller_sender,
|
reply_controller_sender,
|
||||||
);
|
);
|
||||||
|
|
||||||
websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown);
|
websocket::Listener::new(config.get_listening_ip(), config.get_listening_port())
|
||||||
|
.start(websocket_handler, shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
|
/// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use crypto::asymmetric::identity;
|
|||||||
use nymsphinx::addressing::clients::Recipient;
|
use nymsphinx::addressing::clients::Recipient;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::net::IpAddr;
|
||||||
use tap::TapFallible;
|
use tap::TapFallible;
|
||||||
|
|
||||||
#[derive(Args, Clone)]
|
#[derive(Args, Clone)]
|
||||||
@@ -46,6 +47,10 @@ pub(crate) struct Init {
|
|||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
|
|
||||||
|
/// Ip for the socket (if applicable) to listen for requests.
|
||||||
|
#[clap(long)]
|
||||||
|
host: Option<IpAddr>,
|
||||||
|
|
||||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||||
/// modify config post init
|
/// modify config post init
|
||||||
#[clap(long, hide = true)]
|
#[clap(long, hide = true)]
|
||||||
@@ -71,6 +76,7 @@ impl From<Init> for OverrideConfig {
|
|||||||
nym_apis: init_config.nym_apis,
|
nym_apis: init_config.nym_apis,
|
||||||
disable_socket: init_config.disable_socket,
|
disable_socket: init_config.disable_socket,
|
||||||
port: init_config.port,
|
port: init_config.port,
|
||||||
|
host: init_config.host,
|
||||||
fastmode: init_config.fastmode,
|
fastmode: init_config.fastmode,
|
||||||
no_cover: init_config.no_cover,
|
no_cover: init_config.no_cover,
|
||||||
|
|
||||||
@@ -108,7 +114,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
|
|||||||
|
|
||||||
let id = &args.id;
|
let id = &args.id;
|
||||||
|
|
||||||
let already_init = Config::default_config_file_path(Some(id)).exists();
|
let already_init = Config::default_config_file_path(id).exists();
|
||||||
if already_init {
|
if already_init {
|
||||||
println!("Client \"{id}\" was already initialised before");
|
println!("Client \"{id}\" was already initialised before");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use completions::{fig_generate, ArgShell};
|
|||||||
use config::OptionalSet;
|
use config::OptionalSet;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
|
||||||
pub(crate) mod init;
|
pub(crate) mod init;
|
||||||
pub(crate) mod run;
|
pub(crate) mod run;
|
||||||
@@ -56,6 +57,7 @@ pub(crate) struct OverrideConfig {
|
|||||||
nym_apis: Option<Vec<url::Url>>,
|
nym_apis: Option<Vec<url::Url>>,
|
||||||
disable_socket: Option<bool>,
|
disable_socket: Option<bool>,
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
|
host: Option<IpAddr>,
|
||||||
fastmode: bool,
|
fastmode: bool,
|
||||||
no_cover: bool,
|
no_cover: bool,
|
||||||
nyxd_urls: Option<Vec<url::Url>>,
|
nyxd_urls: Option<Vec<url::Url>>,
|
||||||
@@ -81,6 +83,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
|||||||
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode)
|
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode)
|
||||||
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover)
|
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover)
|
||||||
.with_optional(Config::with_port, args.port)
|
.with_optional(Config::with_port, args.port)
|
||||||
|
.with_optional(Config::with_host, args.host)
|
||||||
.with_optional_custom_env_ext(
|
.with_optional_custom_env_ext(
|
||||||
BaseConfig::with_custom_nym_apis,
|
BaseConfig::with_custom_nym_apis,
|
||||||
args.nym_apis,
|
args.nym_apis,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::{config::Config, SocketClient},
|
client::{config::Config, SocketClient},
|
||||||
@@ -43,6 +44,10 @@ pub(crate) struct Run {
|
|||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
|
|
||||||
|
/// Ip for the socket (if applicable) to listen for requests.
|
||||||
|
#[clap(long)]
|
||||||
|
host: Option<IpAddr>,
|
||||||
|
|
||||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||||
/// modify config post init
|
/// modify config post init
|
||||||
#[clap(long, hide = true)]
|
#[clap(long, hide = true)]
|
||||||
@@ -64,6 +69,7 @@ impl From<Run> for OverrideConfig {
|
|||||||
nym_apis: run_config.nym_apis,
|
nym_apis: run_config.nym_apis,
|
||||||
disable_socket: run_config.disable_socket,
|
disable_socket: run_config.disable_socket,
|
||||||
port: run_config.port,
|
port: run_config.port,
|
||||||
|
host: run_config.host,
|
||||||
fastmode: run_config.fastmode,
|
fastmode: run_config.fastmode,
|
||||||
no_cover: run_config.no_cover,
|
no_cover: run_config.no_cover,
|
||||||
nyxd_urls: run_config.nyxd_urls,
|
nyxd_urls: run_config.nyxd_urls,
|
||||||
@@ -94,7 +100,7 @@ fn version_check(cfg: &Config) -> bool {
|
|||||||
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let id = &args.id;
|
let id = &args.id;
|
||||||
|
|
||||||
let mut config = match Config::load_from_file(Some(id)) {
|
let mut config = match Config::load_from_file(id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
|
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ pub(crate) fn execute(args: &Upgrade) {
|
|||||||
|
|
||||||
let id = &args.id;
|
let id = &args.id;
|
||||||
|
|
||||||
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
|
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
|
||||||
eprintln!("failed to load existing config file! - {err}");
|
eprintln!("failed to load existing config file! - {err}");
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use super::handler::HandlerBuilder;
|
use super::handler::HandlerBuilder;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use std::net::IpAddr;
|
||||||
use std::{net::SocketAddr, process, sync::Arc};
|
use std::{net::SocketAddr, process, sync::Arc};
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::{sync::Notify, task::JoinHandle};
|
use tokio::{sync::Notify, task::JoinHandle};
|
||||||
@@ -24,10 +25,9 @@ pub(crate) struct Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Listener {
|
impl Listener {
|
||||||
pub(crate) fn new(port: u16) -> Self {
|
pub(crate) fn new(host: IpAddr, port: u16) -> Self {
|
||||||
Listener {
|
Listener {
|
||||||
// unless we find compelling reason not to, just listen on local only
|
address: SocketAddr::new(host, port),
|
||||||
address: SocketAddr::new("127.0.0.1".parse().unwrap(), port),
|
|
||||||
state: State::AwaitingConnection,
|
state: State::AwaitingConnection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
|
|||||||
let id = &args.id;
|
let id = &args.id;
|
||||||
let provider_address = &args.provider;
|
let provider_address = &args.provider;
|
||||||
|
|
||||||
let already_init = Config::default_config_file_path(Some(id)).exists();
|
let already_init = Config::default_config_file_path(id).exists();
|
||||||
if already_init {
|
if already_init {
|
||||||
println!("SOCKS5 client \"{id}\" was already initialised before");
|
println!("SOCKS5 client \"{id}\" was already initialised before");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ fn version_check(cfg: &Config) -> bool {
|
|||||||
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let id = &args.id;
|
let id = &args.id;
|
||||||
|
|
||||||
let mut config = match Config::load_from_file(Some(id)) {
|
let mut config = match Config::load_from_file(id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
|
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ pub(crate) fn execute(args: &Upgrade) {
|
|||||||
|
|
||||||
let id = &args.id;
|
let id = &args.id;
|
||||||
|
|
||||||
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
|
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
|
||||||
eprintln!("failed to load existing config file! - {err}");
|
eprintln!("failed to load existing config file! - {err}");
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
|
||||||
use coconut_bandwidth_contract_common::msg::InstantiateMsg;
|
use coconut_bandwidth_contract_common::msg::InstantiateMsg;
|
||||||
|
use validator_client::nyxd::AccountId;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
@@ -12,7 +15,7 @@ pub struct Args {
|
|||||||
pub pool_addr: String,
|
pub pool_addr: String,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub multisig_addr: Option<String>,
|
pub multisig_addr: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub mix_denom: Option<String>,
|
pub mix_denom: Option<String>,
|
||||||
@@ -24,8 +27,10 @@ pub async fn generate(args: Args) {
|
|||||||
debug!("Received arguments: {:?}", args);
|
debug!("Received arguments: {:?}", args);
|
||||||
|
|
||||||
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
|
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
let address = std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
||||||
.expect("Multisig address has to be set")
|
.expect("Multisig address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting multisig address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let mix_denom = args.mix_denom.unwrap_or_else(|| {
|
let mix_denom = args.mix_denom.unwrap_or_else(|| {
|
||||||
@@ -34,7 +39,7 @@ pub async fn generate(args: Args) {
|
|||||||
|
|
||||||
let instantiate_msg = InstantiateMsg {
|
let instantiate_msg = InstantiateMsg {
|
||||||
pool_addr: args.pool_addr,
|
pool_addr: args.pool_addr,
|
||||||
multisig_addr,
|
multisig_addr: multisig_addr.to_string(),
|
||||||
mix_denom,
|
mix_denom,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use coconut_dkg_common::msg::InstantiateMsg;
|
use coconut_dkg_common::msg::InstantiateMsg;
|
||||||
use coconut_dkg_common::types::TimeConfiguration;
|
use coconut_dkg_common::types::TimeConfiguration;
|
||||||
|
use validator_client::nyxd::AccountId;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
@@ -14,7 +15,7 @@ pub struct Args {
|
|||||||
pub group_addr: String,
|
pub group_addr: String,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub multisig_addr: Option<String>,
|
pub multisig_addr: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub public_key_submission_time_secs: Option<u64>,
|
pub public_key_submission_time_secs: Option<u64>,
|
||||||
@@ -44,8 +45,10 @@ pub async fn generate(args: Args) {
|
|||||||
debug!("Received arguments: {:?}", args);
|
debug!("Received arguments: {:?}", args);
|
||||||
|
|
||||||
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
|
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
let address = std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
||||||
.expect("Multisig address has to be set")
|
.expect("Multisig address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting multisig address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let mix_denom = args.mix_denom.unwrap_or_else(|| {
|
let mix_denom = args.mix_denom.unwrap_or_else(|| {
|
||||||
@@ -86,7 +89,7 @@ pub async fn generate(args: Args) {
|
|||||||
|
|
||||||
let instantiate_msg = InstantiateMsg {
|
let instantiate_msg = InstantiateMsg {
|
||||||
group_addr: args.group_addr,
|
group_addr: args.group_addr,
|
||||||
multisig_addr,
|
multisig_addr: multisig_addr.to_string(),
|
||||||
time_configuration: Some(time_configuration),
|
time_configuration: Some(time_configuration),
|
||||||
mix_denom,
|
mix_denom,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,15 +6,17 @@ use log::{debug, info};
|
|||||||
|
|
||||||
use cosmwasm_std::Decimal;
|
use cosmwasm_std::Decimal;
|
||||||
use mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
|
use mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
|
||||||
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use validator_client::nyxd::AccountId;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub rewarding_validator_address: Option<String>,
|
pub rewarding_validator_address: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub vesting_contract_address: Option<String>,
|
pub vesting_contract_address: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub rewarding_denom: Option<String>,
|
pub rewarding_denom: Option<String>,
|
||||||
@@ -77,13 +79,17 @@ pub async fn generate(args: Args) {
|
|||||||
debug!("initial_rewarding_params: {:?}", initial_rewarding_params);
|
debug!("initial_rewarding_params: {:?}", initial_rewarding_params);
|
||||||
|
|
||||||
let rewarding_validator_address = args.rewarding_validator_address.unwrap_or_else(|| {
|
let rewarding_validator_address = args.rewarding_validator_address.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
let address = std::env::var(network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
||||||
.expect("Rewarding validator address has to be set")
|
.expect("Rewarding validator address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting rewarding validator address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let vesting_contract_address = args.vesting_contract_address.unwrap_or_else(|| {
|
let vesting_contract_address = args.vesting_contract_address.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::VESTING_CONTRACT_ADDRESS)
|
let address = std::env::var(network_defaults::var_names::VESTING_CONTRACT_ADDRESS)
|
||||||
.expect("Vesting contract address has to be set")
|
.expect("Vesting contract address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting vesting contract address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let rewarding_denom = args.rewarding_denom.unwrap_or_else(|| {
|
let rewarding_denom = args.rewarding_denom.unwrap_or_else(|| {
|
||||||
@@ -92,8 +98,8 @@ pub async fn generate(args: Args) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let instantiate_msg = InstantiateMsg {
|
let instantiate_msg = InstantiateMsg {
|
||||||
rewarding_validator_address,
|
rewarding_validator_address: rewarding_validator_address.to_string(),
|
||||||
vesting_contract_address,
|
vesting_contract_address: vesting_contract_address.to_string(),
|
||||||
rewarding_denom,
|
rewarding_denom,
|
||||||
epochs_in_interval: args.epochs_in_interval,
|
epochs_in_interval: args.epochs_in_interval,
|
||||||
epoch_duration: Duration::from_secs(args.epoch_duration),
|
epoch_duration: Duration::from_secs(args.epoch_duration),
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use clap::Parser;
|
use std::str::FromStr;
|
||||||
use log::{debug, info};
|
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
use cosmwasm_std::Decimal;
|
use cosmwasm_std::Decimal;
|
||||||
use cw_utils::{Duration, Threshold};
|
use cw_utils::{Duration, Threshold};
|
||||||
|
use log::{debug, info};
|
||||||
use multisig_contract_common::msg::InstantiateMsg;
|
use multisig_contract_common::msg::InstantiateMsg;
|
||||||
|
use validator_client::nyxd::AccountId;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
@@ -20,10 +22,10 @@ pub struct Args {
|
|||||||
pub max_voting_period: u64,
|
pub max_voting_period: u64,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub coconut_bandwidth_contract_address: Option<String>,
|
pub coconut_bandwidth_contract_address: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub coconut_dkg_contract_address: Option<String>,
|
pub coconut_dkg_contract_address: Option<AccountId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn generate(args: Args) {
|
pub async fn generate(args: Args) {
|
||||||
@@ -33,13 +35,18 @@ pub async fn generate(args: Args) {
|
|||||||
|
|
||||||
let coconut_bandwidth_contract_address =
|
let coconut_bandwidth_contract_address =
|
||||||
args.coconut_bandwidth_contract_address.unwrap_or_else(|| {
|
args.coconut_bandwidth_contract_address.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS)
|
let address =
|
||||||
.expect("Coconut bandwidth contract address has to be set")
|
std::env::var(network_defaults::var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS)
|
||||||
|
.expect("Coconut bandwidth contract address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting bandwidth contract address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let coconut_dkg_contract_address = args.coconut_dkg_contract_address.unwrap_or_else(|| {
|
let coconut_dkg_contract_address = args.coconut_dkg_contract_address.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::COCONUT_DKG_CONTRACT_ADDRESS)
|
let address = std::env::var(network_defaults::var_names::COCONUT_DKG_CONTRACT_ADDRESS)
|
||||||
.expect("Coconut DKG contract address has to be set")
|
.expect("Coconut DKG contract address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting DKG contract address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let instantiate_msg = InstantiateMsg {
|
let instantiate_msg = InstantiateMsg {
|
||||||
@@ -49,8 +56,8 @@ pub async fn generate(args: Args) {
|
|||||||
.expect("threshold can't be converted to Decimal"),
|
.expect("threshold can't be converted to Decimal"),
|
||||||
},
|
},
|
||||||
max_voting_period: Duration::Time(args.max_voting_period),
|
max_voting_period: Duration::Time(args.max_voting_period),
|
||||||
coconut_bandwidth_contract_address,
|
coconut_bandwidth_contract_address: coconut_bandwidth_contract_address.to_string(),
|
||||||
coconut_dkg_contract_address,
|
coconut_dkg_contract_address: coconut_dkg_contract_address.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
|
||||||
|
use validator_client::nyxd::AccountId;
|
||||||
use vesting_contract_common::InitMsg;
|
use vesting_contract_common::InitMsg;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub mixnet_contract_address: Option<String>,
|
pub mixnet_contract_address: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub mix_denom: Option<String>,
|
pub mix_denom: Option<String>,
|
||||||
@@ -21,8 +24,10 @@ pub async fn generate(args: Args) {
|
|||||||
debug!("Received arguments: {:?}", args);
|
debug!("Received arguments: {:?}", args);
|
||||||
|
|
||||||
let mixnet_contract_address = args.mixnet_contract_address.unwrap_or_else(|| {
|
let mixnet_contract_address = args.mixnet_contract_address.unwrap_or_else(|| {
|
||||||
std::env::var(network_defaults::var_names::MIXNET_CONTRACT_ADDRESS)
|
let address = std::env::var(network_defaults::var_names::MIXNET_CONTRACT_ADDRESS)
|
||||||
.expect("Mixnet contract address has to be set")
|
.expect("Mixnet contract address has to be set");
|
||||||
|
AccountId::from_str(address.as_str())
|
||||||
|
.expect("Failed converting mixnet address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let mix_denom = args.mix_denom.unwrap_or_else(|| {
|
let mix_denom = args.mix_denom.unwrap_or_else(|| {
|
||||||
@@ -30,7 +35,7 @@ pub async fn generate(args: Args) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let instantiate_msg = InitMsg {
|
let instantiate_msg = InitMsg {
|
||||||
mixnet_contract_address,
|
mixnet_contract_address: mixnet_contract_address.to_string(),
|
||||||
mix_denom,
|
mix_denom,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+11
-27
@@ -30,23 +30,15 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
|||||||
fn default_root_directory() -> PathBuf;
|
fn default_root_directory() -> PathBuf;
|
||||||
|
|
||||||
// default, most probable, implementations; can be easily overridden where required
|
// default, most probable, implementations; can be easily overridden where required
|
||||||
fn default_config_directory(id: Option<&str>) -> PathBuf {
|
fn default_config_directory(id: &str) -> PathBuf {
|
||||||
if let Some(id) = id {
|
Self::default_root_directory().join(id).join(CONFIG_DIR)
|
||||||
Self::default_root_directory().join(id).join(CONFIG_DIR)
|
|
||||||
} else {
|
|
||||||
Self::default_root_directory().join(CONFIG_DIR)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_data_directory(id: Option<&str>) -> PathBuf {
|
fn default_data_directory(id: &str) -> PathBuf {
|
||||||
if let Some(id) = id {
|
Self::default_root_directory().join(id).join(DATA_DIR)
|
||||||
Self::default_root_directory().join(id).join(DATA_DIR)
|
|
||||||
} else {
|
|
||||||
Self::default_root_directory().join(DATA_DIR)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_config_file_path(id: Option<&str>) -> PathBuf {
|
fn default_config_file_path(id: &str) -> PathBuf {
|
||||||
Self::default_config_directory(id).join(Self::config_file_name())
|
Self::default_config_directory(id).join(Self::config_file_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,23 +46,15 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
|||||||
|
|
||||||
fn try_default_root_directory() -> Option<PathBuf>;
|
fn try_default_root_directory() -> Option<PathBuf>;
|
||||||
|
|
||||||
fn try_default_config_directory(id: Option<&str>) -> Option<PathBuf> {
|
fn try_default_config_directory(id: &str) -> Option<PathBuf> {
|
||||||
if let Some(id) = id {
|
Self::try_default_root_directory().map(|d| d.join(id).join(CONFIG_DIR))
|
||||||
Self::try_default_root_directory().map(|d| d.join(id).join(CONFIG_DIR))
|
|
||||||
} else {
|
|
||||||
Self::try_default_root_directory().map(|d| d.join(CONFIG_DIR))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_default_data_directory(id: Option<&str>) -> Option<PathBuf> {
|
fn try_default_data_directory(id: &str) -> Option<PathBuf> {
|
||||||
if let Some(id) = id {
|
Self::try_default_root_directory().map(|d| d.join(id).join(DATA_DIR))
|
||||||
Self::try_default_root_directory().map(|d| d.join(id).join(DATA_DIR))
|
|
||||||
} else {
|
|
||||||
Self::try_default_root_directory().map(|d| d.join(DATA_DIR))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_default_config_file_path(id: Option<&str>) -> Option<PathBuf> {
|
fn try_default_config_file_path(id: &str) -> Option<PathBuf> {
|
||||||
Self::try_default_config_directory(id).map(|d| d.join(Self::config_file_name()))
|
Self::try_default_config_directory(id).map(|d| d.join(Self::config_file_name()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +97,7 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_from_file(id: Option<&str>) -> io::Result<Self> {
|
fn load_from_file(id: &str) -> io::Result<Self> {
|
||||||
let file = Self::default_config_file_path(id);
|
let file = Self::default_config_file_path(id);
|
||||||
log::trace!("Loading from file: {:#?}", file);
|
log::trace!("Loading from file: {:#?}", file);
|
||||||
let config_contents = fs::read_to_string(file)?;
|
let config_contents = fs::read_to_string(file)?;
|
||||||
|
|||||||
@@ -13,3 +13,4 @@ cw4 = { version = "0.13.4" }
|
|||||||
cosmwasm-std = "1.0.0"
|
cosmwasm-std = "1.0.0"
|
||||||
schemars = "0.8"
|
schemars = "0.8"
|
||||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||||
|
thiserror = { version = "1.0.23" }
|
||||||
|
|||||||
+3
@@ -1,3 +1,6 @@
|
|||||||
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use cosmwasm_std::StdError;
|
use cosmwasm_std::StdError;
|
||||||
use cw_utils::ThresholdError;
|
use cw_utils::ThresholdError;
|
||||||
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
pub mod error;
|
||||||
pub mod msg;
|
pub mod msg;
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use cosmwasm_std::{entry_point, Addr, Coin, DepsMut, Empty, Env, Response};
|
use cosmwasm_std::{entry_point, Addr, Coin, DepsMut, Empty, Env, Response};
|
||||||
use cw3_flex_multisig::{state::CONFIG, ContractError};
|
use cw3_flex_multisig::state::CONFIG;
|
||||||
use cw_multi_test::{App, AppBuilder, Contract, ContractWrapper};
|
use cw_multi_test::{App, AppBuilder, Contract, ContractWrapper};
|
||||||
|
use multisig_contract_common::error::ContractError;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ cw-storage-plus = { version = "0.13.4" }
|
|||||||
cosmwasm-std = { version = "1.0.0" }
|
cosmwasm-std = { version = "1.0.0" }
|
||||||
schemars = "0.8.1"
|
schemars = "0.8.1"
|
||||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||||
thiserror = { version = "1.0.23" }
|
|
||||||
|
|
||||||
group-contract-common = { path = "../../../common/cosmwasm-smart-contracts/group-contract" }
|
group-contract-common = { path = "../../../common/cosmwasm-smart-contracts/group-contract" }
|
||||||
multisig-contract-common = { path= "../../../common/cosmwasm-smart-contracts/multisig-contract" }
|
multisig-contract-common = { path= "../../../common/cosmwasm-smart-contracts/multisig-contract" }
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ use cw4::{Cw4Contract, MemberChangedHookMsg, MemberDiff};
|
|||||||
use cw_storage_plus::Bound;
|
use cw_storage_plus::Bound;
|
||||||
use cw_utils::{maybe_addr, Expiration, ThresholdResponse};
|
use cw_utils::{maybe_addr, Expiration, ThresholdResponse};
|
||||||
|
|
||||||
use crate::error::ContractError;
|
|
||||||
use crate::state::{Config, CONFIG};
|
use crate::state::{Config, CONFIG};
|
||||||
|
use multisig_contract_common::error::ContractError;
|
||||||
use multisig_contract_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
|
use multisig_contract_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
|
||||||
|
|
||||||
// version info for migration info
|
// version info for migration info
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
pub mod contract;
|
pub mod contract;
|
||||||
pub mod error;
|
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|
||||||
pub use crate::error::ContractError;
|
|
||||||
|
|||||||
+4
-4
@@ -12,10 +12,10 @@ DENOMS_EXPONENT=6
|
|||||||
MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g
|
MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g
|
||||||
VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw
|
VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw
|
||||||
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
|
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
|
||||||
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n12ckdkm3q7eytefs7rwu4ue3t9hxgvl9v08jddmtwgct2ve0pv50q0t8dlt
|
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19d2nwj7fdhxqmyvgy8lf3ad49a6vmww4shryhrkj2mqk36att66s6xzszw
|
||||||
GROUP_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m
|
GROUP_CONTRACT_ADDRESS=n1fqquzw4mk0pkamgr2ywt2v7h2j9nuyjjn4gvpy8zlpp6xn0uyuzqfm28l5
|
||||||
MULTISIG_CONTRACT_ADDRESS=n14krxe8ukzagwhvec0rmteexu62w8k9kp9sra9ww6em2hnmzcukqsa0utc8
|
MULTISIG_CONTRACT_ADDRESS=n1gaq3666chd5348apj8cka8t2mckv7azp9espyr7wgpxyuzur5d0sazpysy
|
||||||
COCONUT_DKG_CONTRACT_ADDRESS=n1rl5n6cxuz2hdy3f7d9hsnw8zn0zwwwr0r4dxfz7tktgpgkcnz9zshmvksc
|
COCONUT_DKG_CONTRACT_ADDRESS=n18yadscxw8v35dds7ksv3j0svmjh3h6e7tmxpadk96mvgz27zygkshuf4vs
|
||||||
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
|
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
|
||||||
STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090"
|
STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090"
|
||||||
NYXD="https://qwerty-validator.qa.nymte.ch/"
|
NYXD="https://qwerty-validator.qa.nymte.ch/"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "explorer-api"
|
name = "explorer-api"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
## UNRELEASED
|
## UNRELEASED
|
||||||
|
|
||||||
|
## [nym-explorer-v1.0.4](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.4) (2023-01-31)
|
||||||
|
|
||||||
|
- Add routing score on gateway list ([#2913])
|
||||||
|
- Add gateway's last Routing Score to the gateways list page ([#2186])
|
||||||
|
- Upgrade Sandbox and make below changes: ([#2332])
|
||||||
|
|
||||||
|
[#2913]: https://github.com/nymtech/nym/pull/2913
|
||||||
|
[#2186]: https://github.com/nymtech/nym/issues/2186
|
||||||
|
[#2332]: https://github.com/nymtech/nym/issues/2332
|
||||||
|
|
||||||
## [nym-explorer-v1.0.3](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.3) (2023-01-24)
|
## [nym-explorer-v1.0.3](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.3) (2023-01-24)
|
||||||
|
|
||||||
- Stake Saturation tooltip on node list and node pages updated ([#2877])
|
- Stake Saturation tooltip on node list and node pages updated ([#2877])
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nym/network-explorer",
|
"name": "@nym/network-explorer",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const OVERVIEW_API = `${API_BASE_URL}/overview`;
|
|||||||
export const MIXNODE_PING = `${API_BASE_URL}/ping`;
|
export const MIXNODE_PING = `${API_BASE_URL}/ping`;
|
||||||
export const MIXNODES_API = `${API_BASE_URL}/mix-nodes`;
|
export const MIXNODES_API = `${API_BASE_URL}/mix-nodes`;
|
||||||
export const MIXNODE_API = `${API_BASE_URL}/mix-node`;
|
export const MIXNODE_API = `${API_BASE_URL}/mix-node`;
|
||||||
export const GATEWAYS_API = `${NYM_API_BASE_URL}/api/v1/gateways`;
|
export const GATEWAYS_API = `${NYM_API_BASE_URL}/api/v1/status/gateways/detailed`;
|
||||||
export const VALIDATORS_API = `${VALIDATOR_BASE_URL}/validators`;
|
export const VALIDATORS_API = `${VALIDATOR_BASE_URL}/validators`;
|
||||||
export const BLOCK_API = `${NYM_API_BASE_URL}/block`;
|
export const BLOCK_API = `${NYM_API_BASE_URL}/block`;
|
||||||
export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`;
|
export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
CountryDataResponse,
|
CountryDataResponse,
|
||||||
DelegationsResponse,
|
DelegationsResponse,
|
||||||
UniqDelegationsResponse,
|
UniqDelegationsResponse,
|
||||||
GatewayResponse,
|
|
||||||
GatewayReportResponse,
|
GatewayReportResponse,
|
||||||
UptimeStoryResponse,
|
UptimeStoryResponse,
|
||||||
MixNodeDescriptionResponse,
|
MixNodeDescriptionResponse,
|
||||||
@@ -27,7 +26,10 @@ import {
|
|||||||
StatusResponse,
|
StatusResponse,
|
||||||
SummaryOverviewResponse,
|
SummaryOverviewResponse,
|
||||||
ValidatorsResponse,
|
ValidatorsResponse,
|
||||||
|
GatewayBondAnnotated,
|
||||||
|
GatewayBond,
|
||||||
} from '../typeDefs/explorer-api';
|
} from '../typeDefs/explorer-api';
|
||||||
|
import { toPercentIntegerString } from '../utils';
|
||||||
|
|
||||||
function getFromCache(key: string) {
|
function getFromCache(key: string) {
|
||||||
const ts = Number(localStorage.getItem('ts'));
|
const ts = Number(localStorage.getItem('ts'));
|
||||||
@@ -89,9 +91,13 @@ export class Api {
|
|||||||
return response.json();
|
return response.json();
|
||||||
};
|
};
|
||||||
|
|
||||||
static fetchGateways = async (): Promise<GatewayResponse> => {
|
static fetchGateways = async (): Promise<GatewayBond[]> => {
|
||||||
const res = await fetch(GATEWAYS_API);
|
const res = await fetch(GATEWAYS_API);
|
||||||
return res.json();
|
const gatewaysAnnotated: GatewayBondAnnotated[] = await res.json();
|
||||||
|
return gatewaysAnnotated.map(({ gateway_bond, performance }) => ({
|
||||||
|
...gateway_bond,
|
||||||
|
performance: toPercentIntegerString(performance),
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
static fetchGatewayUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> =>
|
static fetchGatewayUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> =>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GatewayResponse, GatewayResponseItem, GatewayReportResponse } from '../typeDefs/explorer-api';
|
import { GatewayResponse, GatewayBond, GatewayReportResponse } from '../typeDefs/explorer-api';
|
||||||
|
|
||||||
export type GatewayRowType = {
|
export type GatewayRowType = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -8,6 +8,7 @@ export type GatewayRowType = {
|
|||||||
host: string;
|
host: string;
|
||||||
location: string;
|
location: string;
|
||||||
version: string;
|
version: string;
|
||||||
|
performance: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GatewayEnrichedRowType = GatewayRowType & {
|
export type GatewayEnrichedRowType = GatewayRowType & {
|
||||||
@@ -28,13 +29,11 @@ export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowTy
|
|||||||
bond: gw.pledge_amount.amount || 0,
|
bond: gw.pledge_amount.amount || 0,
|
||||||
host: gw.gateway.host || '',
|
host: gw.gateway.host || '',
|
||||||
version: gw.gateway.version || '',
|
version: gw.gateway.version || '',
|
||||||
|
performance: gw.performance,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function gatewayEnrichedToGridRow(
|
export function gatewayEnrichedToGridRow(gateway: GatewayBond, report: GatewayReportResponse): GatewayEnrichedRowType {
|
||||||
gateway: GatewayResponseItem,
|
|
||||||
report: GatewayReportResponse,
|
|
||||||
): GatewayEnrichedRowType {
|
|
||||||
return {
|
return {
|
||||||
id: gateway.owner,
|
id: gateway.owner,
|
||||||
owner: gateway.owner,
|
owner: gateway.owner,
|
||||||
@@ -47,5 +46,6 @@ export function gatewayEnrichedToGridRow(
|
|||||||
mixPort: gateway.gateway.mix_port || 0,
|
mixPort: gateway.gateway.mix_port || 0,
|
||||||
routingScore: `${report.most_recent}%`,
|
routingScore: `${report.most_recent}%`,
|
||||||
avgUptime: `${report.last_day || report.last_hour}%`,
|
avgUptime: `${report.last_day || report.last_hour}%`,
|
||||||
|
performance: gateway.performance,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Alert, AlertTitle, Box, CircularProgress, Grid } from '@mui/material';
|
import { Alert, AlertTitle, Box, CircularProgress, Grid } from '@mui/material';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { GatewayResponseItem } from '../../typeDefs/explorer-api';
|
import { GatewayBond } from '../../typeDefs/explorer-api';
|
||||||
import { ColumnsType, DetailTable } from '../../components/DetailTable';
|
import { ColumnsType, DetailTable } from '../../components/DetailTable';
|
||||||
import { gatewayEnrichedToGridRow, GatewayEnrichedRowType } from '../../components/Gateways';
|
import { gatewayEnrichedToGridRow, GatewayEnrichedRowType } from '../../components/Gateways';
|
||||||
import { ComponentError } from '../../components/ComponentError';
|
import { ComponentError } from '../../components/ComponentError';
|
||||||
@@ -69,7 +69,7 @@ const columns: ColumnsType[] = [
|
|||||||
/**
|
/**
|
||||||
* Shows gateway details
|
* Shows gateway details
|
||||||
*/
|
*/
|
||||||
const PageGatewayDetailsWithState = ({ selectedGateway }: { selectedGateway: GatewayResponseItem | undefined }) => {
|
const PageGatewayDetailsWithState = ({ selectedGateway }: { selectedGateway: GatewayBond | undefined }) => {
|
||||||
const [enrichGateway, setEnrichGateway] = React.useState<GatewayEnrichedRowType>();
|
const [enrichGateway, setEnrichGateway] = React.useState<GatewayEnrichedRowType>();
|
||||||
const [status, setStatus] = React.useState<number[] | undefined>();
|
const [status, setStatus] = React.useState<number[] | undefined>();
|
||||||
const { uptimeReport, uptimeStory } = useGatewayContext();
|
const { uptimeReport, uptimeStory } = useGatewayContext();
|
||||||
@@ -130,7 +130,7 @@ const PageGatewayDetailsWithState = ({ selectedGateway }: { selectedGateway: Gat
|
|||||||
* Guard component to handle loading and not found states
|
* Guard component to handle loading and not found states
|
||||||
*/
|
*/
|
||||||
const PageGatewayDetailGuard: FCWithChildren = () => {
|
const PageGatewayDetailGuard: FCWithChildren = () => {
|
||||||
const [selectedGateway, setSelectedGateway] = React.useState<GatewayResponseItem | undefined>();
|
const [selectedGateway, setSelectedGateway] = React.useState<GatewayBond | undefined>();
|
||||||
const { gateways } = useMainContext();
|
const { gateways } = useMainContext();
|
||||||
const { id } = useParams<{ id: string | undefined }>();
|
const { id } = useParams<{ id: string | undefined }>();
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,24 @@ export const PageGateways: FCWithChildren = () => {
|
|||||||
</MuiLink>
|
</MuiLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'performance',
|
||||||
|
headerName: 'Routing Score',
|
||||||
|
renderHeader: () => <CustomColumnHeading headingTitle="Routing Score" />,
|
||||||
|
width: 150,
|
||||||
|
headerAlign: 'left',
|
||||||
|
headerClassName: 'MuiDataGrid-header-override',
|
||||||
|
renderCell: (params: GridRenderCellParams) => (
|
||||||
|
<MuiLink
|
||||||
|
sx={{ ...cellStyles }}
|
||||||
|
component={RRDLink}
|
||||||
|
to={`/network-components/gateway/${params.row.identityKey}`}
|
||||||
|
data-testid="pledge-amount"
|
||||||
|
>
|
||||||
|
{`${params.value}%`}
|
||||||
|
</MuiLink>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'host',
|
field: 'host',
|
||||||
renderHeader: () => <CustomColumnHeading headingTitle="IP:Port" />,
|
renderHeader: () => <CustomColumnHeading headingTitle="IP:Port" />,
|
||||||
|
|||||||
@@ -116,15 +116,21 @@ export interface StatsResponse {
|
|||||||
|
|
||||||
export type MixNodeHistoryResponse = StatsResponse;
|
export type MixNodeHistoryResponse = StatsResponse;
|
||||||
|
|
||||||
export interface GatewayResponseItem {
|
export interface GatewayBond {
|
||||||
block_height: number;
|
block_height: number;
|
||||||
pledge_amount: Amount;
|
pledge_amount: Amount;
|
||||||
total_delegation: Amount;
|
total_delegation: Amount;
|
||||||
owner: string;
|
owner: string;
|
||||||
gateway: Gateway;
|
gateway: Gateway;
|
||||||
|
performance: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GatewayResponse = GatewayResponseItem[];
|
export interface GatewayBondAnnotated {
|
||||||
|
gateway_bond: GatewayBond;
|
||||||
|
performance: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GatewayResponse = GatewayBond[];
|
||||||
|
|
||||||
export interface GatewayReportResponse {
|
export interface GatewayReportResponse {
|
||||||
identity: string;
|
identity: string;
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "nym-gateway"
|
name = "nym-gateway"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
authors = [
|
authors = [
|
||||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ impl From<Init> for OverrideConfig {
|
|||||||
pub async fn execute(args: Init, output: OutputFormat) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub async fn execute(args: Init, output: OutputFormat) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
println!("Initialising gateway {}...", args.id);
|
println!("Initialising gateway {}...", args.id);
|
||||||
|
|
||||||
let already_init = if Config::default_config_file_path(Some(&args.id)).exists() {
|
let already_init = if Config::default_config_file_path(&args.id).exists() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Gateway \"{}\" was already initialised before! Config information will be \
|
"Gateway \"{}\" was already initialised before! Config information will be \
|
||||||
overwritten (but keys will be kept)!",
|
overwritten (but keys will be kept)!",
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ fn do_upgrade(mut config: Config, args: &Upgrade, package_version: Version) {
|
|||||||
pub async fn execute(args: &Upgrade) {
|
pub async fn execute(args: &Upgrade) {
|
||||||
let package_version = parse_package_version();
|
let package_version = parse_package_version();
|
||||||
|
|
||||||
let existing_config = Config::load_from_file(Some(&args.id)).unwrap_or_else(|err| {
|
let existing_config = Config::load_from_file(&args.id).unwrap_or_else(|err| {
|
||||||
eprintln!("failed to load existing config file! - {err}");
|
eprintln!("failed to load existing config file! - {err}");
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -374,23 +374,23 @@ pub struct Gateway {
|
|||||||
|
|
||||||
impl Gateway {
|
impl Gateway {
|
||||||
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
|
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("private_sphinx.pem")
|
Config::default_data_directory(id).join("private_sphinx.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_public_sphinx_key_file(id: &str) -> PathBuf {
|
fn default_public_sphinx_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("public_sphinx.pem")
|
Config::default_data_directory(id).join("public_sphinx.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("private_identity.pem")
|
Config::default_data_directory(id).join("private_identity.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("public_identity.pem")
|
Config::default_data_directory(id).join("public_identity.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_database_path(id: &str) -> PathBuf {
|
fn default_database_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("db.sqlite")
|
Config::default_data_directory(id).join("db.sqlite")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ pub(crate) fn build_config<O: Into<OverrideConfig>>(
|
|||||||
id: String,
|
id: String,
|
||||||
override_args: O,
|
override_args: O,
|
||||||
) -> Result<Config, GatewayError> {
|
) -> Result<Config, GatewayError> {
|
||||||
let config = match Config::load_from_file(Some(&id)) {
|
let config = match Config::load_from_file(&id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(
|
error!(
|
||||||
"Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})",
|
"Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})",
|
||||||
);
|
);
|
||||||
return Err(GatewayError::ConfigLoadFailure {
|
return Err(GatewayError::ConfigLoadFailure {
|
||||||
path: Config::default_config_file_path(Some(&id)),
|
path: Config::default_config_file_path(&id),
|
||||||
id,
|
id,
|
||||||
source: err,
|
source: err,
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "nym-mixnode"
|
name = "nym-mixnode"
|
||||||
version = "1.1.8"
|
version = "1.1.9"
|
||||||
authors = [
|
authors = [
|
||||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ fn read_user_input() -> String {
|
|||||||
|
|
||||||
pub(crate) fn execute(args: Describe) {
|
pub(crate) fn execute(args: Describe) {
|
||||||
// ensure that the mixnode has in fact been initialized
|
// ensure that the mixnode has in fact been initialized
|
||||||
match Config::load_from_file(Some(&args.id)) {
|
match Config::load_from_file(&args.id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", &args.id);
|
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", &args.id);
|
||||||
@@ -83,7 +83,7 @@ pub(crate) fn execute(args: Describe) {
|
|||||||
// save the struct
|
// save the struct
|
||||||
NodeDescription::save_to_file(
|
NodeDescription::save_to_file(
|
||||||
&node_description,
|
&node_description,
|
||||||
Config::default_config_directory(Some(&args.id)),
|
Config::default_config_directory(&args.id),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ pub(crate) fn execute(args: &Init, output: OutputFormat) {
|
|||||||
let id = &override_config_fields.id;
|
let id = &override_config_fields.id;
|
||||||
eprintln!("Initialising mixnode {id}...");
|
eprintln!("Initialising mixnode {id}...");
|
||||||
|
|
||||||
let already_init = if Config::default_config_file_path(Some(id)).exists() {
|
let already_init = if Config::default_config_file_path(id).exists() {
|
||||||
eprintln!("Mixnode \"{id}\" was already initialised before! Config information will be overwritten (but keys will be kept)!");
|
eprintln!("Mixnode \"{id}\" was already initialised before! Config information will be overwritten (but keys will be kept)!");
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ pub(crate) struct NodeDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn execute(args: &NodeDetails, output: OutputFormat) {
|
pub(crate) fn execute(args: &NodeDetails, output: OutputFormat) {
|
||||||
let config = match Config::load_from_file(Some(&args.id)) {
|
let config = match Config::load_from_file(&args.id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(
|
error!(
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ fn special_addresses() -> Vec<&'static str> {
|
|||||||
pub(crate) async fn execute(args: &Run, output: OutputFormat) {
|
pub(crate) async fn execute(args: &Run, output: OutputFormat) {
|
||||||
eprintln!("Starting mixnode {}...", args.id);
|
eprintln!("Starting mixnode {}...", args.id);
|
||||||
|
|
||||||
let mut config = match Config::load_from_file(Some(&args.id)) {
|
let mut config = match Config::load_from_file(&args.id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(
|
error!(
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn execute(args: &Sign) {
|
pub(crate) fn execute(args: &Sign) {
|
||||||
let config = match Config::load_from_file(Some(&args.id)) {
|
let config = match Config::load_from_file(&args.id) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(
|
error!(
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ fn do_upgrade(mut config: Config, args: &Upgrade, package_version: Version) {
|
|||||||
pub(crate) fn execute(args: &Upgrade) {
|
pub(crate) fn execute(args: &Upgrade) {
|
||||||
let package_version = parse_package_version();
|
let package_version = parse_package_version();
|
||||||
|
|
||||||
let existing_config = Config::load_from_file(Some(&args.id)).unwrap_or_else(|err| {
|
let existing_config = Config::load_from_file(&args.id).unwrap_or_else(|err| {
|
||||||
eprintln!("failed to load existing config file! - {err}");
|
eprintln!("failed to load existing config file! - {err}");
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -376,19 +376,19 @@ struct MixNode {
|
|||||||
|
|
||||||
impl MixNode {
|
impl MixNode {
|
||||||
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("private_identity.pem")
|
Config::default_data_directory(id).join("private_identity.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("public_identity.pem")
|
Config::default_data_directory(id).join("public_identity.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
|
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("private_sphinx.pem")
|
Config::default_data_directory(id).join("private_sphinx.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_public_sphinx_key_file(id: &str) -> PathBuf {
|
fn default_public_sphinx_key_file(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(Some(id)).join("public_sphinx.pem")
|
Config::default_data_directory(id).join("public_sphinx.pem")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ impl MixNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_node_description(config: &Config) -> NodeDescription {
|
fn load_node_description(config: &Config) -> NodeDescription {
|
||||||
NodeDescription::load_from_file(Config::default_config_directory(Some(&config.get_id())))
|
NodeDescription::load_from_file(Config::default_config_directory(&config.get_id()))
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "nym-api"
|
name = "nym-api"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
authors = [
|
authors = [
|
||||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ pub struct GatewayUptimeHistoryResponse {
|
|||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||||
pub struct CirculatingSupplyResponse {
|
pub struct CirculatingSupplyResponse {
|
||||||
pub initial_supply: Coin,
|
pub total_supply: Coin,
|
||||||
pub mixmining_reserve: Coin,
|
pub mixmining_reserve: Coin,
|
||||||
pub vesting_tokens: Coin,
|
pub vesting_tokens: Coin,
|
||||||
pub circulating_supply: Coin,
|
pub circulating_supply: Coin,
|
||||||
|
|||||||
+3
-3
@@ -7,7 +7,7 @@ use validator_client::nyxd::Coin;
|
|||||||
|
|
||||||
pub(crate) struct CirculatingSupplyCacheData {
|
pub(crate) struct CirculatingSupplyCacheData {
|
||||||
// no need to cache that one as it's constant, but let's put it here for consistency sake
|
// no need to cache that one as it's constant, but let's put it here for consistency sake
|
||||||
pub(crate) initial_supply: Coin,
|
pub(crate) total_supply: Coin,
|
||||||
pub(crate) mixmining_reserve: Cache<Coin>,
|
pub(crate) mixmining_reserve: Cache<Coin>,
|
||||||
pub(crate) vesting_tokens: Cache<Coin>,
|
pub(crate) vesting_tokens: Cache<Coin>,
|
||||||
pub(crate) circulating_supply: Cache<Coin>,
|
pub(crate) circulating_supply: Cache<Coin>,
|
||||||
@@ -18,7 +18,7 @@ impl CirculatingSupplyCacheData {
|
|||||||
let zero_coin = Coin::new(0, &mix_denom);
|
let zero_coin = Coin::new(0, &mix_denom);
|
||||||
|
|
||||||
CirculatingSupplyCacheData {
|
CirculatingSupplyCacheData {
|
||||||
initial_supply: Coin::new(1_000_000_000_000_000, mix_denom),
|
total_supply: Coin::new(1_000_000_000_000_000, mix_denom),
|
||||||
mixmining_reserve: Cache::new(zero_coin.clone()),
|
mixmining_reserve: Cache::new(zero_coin.clone()),
|
||||||
vesting_tokens: Cache::new(zero_coin.clone()),
|
vesting_tokens: Cache::new(zero_coin.clone()),
|
||||||
circulating_supply: Cache::new(zero_coin),
|
circulating_supply: Cache::new(zero_coin),
|
||||||
@@ -29,7 +29,7 @@ impl CirculatingSupplyCacheData {
|
|||||||
impl<'a> From<&'a CirculatingSupplyCacheData> for CirculatingSupplyResponse {
|
impl<'a> From<&'a CirculatingSupplyCacheData> for CirculatingSupplyResponse {
|
||||||
fn from(value: &'a CirculatingSupplyCacheData) -> Self {
|
fn from(value: &'a CirculatingSupplyCacheData) -> Self {
|
||||||
CirculatingSupplyResponse {
|
CirculatingSupplyResponse {
|
||||||
initial_supply: value.initial_supply.clone().into(),
|
total_supply: value.total_supply.clone().into(),
|
||||||
mixmining_reserve: value.mixmining_reserve.clone().into_inner().into(),
|
mixmining_reserve: value.mixmining_reserve.clone().into_inner().into(),
|
||||||
vesting_tokens: value.vesting_tokens.clone().into_inner().into(),
|
vesting_tokens: value.vesting_tokens.clone().into_inner().into(),
|
||||||
circulating_supply: value.circulating_supply.clone().into_inner().into(),
|
circulating_supply: value.circulating_supply.clone().into_inner().into(),
|
||||||
|
|||||||
+1
-1
@@ -76,7 +76,7 @@ impl CirculatingSupplyCache {
|
|||||||
pub(crate) async fn update(&self, mixmining_reserve: Coin, vesting_tokens: Coin) {
|
pub(crate) async fn update(&self, mixmining_reserve: Coin, vesting_tokens: Coin) {
|
||||||
let mut cache = self.data.write().await;
|
let mut cache = self.data.write().await;
|
||||||
|
|
||||||
let mut circulating_supply = cache.initial_supply.clone();
|
let mut circulating_supply = cache.total_supply.clone();
|
||||||
circulating_supply.amount -= mixmining_reserve.amount;
|
circulating_supply.amount -= mixmining_reserve.amount;
|
||||||
circulating_supply.amount -= vesting_tokens.amount;
|
circulating_supply.amount -= vesting_tokens.amount;
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub(crate) mod tests {
|
|||||||
use coconut_dkg_common::dealer::DealerDetails;
|
use coconut_dkg_common::dealer::DealerDetails;
|
||||||
use cosmwasm_std::Addr;
|
use cosmwasm_std::Addr;
|
||||||
use dkg::bte::keys::KeyPair as DkgKeyPair;
|
use dkg::bte::keys::KeyPair as DkgKeyPair;
|
||||||
use dkg::bte::Params;
|
use dkg::bte::{Params, PublicKeyWithProof};
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -186,8 +186,18 @@ pub(crate) mod tests {
|
|||||||
let mut bytes = bs58::decode(details.bte_public_key_with_proof.clone())
|
let mut bytes = bs58::decode(details.bte_public_key_with_proof.clone())
|
||||||
.into_vec()
|
.into_vec()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let last_byte = bytes.last_mut().unwrap();
|
// Find another value for last byte that still deserializes to a public key with proof
|
||||||
*last_byte += 1;
|
let initial_byte = *bytes.last_mut().unwrap();
|
||||||
|
loop {
|
||||||
|
let last_byte = bytes.last_mut().unwrap();
|
||||||
|
let (ret, _) = last_byte.overflowing_add(1);
|
||||||
|
*last_byte = ret;
|
||||||
|
// stop when we find that value, or if we do a full round trip of u8 values
|
||||||
|
// and can't find one, in which case this test is invalid
|
||||||
|
if PublicKeyWithProof::try_from_bytes(&bytes).is_ok() || ret == initial_byte {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
details.bte_public_key_with_proof = bs58::encode(&bytes).into_string();
|
details.bte_public_key_with_proof = bs58::encode(&bytes).into_string();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::coconut::dkg::client::DkgClient;
|
|||||||
use crate::coconut::dkg::complaints::ComplaintReason;
|
use crate::coconut::dkg::complaints::ComplaintReason;
|
||||||
use crate::coconut::dkg::state::{ConsistentState, State};
|
use crate::coconut::dkg::state::{ConsistentState, State};
|
||||||
use crate::coconut::error::CoconutError;
|
use crate::coconut::error::CoconutError;
|
||||||
|
use crate::coconut::helpers::accepted_vote_err;
|
||||||
use coconut_dkg_common::event_attributes::DKG_PROPOSAL_ID;
|
use coconut_dkg_common::event_attributes::DKG_PROPOSAL_ID;
|
||||||
use coconut_dkg_common::types::{NodeIndex, TOTAL_DEALINGS};
|
use coconut_dkg_common::types::{NodeIndex, TOTAL_DEALINGS};
|
||||||
use coconut_dkg_common::verification_key::owner_from_cosmos_msgs;
|
use coconut_dkg_common::verification_key::owner_from_cosmos_msgs;
|
||||||
@@ -203,21 +204,23 @@ pub(crate) async fn verification_key_validation(
|
|||||||
.iter()
|
.iter()
|
||||||
.position(|node_index| contract_share.node_index == *node_index)
|
.position(|node_index| contract_share.node_index == *node_index)
|
||||||
{
|
{
|
||||||
if !check_vk_pairing(¶ms, &recovered_partials[idx], &vk) {
|
let ret = if !check_vk_pairing(¶ms, &recovered_partials[idx], &vk) {
|
||||||
dkg_client
|
dkg_client
|
||||||
.vote_verification_key_share(proposal_id, false)
|
.vote_verification_key_share(proposal_id, false)
|
||||||
.await?;
|
.await
|
||||||
} else {
|
} else {
|
||||||
dkg_client
|
dkg_client
|
||||||
.vote_verification_key_share(proposal_id, true)
|
.vote_verification_key_share(proposal_id, true)
|
||||||
.await?;
|
.await
|
||||||
}
|
};
|
||||||
|
accepted_vote_err(ret)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
dkg_client
|
let ret = dkg_client
|
||||||
.vote_verification_key_share(proposal_id, false)
|
.vote_verification_key_share(proposal_id, false)
|
||||||
.await?
|
.await;
|
||||||
|
accepted_vote_err(ret)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::coconut::error::CoconutError;
|
||||||
|
use validator_client::nyxd::error::NyxdError::AbciError;
|
||||||
|
|
||||||
|
// If the result is already established, the vote might be redundant and
|
||||||
|
// thus the transaction might fail
|
||||||
|
pub(crate) fn accepted_vote_err(ret: Result<(), CoconutError>) -> Result<(), CoconutError> {
|
||||||
|
if let Err(CoconutError::NyxdError(AbciError { ref log, .. })) = ret {
|
||||||
|
let accepted_err = multisig_contract_common::error::ContractError::NotOpen {}.to_string();
|
||||||
|
// If redundant voting is not the case, error out on all other error variants
|
||||||
|
if !log.value().contains(&accepted_err) {
|
||||||
|
ret?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ use self::comm::APICommunicationChannel;
|
|||||||
use crate::coconut::client::Client as LocalClient;
|
use crate::coconut::client::Client as LocalClient;
|
||||||
use crate::coconut::deposit::extract_encryption_key;
|
use crate::coconut::deposit::extract_encryption_key;
|
||||||
use crate::coconut::error::{CoconutError, Result};
|
use crate::coconut::error::{CoconutError, Result};
|
||||||
|
use crate::coconut::helpers::accepted_vote_err;
|
||||||
use crate::support::storage::NymApiStorage;
|
use crate::support::storage::NymApiStorage;
|
||||||
use coconut_bandwidth_contract_common::spend_credential::{
|
use coconut_bandwidth_contract_common::spend_credential::{
|
||||||
funds_from_cosmos_msgs, SpendCredentialStatus,
|
funds_from_cosmos_msgs, SpendCredentialStatus,
|
||||||
@@ -40,6 +41,7 @@ pub(crate) mod comm;
|
|||||||
mod deposit;
|
mod deposit;
|
||||||
pub(crate) mod dkg;
|
pub(crate) mod dkg;
|
||||||
pub(crate) mod error;
|
pub(crate) mod error;
|
||||||
|
pub(crate) mod helpers;
|
||||||
pub(crate) mod keypair;
|
pub(crate) mod keypair;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod tests;
|
pub(crate) mod tests;
|
||||||
@@ -301,7 +303,7 @@ pub async fn verify_bandwidth_credential(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Vote yes or no on the proposal based on the verification result
|
// Vote yes or no on the proposal based on the verification result
|
||||||
state
|
let ret = state
|
||||||
.client
|
.client
|
||||||
.vote_proposal(
|
.vote_proposal(
|
||||||
proposal_id,
|
proposal_id,
|
||||||
@@ -312,7 +314,8 @@ pub async fn verify_bandwidth_credential(
|
|||||||
Some(verify_credential_body.gateway_cosmos_addr().to_owned()),
|
Some(verify_credential_body.gateway_cosmos_addr().to_owned()),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.await?;
|
.await;
|
||||||
|
accepted_vote_err(ret)?;
|
||||||
|
|
||||||
Ok(Json(VerifyCredentialResponse::new(vote_yes)))
|
Ok(Json(VerifyCredentialResponse::new(vote_yes)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ pub(crate) struct CliArgs {
|
|||||||
|
|
||||||
/// Id of the nym-api we want to run
|
/// Id of the nym-api we want to run
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub(crate) id: Option<String>,
|
pub(crate) id: String,
|
||||||
|
|
||||||
/// Specifies whether network monitoring is enabled on this API
|
/// Specifies whether network monitoring is enabled on this API
|
||||||
#[clap(short = 'm', long)]
|
#[clap(short = 'm', long)]
|
||||||
@@ -102,12 +102,13 @@ pub(crate) struct CliArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_config(args: CliArgs) -> Result<Config> {
|
pub(crate) fn build_config(args: CliArgs) -> Result<Config> {
|
||||||
|
let id = args.id.clone();
|
||||||
|
|
||||||
// try to load config from the file, if it doesn't exist, use default values
|
// try to load config from the file, if it doesn't exist, use default values
|
||||||
let id = args.id.as_deref();
|
let (config_from_file, already_initialized) = match Config::load_from_file(&id) {
|
||||||
let (config_from_file, _already_initialized) = match Config::load_from_file(id) {
|
|
||||||
Ok(cfg) => (cfg, true),
|
Ok(cfg) => (cfg, true),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let config_path = Config::default_config_file_path(id)
|
let config_path = Config::default_config_file_path(&id)
|
||||||
.into_os_string()
|
.into_os_string()
|
||||||
.into_string()
|
.into_string()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -121,23 +122,20 @@ pub(crate) fn build_config(args: CliArgs) -> Result<Config> {
|
|||||||
|
|
||||||
let config = override_config(config_from_file, args);
|
let config = override_config(config_from_file, args);
|
||||||
|
|
||||||
if !_already_initialized {
|
if !already_initialized {
|
||||||
|
fs::create_dir_all(Config::default_config_directory(&id))
|
||||||
|
.expect("Could not create config directory");
|
||||||
|
fs::create_dir_all(Config::default_data_directory(&id))
|
||||||
|
.expect("Could not create data directory");
|
||||||
crate::coconut::dkg::controller::init_keypair(&config)?;
|
crate::coconut::dkg::controller::init_keypair(&config)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn override_config(mut config: Config, args: CliArgs) -> Config {
|
pub(crate) fn override_config(config: Config, args: CliArgs) -> Config {
|
||||||
if let Some(id) = args.id {
|
|
||||||
fs::create_dir_all(Config::default_config_directory(Some(&id)))
|
|
||||||
.expect("Could not create config directory");
|
|
||||||
fs::create_dir_all(Config::default_data_directory(Some(&id)))
|
|
||||||
.expect("Could not create data directory");
|
|
||||||
config = config.with_id(&id);
|
|
||||||
}
|
|
||||||
|
|
||||||
config
|
config
|
||||||
|
.with_id(&args.id)
|
||||||
.with_optional(Config::with_custom_nyxd_validator, args.nyxd_validator)
|
.with_optional(Config::with_custom_nyxd_validator, args.nyxd_validator)
|
||||||
.with_optional_env(
|
.with_optional_env(
|
||||||
Config::with_custom_mixnet_contract,
|
Config::with_custom_mixnet_contract,
|
||||||
|
|||||||
@@ -201,8 +201,8 @@ pub struct NetworkMonitor {
|
|||||||
impl NetworkMonitor {
|
impl NetworkMonitor {
|
||||||
pub const DB_FILE: &'static str = "credentials_database.db";
|
pub const DB_FILE: &'static str = "credentials_database.db";
|
||||||
|
|
||||||
fn default_credentials_database_path() -> PathBuf {
|
fn default_credentials_database_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::DB_FILE)
|
Config::default_data_directory(id).join(Self::DB_FILE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ impl Default for NetworkMonitor {
|
|||||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||||
gateway_connection_timeout: DEFAULT_GATEWAY_CONNECTION_TIMEOUT,
|
gateway_connection_timeout: DEFAULT_GATEWAY_CONNECTION_TIMEOUT,
|
||||||
packet_delivery_timeout: DEFAULT_PACKET_DELIVERY_TIMEOUT,
|
packet_delivery_timeout: DEFAULT_PACKET_DELIVERY_TIMEOUT,
|
||||||
credentials_database_path: Self::default_credentials_database_path(),
|
credentials_database_path: Default::default(),
|
||||||
test_routes: DEFAULT_TEST_ROUTES,
|
test_routes: DEFAULT_TEST_ROUTES,
|
||||||
minimum_test_routes: DEFAULT_MINIMUM_TEST_ROUTES,
|
minimum_test_routes: DEFAULT_MINIMUM_TEST_ROUTES,
|
||||||
route_test_packets: DEFAULT_ROUTE_TEST_PACKETS,
|
route_test_packets: DEFAULT_ROUTE_TEST_PACKETS,
|
||||||
@@ -242,15 +242,15 @@ pub struct NodeStatusAPI {
|
|||||||
impl NodeStatusAPI {
|
impl NodeStatusAPI {
|
||||||
pub const DB_FILE: &'static str = "db.sqlite";
|
pub const DB_FILE: &'static str = "db.sqlite";
|
||||||
|
|
||||||
fn default_database_path() -> PathBuf {
|
fn default_database_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::DB_FILE)
|
Config::default_data_directory(id).join(Self::DB_FILE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NodeStatusAPI {
|
impl Default for NodeStatusAPI {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
NodeStatusAPI {
|
NodeStatusAPI {
|
||||||
database_path: Self::default_database_path(),
|
database_path: Default::default(),
|
||||||
caching_interval: DEFAULT_NODE_STATUS_CACHE_INTERVAL,
|
caching_interval: DEFAULT_NODE_STATUS_CACHE_INTERVAL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,24 +342,24 @@ impl CoconutSigner {
|
|||||||
pub const COCONUT_VERIFICATION_KEY_FILE: &'static str = "coconut_verification_key.pem";
|
pub const COCONUT_VERIFICATION_KEY_FILE: &'static str = "coconut_verification_key.pem";
|
||||||
pub const COCONUT_SECRET_KEY_FILE: &'static str = "coconut_secret_key.pem";
|
pub const COCONUT_SECRET_KEY_FILE: &'static str = "coconut_secret_key.pem";
|
||||||
|
|
||||||
fn default_coconut_verification_key_path() -> PathBuf {
|
fn default_coconut_verification_key_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::COCONUT_VERIFICATION_KEY_FILE)
|
Config::default_data_directory(id).join(Self::COCONUT_VERIFICATION_KEY_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_coconut_secret_key_path() -> PathBuf {
|
fn default_coconut_secret_key_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::COCONUT_SECRET_KEY_FILE)
|
Config::default_data_directory(id).join(Self::COCONUT_SECRET_KEY_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_dkg_persistent_state_path() -> PathBuf {
|
fn default_dkg_persistent_state_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::DKG_PERSISTENT_STATE_FILE)
|
Config::default_data_directory(id).join(Self::DKG_PERSISTENT_STATE_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_dkg_decryption_key_path() -> PathBuf {
|
fn default_dkg_decryption_key_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::DKG_DECRYPTION_KEY_FILE)
|
Config::default_data_directory(id).join(Self::DKG_DECRYPTION_KEY_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_dkg_public_key_with_proof_path() -> PathBuf {
|
fn default_dkg_public_key_with_proof_path(id: &str) -> PathBuf {
|
||||||
Config::default_data_directory(None).join(Self::DKG_PUBLIC_KEY_WITH_PROOF_FILE)
|
Config::default_data_directory(id).join(Self::DKG_PUBLIC_KEY_WITH_PROOF_FILE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,11 +367,11 @@ impl Default for CoconutSigner {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
enabled: Default::default(),
|
enabled: Default::default(),
|
||||||
dkg_persistent_state_path: CoconutSigner::default_dkg_persistent_state_path(),
|
dkg_persistent_state_path: Default::default(),
|
||||||
verification_key_path: CoconutSigner::default_coconut_verification_key_path(),
|
verification_key_path: Default::default(),
|
||||||
secret_key_path: CoconutSigner::default_coconut_secret_key_path(),
|
secret_key_path: Default::default(),
|
||||||
decryption_key_path: CoconutSigner::default_dkg_decryption_key_path(),
|
decryption_key_path: Default::default(),
|
||||||
public_key_with_proof_path: CoconutSigner::default_dkg_public_key_with_proof_path(),
|
public_key_with_proof_path: Default::default(),
|
||||||
dkg_contract_polling_rate: DEFAULT_DKG_CONTRACT_POLLING_RATE,
|
dkg_contract_polling_rate: DEFAULT_DKG_CONTRACT_POLLING_RATE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,20 +384,18 @@ impl Config {
|
|||||||
|
|
||||||
pub fn with_id(mut self, id: &str) -> Self {
|
pub fn with_id(mut self, id: &str) -> Self {
|
||||||
self.base.id = id.to_string();
|
self.base.id = id.to_string();
|
||||||
self.node_status_api.database_path =
|
self.node_status_api.database_path = NodeStatusAPI::default_database_path(id);
|
||||||
Config::default_data_directory(Some(id)).join(NodeStatusAPI::DB_FILE);
|
|
||||||
self.network_monitor.credentials_database_path =
|
self.network_monitor.credentials_database_path =
|
||||||
Config::default_data_directory(Some(id)).join(NetworkMonitor::DB_FILE);
|
NetworkMonitor::default_credentials_database_path(id);
|
||||||
self.coconut_signer.dkg_persistent_state_path =
|
self.coconut_signer.dkg_persistent_state_path =
|
||||||
Config::default_data_directory(Some(id)).join(CoconutSigner::DKG_PERSISTENT_STATE_FILE);
|
CoconutSigner::default_dkg_persistent_state_path(id);
|
||||||
self.coconut_signer.verification_key_path = Config::default_data_directory(Some(id))
|
self.coconut_signer.verification_key_path =
|
||||||
.join(CoconutSigner::COCONUT_VERIFICATION_KEY_FILE);
|
CoconutSigner::default_coconut_verification_key_path(id);
|
||||||
self.coconut_signer.secret_key_path =
|
self.coconut_signer.secret_key_path = CoconutSigner::default_coconut_secret_key_path(id);
|
||||||
Config::default_data_directory(Some(id)).join(CoconutSigner::COCONUT_SECRET_KEY_FILE);
|
|
||||||
self.coconut_signer.decryption_key_path =
|
self.coconut_signer.decryption_key_path =
|
||||||
Config::default_data_directory(Some(id)).join(CoconutSigner::DKG_DECRYPTION_KEY_FILE);
|
CoconutSigner::default_dkg_decryption_key_path(id);
|
||||||
self.coconut_signer.public_key_with_proof_path = Config::default_data_directory(Some(id))
|
self.coconut_signer.public_key_with_proof_path =
|
||||||
.join(CoconutSigner::DKG_PUBLIC_KEY_WITH_PROOF_FILE);
|
CoconutSigner::default_dkg_public_key_with_proof_path(id);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+783
File diff suppressed because one or more lines are too long
@@ -12,12 +12,22 @@ describe("Get circulating supply", (): void => {
|
|||||||
it("Get circulating supply amounts", async (): Promise<void> => {
|
it("Get circulating supply amounts", async (): Promise<void> => {
|
||||||
const response = await contract.getCirculatingSupply();
|
const response = await contract.getCirculatingSupply();
|
||||||
|
|
||||||
let initial: number = +response.initial_supply.amount;
|
const initial: number = +response.total_supply.amount;
|
||||||
let mixmining: number = +response.mixmining_reserve.amount;
|
const mixmining: number = +response.mixmining_reserve.amount;
|
||||||
let vest: number = +response.vesting_tokens.amount;
|
const vest: number = +response.vesting_tokens.amount;
|
||||||
let circsupply: number = +response.circulating_supply.amount;
|
const circsupply: number = +response.circulating_supply.amount;
|
||||||
|
|
||||||
expect(typeof response.vesting_tokens.amount).toBe("string");
|
expect(typeof response.vesting_tokens.amount).toBe("string");
|
||||||
expect(initial - mixmining - vest).toStrictEqual(circsupply);
|
expect(initial - mixmining - vest).toStrictEqual(circsupply);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Get total supply value", async (): Promise<void> => {
|
||||||
|
const response = await contract.getTotalSupplyValue();
|
||||||
|
expect(typeof response).toBe("number");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Get circulating supply value", async (): Promise<void> => {
|
||||||
|
const response = await contract.getCirculatingSupplyValue();
|
||||||
|
expect(typeof response).toBe("number");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
+127
-57
@@ -17,8 +17,12 @@ describe("Get mixnode data", (): void => {
|
|||||||
//bond information overview
|
//bond information overview
|
||||||
expect(typeof mixnode.bond_information.mix_id).toBe("number");
|
expect(typeof mixnode.bond_information.mix_id).toBe("number");
|
||||||
expect(typeof mixnode.bond_information.owner).toBe("string");
|
expect(typeof mixnode.bond_information.owner).toBe("string");
|
||||||
expect(typeof mixnode.bond_information.original_pledge.amount).toBe("string");
|
expect(typeof mixnode.bond_information.original_pledge.amount).toBe(
|
||||||
expect(typeof mixnode.bond_information.original_pledge.denom).toBe("string");
|
"string"
|
||||||
|
);
|
||||||
|
expect(typeof mixnode.bond_information.original_pledge.denom).toBe(
|
||||||
|
"string"
|
||||||
|
);
|
||||||
expect(typeof mixnode.bond_information.layer).toBe("number");
|
expect(typeof mixnode.bond_information.layer).toBe("number");
|
||||||
expect(typeof mixnode.bond_information.bonding_height).toBe("number");
|
expect(typeof mixnode.bond_information.bonding_height).toBe("number");
|
||||||
expect(typeof mixnode.bond_information.is_unbonding).toBe("boolean");
|
expect(typeof mixnode.bond_information.is_unbonding).toBe("boolean");
|
||||||
@@ -31,8 +35,12 @@ describe("Get mixnode data", (): void => {
|
|||||||
|
|
||||||
//mixnode
|
//mixnode
|
||||||
expect(typeof mixnode.bond_information.mix_node.host).toBe("string");
|
expect(typeof mixnode.bond_information.mix_node.host).toBe("string");
|
||||||
expect(mixnode.bond_information.mix_node.http_api_port).toStrictEqual(8000);
|
expect(mixnode.bond_information.mix_node.http_api_port).toStrictEqual(
|
||||||
expect(typeof mixnode.bond_information.mix_node.verloc_port).toBe("number");
|
8000
|
||||||
|
);
|
||||||
|
expect(typeof mixnode.bond_information.mix_node.verloc_port).toBe(
|
||||||
|
"number"
|
||||||
|
);
|
||||||
expect(typeof mixnode.bond_information.mix_node.mix_port).toBe("number");
|
expect(typeof mixnode.bond_information.mix_node.mix_port).toBe("number");
|
||||||
expect(mixnode.bond_information.mix_node.mix_port).toStrictEqual(1789);
|
expect(mixnode.bond_information.mix_node.mix_port).toStrictEqual(1789);
|
||||||
expect(mixnode.bond_information.mix_node.verloc_port).toStrictEqual(1790);
|
expect(mixnode.bond_information.mix_node.verloc_port).toStrictEqual(1790);
|
||||||
@@ -40,30 +48,39 @@ describe("Get mixnode data", (): void => {
|
|||||||
const identitykey = mixnode.bond_information.mix_node.identity_key;
|
const identitykey = mixnode.bond_information.mix_node.identity_key;
|
||||||
if (typeof identitykey === "string") {
|
if (typeof identitykey === "string") {
|
||||||
if (identitykey.length === 43) {
|
if (identitykey.length === 43) {
|
||||||
return true
|
return true;
|
||||||
}
|
} else expect(identitykey).toHaveLength(44);
|
||||||
else expect(identitykey).toHaveLength(44);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sphinx = mixnode.bond_information.mix_node.sphinx_key
|
const sphinx = mixnode.bond_information.mix_node.sphinx_key;
|
||||||
if (typeof sphinx === "string") {
|
if (typeof sphinx === "string") {
|
||||||
if (sphinx.length === 43) {
|
if (sphinx.length === 43) {
|
||||||
return true
|
return true;
|
||||||
}
|
} else expect(sphinx).toHaveLength(44);
|
||||||
else expect(sphinx).toHaveLength(44);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//rewarding details
|
//rewarding details
|
||||||
expect(typeof mixnode.rewarding_details.cost_params.profit_margin_percent).toBe("string");
|
expect(
|
||||||
expect(typeof mixnode.rewarding_details.cost_params.interval_operating_cost.denom).toBe("string");
|
typeof mixnode.rewarding_details.cost_params.profit_margin_percent
|
||||||
expect(typeof mixnode.rewarding_details.cost_params.interval_operating_cost.amount).toBe("string");
|
).toBe("string");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.rewarding_details.cost_params.interval_operating_cost
|
||||||
|
.denom
|
||||||
|
).toBe("string");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.rewarding_details.cost_params.interval_operating_cost
|
||||||
|
.amount
|
||||||
|
).toBe("string");
|
||||||
expect(typeof mixnode.rewarding_details.operator).toBe("string");
|
expect(typeof mixnode.rewarding_details.operator).toBe("string");
|
||||||
expect(typeof mixnode.rewarding_details.delegates).toBe("string");
|
expect(typeof mixnode.rewarding_details.delegates).toBe("string");
|
||||||
expect(typeof mixnode.rewarding_details.total_unit_reward).toBe("string");
|
expect(typeof mixnode.rewarding_details.total_unit_reward).toBe("string");
|
||||||
expect(typeof mixnode.rewarding_details.unit_delegation).toBe("string");
|
expect(typeof mixnode.rewarding_details.unit_delegation).toBe("string");
|
||||||
expect(typeof mixnode.rewarding_details.last_rewarded_epoch).toBe("number");
|
expect(typeof mixnode.rewarding_details.last_rewarded_epoch).toBe(
|
||||||
expect(typeof mixnode.rewarding_details.unique_delegations).toBe("number");
|
"number"
|
||||||
|
);
|
||||||
|
expect(typeof mixnode.rewarding_details.unique_delegations).toBe(
|
||||||
|
"number"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,85 +96,139 @@ describe("Get mixnode data", (): void => {
|
|||||||
expect(typeof mixnode.family).toBe("string");
|
expect(typeof mixnode.family).toBe("string");
|
||||||
|
|
||||||
//mixnode details bond info
|
//mixnode details bond info
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.mix_id).toBe("number")
|
expect(typeof mixnode.mixnode_details.bond_information.mix_id).toBe(
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.owner).toBe("string");
|
"number"
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.original_pledge.amount).toBe("string");
|
);
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.original_pledge.denom).toBe("string");
|
expect(typeof mixnode.mixnode_details.bond_information.owner).toBe(
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.layer).toBe("number");
|
"string"
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.bonding_height).toBe("number");
|
);
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.is_unbonding).toBe("boolean");
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.bond_information.original_pledge.amount
|
||||||
|
).toBe("string");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.bond_information.original_pledge.denom
|
||||||
|
).toBe("string");
|
||||||
|
expect(typeof mixnode.mixnode_details.bond_information.layer).toBe(
|
||||||
|
"number"
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.bond_information.bonding_height
|
||||||
|
).toBe("number");
|
||||||
|
expect(typeof mixnode.mixnode_details.bond_information.is_unbonding).toBe(
|
||||||
|
"boolean"
|
||||||
|
);
|
||||||
|
|
||||||
if (mixnode.mixnode_details.bond_information.proxy === null) {
|
if (mixnode.mixnode_details.bond_information.proxy === null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else {
|
expect(typeof mixnode.mixnode_details.bond_information.proxy).toBe(
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.proxy).toBe("string");
|
"string"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//mixnode
|
//mixnode
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.mix_node.host).toBe("string")
|
expect(
|
||||||
expect(mixnode.mixnode_details.bond_information.mix_node.http_api_port).toStrictEqual(8000);
|
typeof mixnode.mixnode_details.bond_information.mix_node.host
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.mix_node.verloc_port).toBe("number")
|
).toBe("string");
|
||||||
expect(typeof mixnode.mixnode_details.bond_information.mix_node.mix_port).toBe("number")
|
expect(
|
||||||
expect(mixnode.mixnode_details.bond_information.mix_node.mix_port).toStrictEqual(1789);
|
mixnode.mixnode_details.bond_information.mix_node.http_api_port
|
||||||
expect(mixnode.mixnode_details.bond_information.mix_node.verloc_port).toStrictEqual(1790)
|
).toStrictEqual(8000);
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.bond_information.mix_node.verloc_port
|
||||||
|
).toBe("number");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.bond_information.mix_node.mix_port
|
||||||
|
).toBe("number");
|
||||||
|
expect(
|
||||||
|
mixnode.mixnode_details.bond_information.mix_node.mix_port
|
||||||
|
).toStrictEqual(1789);
|
||||||
|
expect(
|
||||||
|
mixnode.mixnode_details.bond_information.mix_node.verloc_port
|
||||||
|
).toStrictEqual(1790);
|
||||||
|
|
||||||
let identitykey2 = mixnode.mixnode_details.bond_information.mix_node.identity_key
|
const identitykey2 =
|
||||||
|
mixnode.mixnode_details.bond_information.mix_node.identity_key;
|
||||||
if (typeof identitykey2 === "string") {
|
if (typeof identitykey2 === "string") {
|
||||||
if (identitykey2.length === 43) {
|
if (identitykey2.length === 43) {
|
||||||
return true
|
return true;
|
||||||
}
|
} else expect(identitykey2).toHaveLength(44);
|
||||||
else expect(identitykey2).toHaveLength(44);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sphinx2 = mixnode.mixnode_details.bond_information.mix_node.sphinx_key
|
const sphinx2 =
|
||||||
|
mixnode.mixnode_details.bond_information.mix_node.sphinx_key;
|
||||||
if (typeof sphinx2 === "string") {
|
if (typeof sphinx2 === "string") {
|
||||||
if (sphinx2.length === 43) {
|
if (sphinx2.length === 43) {
|
||||||
return true
|
return true;
|
||||||
}
|
} else expect(sphinx2).toHaveLength(44);
|
||||||
else expect(sphinx2).toHaveLength(44);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mixnode rewarding info
|
//mixnode rewarding info
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.cost_params.profit_margin_percent).toBe("string")
|
expect(
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.cost_params.interval_operating_cost.denom).toBe("string")
|
typeof mixnode.mixnode_details.rewarding_details.cost_params
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.cost_params.interval_operating_cost.amount).toBe("string")
|
.profit_margin_percent
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.operator).toBe("string")
|
).toBe("string");
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.delegates).toBe("string")
|
expect(
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.total_unit_reward).toBe("string")
|
typeof mixnode.mixnode_details.rewarding_details.cost_params
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.unit_delegation).toBe("string")
|
.interval_operating_cost.denom
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.last_rewarded_epoch).toBe("number")
|
).toBe("string");
|
||||||
expect(typeof mixnode.mixnode_details.rewarding_details.unique_delegations).toBe("number")
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.rewarding_details.cost_params
|
||||||
|
.interval_operating_cost.amount
|
||||||
|
).toBe("string");
|
||||||
|
expect(typeof mixnode.mixnode_details.rewarding_details.operator).toBe(
|
||||||
|
"string"
|
||||||
|
);
|
||||||
|
expect(typeof mixnode.mixnode_details.rewarding_details.delegates).toBe(
|
||||||
|
"string"
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.rewarding_details.total_unit_reward
|
||||||
|
).toBe("string");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.rewarding_details.unit_delegation
|
||||||
|
).toBe("string");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.rewarding_details.last_rewarded_epoch
|
||||||
|
).toBe("number");
|
||||||
|
expect(
|
||||||
|
typeof mixnode.mixnode_details.rewarding_details.unique_delegations
|
||||||
|
).toBe("number");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get active mixnodes", async (): Promise<void> => {
|
it("Get active mixnodes", async (): Promise<void> => {
|
||||||
const response = await contract.getActiveMixnodes();
|
const response = await contract.getActiveMixnodes();
|
||||||
response.forEach(function (mixnode) {
|
response.forEach(function (mixnode) {
|
||||||
expect(mixnode.rewarding_details.cost_params.profit_margin_percent).toBeTruthy()
|
expect(
|
||||||
expect(typeof mixnode.bond_information.layer).toBe("number")
|
mixnode.rewarding_details.cost_params.profit_margin_percent
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(typeof mixnode.bond_information.layer).toBe("number");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get active mixnodes detailed", async (): Promise<void> => {
|
it("Get active mixnodes detailed", async (): Promise<void> => {
|
||||||
const response = await contract.getActiveMixnodesDetailed();
|
const response = await contract.getActiveMixnodesDetailed();
|
||||||
response.forEach(function (mixnode) {
|
response.forEach(function (mixnode) {
|
||||||
expect(mixnode.mixnode_details.rewarding_details.cost_params.profit_margin_percent).toBeTruthy()
|
expect(
|
||||||
|
mixnode.mixnode_details.rewarding_details.cost_params
|
||||||
|
.profit_margin_percent
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get rewarded mixnodes", async (): Promise<void> => {
|
it("Get rewarded mixnodes", async (): Promise<void> => {
|
||||||
const response = await contract.getRewardedMixnodes();
|
const response = await contract.getRewardedMixnodes();
|
||||||
response.forEach(function (mixnode) {
|
response.forEach(function (mixnode) {
|
||||||
expect(mixnode.rewarding_details.last_rewarded_epoch).toBeTruthy()
|
expect(mixnode.rewarding_details.last_rewarded_epoch).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get rewarded mixnodes detailed", async (): Promise<void> => {
|
it("Get rewarded mixnodes detailed", async (): Promise<void> => {
|
||||||
const response = await contract.getRewardedMixnodesDetailed();
|
const response = await contract.getRewardedMixnodesDetailed();
|
||||||
response.forEach(function (mixnode) {
|
response.forEach(function (mixnode) {
|
||||||
expect(mixnode.mixnode_details.rewarding_details.last_rewarded_epoch).toBeTruthy()
|
expect(
|
||||||
|
mixnode.mixnode_details.rewarding_details.last_rewarded_epoch
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -167,5 +238,4 @@ describe("Get mixnode data", (): void => {
|
|||||||
expect(typeof value).toBe("number");
|
expect(typeof value).toBe("number");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,5 +46,4 @@ describe("Get gateway data", (): void => {
|
|||||||
expect(typeof response.last_hour).toBe("number");
|
expect(typeof response.last_hour).toBe("number");
|
||||||
expect(typeof response.last_day).toBe("number");
|
expect(typeof response.last_day).toBe("number");
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ describe("Get mixnode data", (): void => {
|
|||||||
const response = await status.getMixnodeHistory(identity_key);
|
const response = await status.getMixnodeHistory(identity_key);
|
||||||
|
|
||||||
response.history.forEach((x) => {
|
response.history.forEach((x) => {
|
||||||
console.log(x.date);
|
expect(typeof x.date).toBe("string");
|
||||||
console.log(x.uptime);
|
expect(typeof x.uptime).toBe("number");
|
||||||
})
|
});
|
||||||
|
|
||||||
expect(identity_key).toStrictEqual(response.mix_id);
|
expect(identity_key).toStrictEqual(response.mix_id);
|
||||||
expect(typeof response.owner).toBe("string");
|
expect(typeof response.owner).toBe("string");
|
||||||
@@ -67,7 +67,9 @@ describe("Get mixnode data", (): void => {
|
|||||||
const identity_key = config.environmnetConfig.mix_id;
|
const identity_key = config.environmnetConfig.mix_id;
|
||||||
const response = await status.getMixnodeRewardComputation(identity_key);
|
const response = await status.getMixnodeRewardComputation(identity_key);
|
||||||
|
|
||||||
expect(response.reward_params.interval.sybil_resistance).toStrictEqual("0.3");
|
expect(response.reward_params.interval.sybil_resistance).toStrictEqual(
|
||||||
|
"0.3"
|
||||||
|
);
|
||||||
expect(response.reward_params.active_set_size).toStrictEqual(240);
|
expect(response.reward_params.active_set_size).toStrictEqual(240);
|
||||||
expect(typeof response.reward_params.interval.reward_pool).toBe("string");
|
expect(typeof response.reward_params.interval.reward_pool).toBe("string");
|
||||||
});
|
});
|
||||||
@@ -79,30 +81,42 @@ describe("Get mixnode data", (): void => {
|
|||||||
expect(typeof response.in_active).toBe("string");
|
expect(typeof response.in_active).toBe("string");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get all mixnodes inclusion probability", async (): Promise<void> => {
|
it("Get all mixnodes inclusion probabilities", async (): Promise<void> => {
|
||||||
const response = await status.getAllMixnodeInclusionProbability();
|
const response = await status.getAllMixnodeInclusionProbability();
|
||||||
|
const array = response.inclusion_probabilities;
|
||||||
expect(response.inclusion_probabilities).toBeTruthy();
|
array.forEach((x) => {
|
||||||
|
expect(typeof x.in_reserve).toBe("number");
|
||||||
|
expect(typeof x.mix_id).toBe("number");
|
||||||
|
});
|
||||||
|
expect(typeof response.elapsed.nanos).toBe("number");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get all mixnodes", async (): Promise<void> => {
|
it("Get all mixnodes", async (): Promise<void> => {
|
||||||
const response = await status.getDetailedMixnodes();
|
const response = await status.getDetailedMixnodes();
|
||||||
|
response.forEach((x) => {
|
||||||
expect(typeof response.stake_saturation).toBe("string");
|
expect(typeof x.mixnode_details.bond_information.mix_id).toBe("number");
|
||||||
|
expect(typeof x.mixnode_details.bond_information.layer).toBe("number");
|
||||||
|
expect(typeof x.stake_saturation).toBe("string");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get all rewarded mixnodes", async (): Promise<void> => {
|
it("Get all rewarded mixnodes", async (): Promise<void> => {
|
||||||
const response = await status.getDetailedRewardedMixnodes();
|
const response = await status.getDetailedRewardedMixnodes();
|
||||||
|
response.forEach((x) => {
|
||||||
expect(typeof response.mixnode_details.rewarding_details.last_rewarded_epoch).toBe("number");
|
expect(typeof x.mixnode_details.bond_information.mix_id).toBe("number");
|
||||||
|
expect(typeof x.mixnode_details.bond_information.layer).toBe("number");
|
||||||
|
expect(typeof x.stake_saturation).toBe("string");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Get all active mixnodes", async (): Promise<void> => {
|
it("Get all active mixnodes", async (): Promise<void> => {
|
||||||
const response = await status.getDetailedActiveMixnodes();
|
const response = await status.getDetailedActiveMixnodes();
|
||||||
|
response.forEach((x) => {
|
||||||
expect(typeof response.mixnode_details.bond_information.layer).toBe("number");
|
expect(typeof x.mixnode_details.bond_information.mix_id).toBe("number");
|
||||||
|
expect(typeof x.mixnode_details.bond_information.layer).toBe("number");
|
||||||
|
expect(typeof x.stake_saturation).toBe("string");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Compute mixnode reward estimation", (): void => {
|
describe("Compute mixnode reward estimation", (): void => {
|
||||||
@@ -110,11 +124,11 @@ describe("Compute mixnode reward estimation", (): void => {
|
|||||||
status = new Status();
|
status = new Status();
|
||||||
config = ConfigHandler.getInstance();
|
config = ConfigHandler.getInstance();
|
||||||
});
|
});
|
||||||
it("with correct data", async (): Promise<void> => {
|
// TODO Fix this test
|
||||||
|
it.skip("with correct data", async (): Promise<void> => {
|
||||||
const response = await status.sendMixnodeRewardEstimatedComputation(8);
|
const response = await status.sendMixnodeRewardEstimatedComputation(8);
|
||||||
const body =
|
const body = expect(typeof response.estimation.total_node_reward).toBe(
|
||||||
|
"string"
|
||||||
expect(typeof response.estimation.total_node_reward).toBe("string");
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,4 +12,18 @@ export default class ContractCache extends APIClient {
|
|||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getTotalSupplyValue(): Promise<number> {
|
||||||
|
const response = await this.restClient.sendGet({
|
||||||
|
route: `circulating-supply/total-supply-value`,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCirculatingSupplyValue(): Promise<number> {
|
||||||
|
const response = await this.restClient.sendGet({
|
||||||
|
route: `circulating-supply/circulating-supply-value`,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import {
|
|||||||
AllGateways,
|
AllGateways,
|
||||||
AllMixnodes,
|
AllMixnodes,
|
||||||
EpochRewardParams,
|
EpochRewardParams,
|
||||||
|
BlacklistedGateways,
|
||||||
|
BlacklistedMixnodes,
|
||||||
CurrentEpoch,
|
CurrentEpoch,
|
||||||
} from "../types/ContractCacheTypes";
|
} from "../types/ContractCacheTypes";
|
||||||
import { APIClient } from "./abstracts/APIClient";
|
import { APIClient } from "./abstracts/APIClient";
|
||||||
@@ -62,14 +64,14 @@ export default class ContractCache extends APIClient {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getBlacklistedMixnodes(): Promise<[]> {
|
public async getBlacklistedMixnodes(): Promise<BlacklistedMixnodes[]> {
|
||||||
const response = await this.restClient.sendGet({
|
const response = await this.restClient.sendGet({
|
||||||
route: `mixnodes/blacklisted`,
|
route: `mixnodes/blacklisted`,
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getBlacklistedGateways(): Promise<[]> {
|
public async getBlacklistedGateways(): Promise<BlacklistedGateways[]> {
|
||||||
const response = await this.restClient.sendGet({
|
const response = await this.restClient.sendGet({
|
||||||
route: `gateways/blacklisted`,
|
route: `gateways/blacklisted`,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -147,13 +147,13 @@ export default class Status extends APIClient {
|
|||||||
|
|
||||||
public async getAllMixnodeInclusionProbability(): Promise<InclusionProbabilities> {
|
public async getAllMixnodeInclusionProbability(): Promise<InclusionProbabilities> {
|
||||||
const response = await this.restClient.sendGet({
|
const response = await this.restClient.sendGet({
|
||||||
route: `/mixnodes/inclusion-probability`,
|
route: `/mixnodes/inclusion_probability`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDetailedMixnodes(): Promise<DetailedMixnodes> {
|
public async getDetailedMixnodes(): Promise<DetailedMixnodes[]> {
|
||||||
const response = await this.restClient.sendGet({
|
const response = await this.restClient.sendGet({
|
||||||
route: `/mixnodes/detailed`,
|
route: `/mixnodes/detailed`,
|
||||||
});
|
});
|
||||||
@@ -161,7 +161,7 @@ export default class Status extends APIClient {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDetailedRewardedMixnodes(): Promise<DetailedMixnodes> {
|
public async getDetailedRewardedMixnodes(): Promise<DetailedMixnodes[]> {
|
||||||
const response = await this.restClient.sendGet({
|
const response = await this.restClient.sendGet({
|
||||||
route: `/mixnodes/rewarded/detailed`,
|
route: `/mixnodes/rewarded/detailed`,
|
||||||
});
|
});
|
||||||
@@ -169,7 +169,7 @@ export default class Status extends APIClient {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDetailedActiveMixnodes(): Promise<DetailedMixnodes> {
|
public async getDetailedActiveMixnodes(): Promise<DetailedMixnodes[]> {
|
||||||
const response = await this.restClient.sendGet({
|
const response = await this.restClient.sendGet({
|
||||||
route: `/mixnodes/active/detailed`,
|
route: `/mixnodes/active/detailed`,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export type Detailed = {
|
export type Detailed = {
|
||||||
initial_supply: InitialSupply;
|
total_supply: TotalSupply;
|
||||||
mixmining_reserve: MixminingReserve;
|
mixmining_reserve: MixminingReserve;
|
||||||
vesting_tokens: VestingTokens;
|
vesting_tokens: VestingTokens;
|
||||||
circulating_supply: CirculatingSupply;
|
circulating_supply: CirculatingSupply;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InitialSupply = {
|
export type TotalSupply = {
|
||||||
demon: "unym";
|
demon: "unym";
|
||||||
amount: string;
|
amount: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
export interface AllMixnodes {
|
export type AllMixnodes = {
|
||||||
bond_information: BondInformation;
|
bond_information: BondInformation;
|
||||||
rewarding_details: RewardingDetails;
|
rewarding_details: RewardingDetails;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface BondInformation {
|
export type BondInformation = {
|
||||||
mix_id: number;
|
mix_id: number;
|
||||||
owner: string;
|
owner: string;
|
||||||
original_pledge: OriginalPledge;
|
original_pledge: OriginalPledge;
|
||||||
@@ -12,9 +12,9 @@ export interface BondInformation {
|
|||||||
proxy: string;
|
proxy: string;
|
||||||
bonding_height: number;
|
bonding_height: number;
|
||||||
is_unbonding: boolean;
|
is_unbonding: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface RewardingDetails {
|
export type RewardingDetails = {
|
||||||
cost_params: CostParams;
|
cost_params: CostParams;
|
||||||
operator: string;
|
operator: string;
|
||||||
delegates: string;
|
delegates: string;
|
||||||
@@ -22,29 +22,29 @@ export interface RewardingDetails {
|
|||||||
unit_delegation: string;
|
unit_delegation: string;
|
||||||
last_rewarded_epoch: number;
|
last_rewarded_epoch: number;
|
||||||
unique_delegations: number;
|
unique_delegations: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface CostParams {
|
export type CostParams = {
|
||||||
profit_margin_percent: string;
|
profit_margin_percent: string;
|
||||||
interval_operating_cost: IntervalOperatingCost;
|
interval_operating_cost: IntervalOperatingCost;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface IntervalOperatingCost {
|
export type IntervalOperatingCost = {
|
||||||
denom: string;
|
denom: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface OriginalPledge {
|
export type OriginalPledge = {
|
||||||
denom: string;
|
denom: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface TotalDelegation {
|
export type TotalDelegation = {
|
||||||
denom: string;
|
denom: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface Mixnode {
|
export type Mixnode = {
|
||||||
host: string;
|
host: string;
|
||||||
mix_port: number;
|
mix_port: number;
|
||||||
verloc_port: number;
|
verloc_port: number;
|
||||||
@@ -52,9 +52,9 @@ export interface Mixnode {
|
|||||||
sphinx_key: string;
|
sphinx_key: string;
|
||||||
identity_key: string;
|
identity_key: string;
|
||||||
version: string;
|
version: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface MixnodeBond {
|
export type MixnodeBond = {
|
||||||
pledge_amount: OriginalPledge;
|
pledge_amount: OriginalPledge;
|
||||||
total_delegation: TotalDelegation;
|
total_delegation: TotalDelegation;
|
||||||
owner: string;
|
owner: string;
|
||||||
@@ -63,9 +63,9 @@ export interface MixnodeBond {
|
|||||||
mix_node: Mixnode;
|
mix_node: Mixnode;
|
||||||
proxy: string;
|
proxy: string;
|
||||||
accumulated_rewards: string;
|
accumulated_rewards: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface MixnodesDetailed {
|
export type MixnodesDetailed = {
|
||||||
mixnode_details: AllMixnodes;
|
mixnode_details: AllMixnodes;
|
||||||
stake_saturation: string;
|
stake_saturation: string;
|
||||||
uncapped_stake_saturation: string;
|
uncapped_stake_saturation: string;
|
||||||
@@ -73,7 +73,11 @@ export interface MixnodesDetailed {
|
|||||||
estimated_operator_apy: string;
|
estimated_operator_apy: string;
|
||||||
estimated_delegators_apy: string;
|
estimated_delegators_apy: string;
|
||||||
family: string;
|
family: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export type BlacklistedMixnodes = {};
|
||||||
|
|
||||||
|
export type BlacklistedGateways = {};
|
||||||
|
|
||||||
export interface Gateway {
|
export interface Gateway {
|
||||||
host: string;
|
host: string;
|
||||||
@@ -93,13 +97,13 @@ export interface AllGateways {
|
|||||||
proxy: string;
|
proxy: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EpochRewardParams {
|
export type EpochRewardParams = {
|
||||||
interval: Interval;
|
interval: Interval;
|
||||||
rewarded_set_size: number;
|
rewarded_set_size: number;
|
||||||
active_set_size: number;
|
active_set_size: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface Interval {
|
export type Interval = {
|
||||||
reward_pool: string;
|
reward_pool: string;
|
||||||
staking_supply: string;
|
staking_supply: string;
|
||||||
staking_supply_scale_factor: string;
|
staking_supply_scale_factor: string;
|
||||||
@@ -108,18 +112,18 @@ export interface Interval {
|
|||||||
sybil_resistance: string;
|
sybil_resistance: string;
|
||||||
active_set_work_factor: string;
|
active_set_work_factor: string;
|
||||||
interval_pool_emission: string;
|
interval_pool_emission: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface CurrentEpoch {
|
export type CurrentEpoch = {
|
||||||
id: number;
|
id: number;
|
||||||
epochs_in_interval: number;
|
epochs_in_interval: number;
|
||||||
current_epoch_start: string;
|
current_epoch_start: string;
|
||||||
current_epoch_id: number;
|
current_epoch_id: number;
|
||||||
epoch_length: EpochLength;
|
epoch_length: EpochLength;
|
||||||
total_elapsed_epochs: number;
|
total_elapsed_epochs: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface EpochLength {
|
export type EpochLength = {
|
||||||
secs: number;
|
secs: number;
|
||||||
nanos: number;
|
nanos: number;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -20,6 +20,6 @@
|
|||||||
"typeRoots": ["node_modules/@types"],
|
"typeRoots": ["node_modules/@types"],
|
||||||
"alwaysStrict": true
|
"alwaysStrict": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "tests/functional_test/*/*"],
|
"include": ["src/**/*", "functional_test/*/*"],
|
||||||
"exclude": ["unit_test/**/*"]
|
"exclude": ["unit_test/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "nym-api-requests"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bs58 = "0.4.0"
|
||||||
|
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
|
||||||
|
cosmwasm-std = { version = "1.0.0", default-features = false }
|
||||||
|
getset = "0.1.1"
|
||||||
|
schemars = { version = "0.8", features = ["preserve_order"] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
ts-rs = { version = "6.1.2", optional = true }
|
||||||
|
|
||||||
|
coconut-interface = { path = "../../common/coconut-interface", optional = true }
|
||||||
|
mixnet-contract-common = { path= "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
coconut = ["coconut-interface"]
|
||||||
|
generate-ts = ["ts-rs"]
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use cosmrs::AccountId;
|
||||||
|
use getset::{CopyGetters, Getters};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use coconut_interface::{
|
||||||
|
error::CoconutInterfaceError, Attribute, Base58, BlindSignRequest, Credential, VerificationKey,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Getters, CopyGetters)]
|
||||||
|
pub struct VerifyCredentialBody {
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
credential: Credential,
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
proposal_id: u64,
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
gateway_cosmos_addr: AccountId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VerifyCredentialBody {
|
||||||
|
pub fn new(
|
||||||
|
credential: Credential,
|
||||||
|
proposal_id: u64,
|
||||||
|
gateway_cosmos_addr: AccountId,
|
||||||
|
) -> VerifyCredentialBody {
|
||||||
|
VerifyCredentialBody {
|
||||||
|
credential,
|
||||||
|
proposal_id,
|
||||||
|
gateway_cosmos_addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct VerifyCredentialResponse {
|
||||||
|
pub verification_result: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VerifyCredentialResponse {
|
||||||
|
pub fn new(verification_result: bool) -> Self {
|
||||||
|
VerifyCredentialResponse {
|
||||||
|
verification_result,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All strings are base58 encoded representations of structs
|
||||||
|
#[derive(Clone, Serialize, Deserialize, Debug, Getters, CopyGetters)]
|
||||||
|
pub struct BlindSignRequestBody {
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
blind_sign_request: BlindSignRequest,
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
tx_hash: String,
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
signature: String,
|
||||||
|
public_attributes: Vec<String>,
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
public_attributes_plain: Vec<String>,
|
||||||
|
#[getset(get = "pub")]
|
||||||
|
total_params: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlindSignRequestBody {
|
||||||
|
pub fn new(
|
||||||
|
blind_sign_request: &BlindSignRequest,
|
||||||
|
tx_hash: String,
|
||||||
|
signature: String,
|
||||||
|
public_attributes: &[Attribute],
|
||||||
|
public_attributes_plain: Vec<String>,
|
||||||
|
total_params: u32,
|
||||||
|
) -> BlindSignRequestBody {
|
||||||
|
BlindSignRequestBody {
|
||||||
|
blind_sign_request: blind_sign_request.clone(),
|
||||||
|
tx_hash,
|
||||||
|
signature,
|
||||||
|
public_attributes: public_attributes
|
||||||
|
.iter()
|
||||||
|
.map(|attr| attr.to_bs58())
|
||||||
|
.collect(),
|
||||||
|
public_attributes_plain,
|
||||||
|
total_params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public_attributes(&self) -> Vec<Attribute> {
|
||||||
|
self.public_attributes
|
||||||
|
.iter()
|
||||||
|
.map(|x| Attribute::try_from_bs58(x).unwrap())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BlindedSignatureResponse {
|
||||||
|
pub remote_key: [u8; 32],
|
||||||
|
pub encrypted_signature: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlindedSignatureResponse {
|
||||||
|
pub fn new(encrypted_signature: Vec<u8>, remote_key: [u8; 32]) -> BlindedSignatureResponse {
|
||||||
|
BlindedSignatureResponse {
|
||||||
|
encrypted_signature,
|
||||||
|
remote_key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_base58_string(&self) -> String {
|
||||||
|
bs58::encode(&self.to_bytes()).into_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_base58_string<I: AsRef<[u8]>>(val: I) -> Result<Self, CoconutInterfaceError> {
|
||||||
|
let bytes = bs58::decode(val).into_vec()?;
|
||||||
|
Self::from_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
let mut bytes = self.remote_key.to_vec();
|
||||||
|
bytes.extend_from_slice(&self.encrypted_signature);
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CoconutInterfaceError> {
|
||||||
|
if bytes.len() < 32 {
|
||||||
|
return Err(CoconutInterfaceError::InvalidByteLength(bytes.len(), 32));
|
||||||
|
}
|
||||||
|
let mut remote_key = [0u8; 32];
|
||||||
|
remote_key.copy_from_slice(&bytes[..32]);
|
||||||
|
let encrypted_signature = bytes[32..].to_vec();
|
||||||
|
Ok(BlindedSignatureResponse {
|
||||||
|
remote_key,
|
||||||
|
encrypted_signature,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct VerificationKeyResponse {
|
||||||
|
pub key: VerificationKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VerificationKeyResponse {
|
||||||
|
pub fn new(key: VerificationKey) -> VerificationKeyResponse {
|
||||||
|
VerificationKeyResponse { key }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct CosmosAddressResponse {
|
||||||
|
pub addr: AccountId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CosmosAddressResponse {
|
||||||
|
pub fn new(addr: AccountId) -> CosmosAddressResponse {
|
||||||
|
CosmosAddressResponse { addr }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "coconut")]
|
||||||
|
pub mod coconut;
|
||||||
|
pub mod models;
|
||||||
|
|
||||||
|
pub trait Deprecatable {
|
||||||
|
fn deprecate(self) -> Deprecated<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deprecatable for T {}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct Deprecated<T> {
|
||||||
|
pub deprecated: bool,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub response: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for Deprecated<T> {
|
||||||
|
fn from(response: T) -> Self {
|
||||||
|
Deprecated {
|
||||||
|
deprecated: true,
|
||||||
|
response,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use cosmwasm_std::{Coin, Decimal};
|
||||||
|
use mixnet_contract_common::families::FamilyHead;
|
||||||
|
use mixnet_contract_common::mixnode::MixNodeDetails;
|
||||||
|
use mixnet_contract_common::reward_params::{Performance, RewardingParams};
|
||||||
|
use mixnet_contract_common::rewarding::RewardEstimate;
|
||||||
|
use mixnet_contract_common::{
|
||||||
|
IdentityKey, Interval, MixId, MixNode, Percent, RewardedSetNodeStatus,
|
||||||
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{fmt, time::Duration};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||||
|
pub struct RequestError {
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestError {
|
||||||
|
pub fn new<S: Into<String>>(msg: S) -> Self {
|
||||||
|
RequestError {
|
||||||
|
message: msg.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message(&self) -> &str {
|
||||||
|
&self.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/MixnodeStatus.ts")
|
||||||
|
)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum MixnodeStatus {
|
||||||
|
Active, // in both the active set and the rewarded set
|
||||||
|
Standby, // only in the rewarded set
|
||||||
|
Inactive, // in neither the rewarded set nor the active set, but is bonded
|
||||||
|
NotFound, // doesn't even exist in the bonded set
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MixnodeStatus> for Option<RewardedSetNodeStatus> {
|
||||||
|
fn from(status: MixnodeStatus) -> Self {
|
||||||
|
match status {
|
||||||
|
MixnodeStatus::Active => Some(RewardedSetNodeStatus::Active),
|
||||||
|
MixnodeStatus::Standby => Some(RewardedSetNodeStatus::Standby),
|
||||||
|
MixnodeStatus::Inactive => None,
|
||||||
|
MixnodeStatus::NotFound => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MixnodeStatus {
|
||||||
|
pub fn is_active(&self) -> bool {
|
||||||
|
*self == MixnodeStatus::Active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/MixnodeCoreStatusResponse.ts")
|
||||||
|
)]
|
||||||
|
pub struct MixnodeCoreStatusResponse {
|
||||||
|
pub mix_id: MixId,
|
||||||
|
pub count: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/GatewayCoreStatusResponse.ts")
|
||||||
|
)]
|
||||||
|
pub struct GatewayCoreStatusResponse {
|
||||||
|
pub identity: String,
|
||||||
|
pub count: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/MixnodeStatusResponse.ts")
|
||||||
|
)]
|
||||||
|
pub struct MixnodeStatusResponse {
|
||||||
|
pub status: MixnodeStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct MixNodeBondAnnotated {
|
||||||
|
pub mixnode_details: MixNodeDetails,
|
||||||
|
pub stake_saturation: StakeSaturation,
|
||||||
|
pub uncapped_stake_saturation: StakeSaturation,
|
||||||
|
pub performance: Performance,
|
||||||
|
pub estimated_operator_apy: Decimal,
|
||||||
|
pub estimated_delegators_apy: Decimal,
|
||||||
|
pub family: Option<FamilyHead>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MixNodeBondAnnotated {
|
||||||
|
pub fn mix_node(&self) -> &MixNode {
|
||||||
|
&self.mixnode_details.bond_information.mix_node
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mix_id(&self) -> MixId {
|
||||||
|
self.mixnode_details.mix_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct ComputeRewardEstParam {
|
||||||
|
pub performance: Option<Performance>,
|
||||||
|
pub active_in_rewarded_set: Option<bool>,
|
||||||
|
pub pledge_amount: Option<u64>,
|
||||||
|
pub total_delegation: Option<u64>,
|
||||||
|
pub interval_operating_cost: Option<Coin>,
|
||||||
|
pub profit_margin_percent: Option<Percent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/RewardEstimationResponse.ts")
|
||||||
|
)]
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct RewardEstimationResponse {
|
||||||
|
pub estimation: RewardEstimate,
|
||||||
|
pub reward_params: RewardingParams,
|
||||||
|
pub epoch: Interval,
|
||||||
|
#[cfg_attr(feature = "generate-ts", ts(type = "number"))]
|
||||||
|
pub as_at: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct UptimeResponse {
|
||||||
|
pub mix_id: MixId,
|
||||||
|
pub avg_uptime: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/StakeSaturationResponse.ts")
|
||||||
|
)]
|
||||||
|
pub struct StakeSaturationResponse {
|
||||||
|
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
|
||||||
|
pub saturation: StakeSaturation,
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
|
||||||
|
pub uncapped_saturation: StakeSaturation,
|
||||||
|
pub as_at: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type StakeSaturation = Decimal;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/SelectionChance.ts")
|
||||||
|
)]
|
||||||
|
pub enum SelectionChance {
|
||||||
|
High,
|
||||||
|
Good,
|
||||||
|
Low,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f64> for SelectionChance {
|
||||||
|
fn from(p: f64) -> SelectionChance {
|
||||||
|
match p {
|
||||||
|
p if p >= 0.7 => SelectionChance::High,
|
||||||
|
p if p >= 0.3 => SelectionChance::Good,
|
||||||
|
_ => SelectionChance::Low,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Decimal> for SelectionChance {
|
||||||
|
fn from(p: Decimal) -> Self {
|
||||||
|
match p {
|
||||||
|
p if p >= Decimal::from_ratio(70u32, 100u32) => SelectionChance::High,
|
||||||
|
p if p >= Decimal::from_ratio(30u32, 100u32) => SelectionChance::Good,
|
||||||
|
_ => SelectionChance::Low,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SelectionChance {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
SelectionChance::High => write!(f, "High"),
|
||||||
|
SelectionChance::Good => write!(f, "Good"),
|
||||||
|
SelectionChance::Low => write!(f, "Low"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "generate-ts",
|
||||||
|
ts(export_to = "ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts")
|
||||||
|
)]
|
||||||
|
pub struct InclusionProbabilityResponse {
|
||||||
|
pub in_active: SelectionChance,
|
||||||
|
pub in_reserve: SelectionChance,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for InclusionProbabilityResponse {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"in_active: {}, in_reserve: {}",
|
||||||
|
self.in_active, self.in_reserve
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, schemars::JsonSchema)]
|
||||||
|
pub struct AllInclusionProbabilitiesResponse {
|
||||||
|
pub inclusion_probabilities: Vec<InclusionProbability>,
|
||||||
|
pub samples: u64,
|
||||||
|
pub elapsed: Duration,
|
||||||
|
pub delta_max: f64,
|
||||||
|
pub delta_l2: f64,
|
||||||
|
pub as_at: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, schemars::JsonSchema)]
|
||||||
|
pub struct InclusionProbability {
|
||||||
|
pub mix_id: MixId,
|
||||||
|
pub in_active: f64,
|
||||||
|
pub in_reserve: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Uptime = u8;
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||||
|
pub struct MixnodeStatusReportResponse {
|
||||||
|
pub mix_id: MixId,
|
||||||
|
pub identity: IdentityKey,
|
||||||
|
pub owner: String,
|
||||||
|
pub most_recent: Uptime,
|
||||||
|
pub last_hour: Uptime,
|
||||||
|
pub last_day: Uptime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||||
|
pub struct GatewayStatusReportResponse {
|
||||||
|
pub identity: String,
|
||||||
|
pub owner: String,
|
||||||
|
pub most_recent: Uptime,
|
||||||
|
pub last_hour: Uptime,
|
||||||
|
pub last_day: Uptime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||||
|
pub struct HistoricalUptimeResponse {
|
||||||
|
pub date: String,
|
||||||
|
pub uptime: Uptime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||||
|
pub struct MixnodeUptimeHistoryResponse {
|
||||||
|
pub mix_id: MixId,
|
||||||
|
pub identity: String,
|
||||||
|
pub owner: String,
|
||||||
|
pub history: Vec<HistoricalUptimeResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||||
|
pub struct GatewayUptimeHistoryResponse {
|
||||||
|
pub identity: String,
|
||||||
|
pub owner: String,
|
||||||
|
pub history: Vec<HistoricalUptimeResponse>,
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<title>Nym Connect</title>
|
|
||||||
</head>
|
|
||||||
<body style="background: rgb(29, 33, 37);">
|
|
||||||
<div id="root-growth"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<title>Nym Wallet Logs</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root-log"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -41,8 +41,8 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
tauri = { git = "https://github.com/tauri-apps/tauri", branch = "next", features = ["clipboard-write-text", "native-tls-vendored", "notification-all", "shell-open", "system-tray", "window-close", "window-minimize", "window-start-dragging"] }
|
# TODO swithing to `rfd101` temporarily, untill https://github.com/tauri-apps/tauri/pull/6174 is merged
|
||||||
# tauri = { version = "2.0.0-alpha.0", features = ["clipboard-write-text", "native-tls-vendored", "notification-all", "shell-open", "system-tray", "window-close", "window-minimize", "window-start-dragging"] }
|
tauri = { git = "https://github.com/tauri-apps/tauri", branch = "rfd101", features = ["clipboard-write-text", "native-tls-vendored", "notification-all", "shell-open", "system-tray", "window-close", "window-minimize", "window-start-dragging"] }
|
||||||
tendermint-rpc = "0.23.0"
|
tendermint-rpc = "0.23.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1.24.1", features = ["sync", "time"] }
|
tokio = { version = "1.24.1", features = ["sync", "time"] }
|
||||||
@@ -64,3 +64,9 @@ tempfile = "3.3.0"
|
|||||||
[features]
|
[features]
|
||||||
default = ["custom-protocol"]
|
default = ["custom-protocol"]
|
||||||
custom-protocol = ["tauri/custom-protocol"]
|
custom-protocol = ["tauri/custom-protocol"]
|
||||||
|
|
||||||
|
# [profile.dev]
|
||||||
|
# strip = true
|
||||||
|
# opt-level = "s"
|
||||||
|
# lto = true
|
||||||
|
|
||||||
|
|||||||
+91
-90
@@ -1,111 +1,112 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
id("rustPlugin")
|
id("rustPlugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = 33
|
compileSdk = 33
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
manifestPlaceholders["usesCleartextTraffic"] = "false"
|
manifestPlaceholders["usesCleartextTraffic"] = "false"
|
||||||
applicationId = "net.nymtech.nym_connect_android"
|
applicationId = "net.nymtech.nym_connect_android"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 33
|
targetSdk = 33
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0"
|
versionName = "1.0"
|
||||||
|
}
|
||||||
|
sourceSets.getByName("main") {
|
||||||
|
// Vulkan validation layers
|
||||||
|
val ndkHome = System.getenv("NDK_HOME")
|
||||||
|
jniLibs.srcDir("${ndkHome}/sources/third_party/vulkan/src/build-android/jniLibs")
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
getByName("debug") {
|
||||||
|
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||||
|
isDebuggable = true
|
||||||
|
isJniDebuggable = true
|
||||||
|
isMinifyEnabled = false
|
||||||
|
packagingOptions {
|
||||||
|
jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
|
||||||
|
|
||||||
|
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
|
||||||
|
|
||||||
|
jniLibs.keepDebugSymbols.add("*/x86/*.so")
|
||||||
|
|
||||||
|
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sourceSets.getByName("main") {
|
getByName("release") {
|
||||||
// Vulkan validation layers
|
isMinifyEnabled = false
|
||||||
val ndkHome = System.getenv("NDK_HOME")
|
// proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
|
||||||
jniLibs.srcDir("${ndkHome}/sources/third_party/vulkan/src/build-android/jniLibs")
|
|
||||||
}
|
}
|
||||||
buildTypes {
|
}
|
||||||
getByName("debug") {
|
flavorDimensions.add("abi")
|
||||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
productFlavors {
|
||||||
isDebuggable = true
|
create("universal") {
|
||||||
isJniDebuggable = true
|
val abiList = findProperty("abiList") as? String
|
||||||
isMinifyEnabled = false
|
|
||||||
packagingOptions {
|
|
||||||
jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
|
|
||||||
|
|
||||||
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
|
dimension = "abi"
|
||||||
|
ndk {
|
||||||
jniLibs.keepDebugSymbols.add("*/x86/*.so")
|
abiFilters += abiList?.split(",")?.map { it.trim() } ?: listOf(
|
||||||
|
"arm64-v8a", "armeabi-v7a", "x86", "x86_64",
|
||||||
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
getByName("release") {
|
|
||||||
isMinifyEnabled = false
|
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
flavorDimensions.add("abi")
|
create("arm64") {
|
||||||
productFlavors {
|
dimension = "abi"
|
||||||
create("universal") {
|
ndk {
|
||||||
val abiList = findProperty("abiList") as? String
|
abiFilters += listOf("arm64-v8a")
|
||||||
|
}
|
||||||
dimension = "abi"
|
|
||||||
ndk {
|
|
||||||
abiFilters += abiList?.split(",")?.map { it.trim() } ?: listOf( "arm64-v8a", "armeabi-v7a", "x86", "x86_64",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
create("arm64") {
|
|
||||||
dimension = "abi"
|
|
||||||
ndk {
|
|
||||||
abiFilters += listOf("arm64-v8a")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
create("arm") {
|
|
||||||
dimension = "abi"
|
|
||||||
ndk {
|
|
||||||
abiFilters += listOf("armeabi-v7a")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
create("x86") {
|
|
||||||
dimension = "abi"
|
|
||||||
ndk {
|
|
||||||
abiFilters += listOf("x86")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
create("x86_64") {
|
|
||||||
dimension = "abi"
|
|
||||||
ndk {
|
|
||||||
abiFilters += listOf("x86_64")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assetPacks += mutableSetOf()
|
create("arm") {
|
||||||
namespace = "net.nymtech.nym_connect_android"
|
dimension = "abi"
|
||||||
|
ndk {
|
||||||
|
abiFilters += listOf("armeabi-v7a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create("x86") {
|
||||||
|
dimension = "abi"
|
||||||
|
ndk {
|
||||||
|
abiFilters += listOf("x86")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create("x86_64") {
|
||||||
|
dimension = "abi"
|
||||||
|
ndk {
|
||||||
|
abiFilters += listOf("x86_64")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assetPacks += mutableSetOf()
|
||||||
|
namespace = "net.nymtech.nym_connect_android"
|
||||||
}
|
}
|
||||||
|
|
||||||
rust {
|
rust {
|
||||||
rootDirRel = "../../../../"
|
rootDirRel = "../../../../"
|
||||||
targets = listOf("aarch64", "armv7", "i686", "x86_64")
|
targets = listOf("aarch64", "armv7", "i686", "x86_64")
|
||||||
arches = listOf("arm64", "arm", "x86", "x86_64")
|
arches = listOf("arm64", "arm", "x86", "x86_64")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.webkit:webkit:1.5.0")
|
implementation("androidx.webkit:webkit:1.5.0")
|
||||||
implementation("androidx.appcompat:appcompat:1.5.1")
|
implementation("androidx.appcompat:appcompat:1.5.1")
|
||||||
implementation("com.google.android.material:material:1.7.0")
|
implementation("com.google.android.material:material:1.7.0")
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.4")
|
androidTestImplementation("androidx.test.ext:junit:1.1.4")
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
android.applicationVariants.all {
|
android.applicationVariants.all {
|
||||||
tasks["mergeUniversalReleaseJniLibFolders"].dependsOn(tasks["rustBuildRelease"])
|
tasks["mergeUniversalReleaseJniLibFolders"].dependsOn(tasks["rustBuildRelease"])
|
||||||
tasks["mergeUniversalDebugJniLibFolders"].dependsOn(tasks["rustBuildDebug"])
|
tasks["mergeUniversalDebugJniLibFolders"].dependsOn(tasks["rustBuildDebug"])
|
||||||
productFlavors.filter{ it.name != "universal" }.forEach { _ ->
|
productFlavors.filter { it.name != "universal" }.forEach { _ ->
|
||||||
val archAndBuildType = name.capitalize()
|
val archAndBuildType = name.capitalize()
|
||||||
tasks["merge${archAndBuildType}JniLibFolders"].dependsOn(tasks["rustBuild${archAndBuildType}"])
|
tasks["merge${archAndBuildType}JniLibFolders"].dependsOn(tasks["rustBuild${archAndBuildType}"])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/home/pierre/Documents/nym/nym/nym-connect-android/src-tauri/target/aarch64-linux-android/debug/libnym_connect_android.so
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/home/pierre/Documents/nym/nym/nym-connect-android/src-tauri/target/armv7-linux-androideabi/debug/libnym_connect_android.so
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/home/pierre/Documents/nym/nym/nym-connect-android/src-tauri/target/i686-linux-android/debug/libnym_connect_android.so
|
||||||
+5
-5
@@ -2,12 +2,12 @@
|
|||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.nym_connect_android" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
<style name="Theme.nym_connect_android" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">@color/purple_200</item>
|
<item name="colorPrimary">@color/grey_800</item>
|
||||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
<item name="colorPrimaryVariant">@color/grey_900</item>
|
||||||
<item name="colorOnPrimary">@color/black</item>
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
<!-- Secondary brand color. -->
|
<!-- Secondary brand color. -->
|
||||||
<item name="colorSecondary">@color/teal_200</item>
|
<item name="colorSecondary">@color/green_500</item>
|
||||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
<item name="colorSecondaryVariant">@color/green_900</item>
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||||
|
|||||||
+4
-5
@@ -1,10 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="purple_200">#FFBB86FC</color>
|
<color name="grey_900">#212121</color>
|
||||||
<color name="purple_500">#FF6200EE</color>
|
<color name="grey_800">#424242</color>
|
||||||
<color name="purple_700">#FF3700B3</color>
|
<color name="green_500">#4caf50</color>
|
||||||
<color name="teal_200">#FF03DAC5</color>
|
<color name="green_900">#1b5e20</color>
|
||||||
<color name="teal_700">#FF018786</color>
|
|
||||||
<color name="black">#FF000000</color>
|
<color name="black">#FF000000</color>
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
</resources>
|
</resources>
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">nym-connect-android</string>
|
<string name="app_name">Nym Connect</string>
|
||||||
</resources>
|
</resources>
|
||||||
+4
-4
@@ -2,12 +2,12 @@
|
|||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.nym_connect_android" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
<style name="Theme.nym_connect_android" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">@color/purple_500</item>
|
<item name="colorPrimary">@color/grey_800</item>
|
||||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
<item name="colorPrimaryVariant">@color/grey_900</item>
|
||||||
<item name="colorOnPrimary">@color/white</item>
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
<!-- Secondary brand color. -->
|
<!-- Secondary brand color. -->
|
||||||
<item name="colorSecondary">@color/teal_200</item>
|
<item name="colorSecondary">@color/green_500</item>
|
||||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
<item name="colorSecondaryVariant">@color/green_900</item>
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||||
|
|||||||
@@ -40,11 +40,6 @@ pub enum BackendError {
|
|||||||
#[from]
|
#[from]
|
||||||
source: ClientCoreError,
|
source: ClientCoreError,
|
||||||
},
|
},
|
||||||
#[error("{source}")]
|
|
||||||
ApiClientError {
|
|
||||||
#[from]
|
|
||||||
source: crate::operations::growth::api_client::ApiClientError,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("could not send disconnect signal to the SOCKS5 client")]
|
#[error("could not send disconnect signal to the SOCKS5 client")]
|
||||||
CoundNotSendDisconnectSignal,
|
CoundNotSendDisconnectSignal,
|
||||||
|
|||||||
@@ -1,270 +0,0 @@
|
|||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum ApiClientError {
|
|
||||||
#[error("{source}")]
|
|
||||||
Reqwest {
|
|
||||||
#[from]
|
|
||||||
source: reqwest::Error,
|
|
||||||
},
|
|
||||||
#[error("{source}")]
|
|
||||||
SerdeJson {
|
|
||||||
#[from]
|
|
||||||
source: serde_json::Error,
|
|
||||||
},
|
|
||||||
#[error("{0}")]
|
|
||||||
Status(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
const API_BASE_URL: &str = "https://growth-api.nymtech.net";
|
|
||||||
|
|
||||||
// For development mode, switch to this
|
|
||||||
// const API_BASE_URL: &str = "http://localhost:8000";
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct GrowthApiClient {
|
|
||||||
base_url: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GrowthApiClient {
|
|
||||||
pub fn new(resource_base: &str) -> Self {
|
|
||||||
let base_url = std::env::var("API_BASE_URL").unwrap_or_else(|_| API_BASE_URL.to_string());
|
|
||||||
GrowthApiClient {
|
|
||||||
base_url: format!("{base_url}{resource_base}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn registrations() -> Registrations {
|
|
||||||
Registrations::new(GrowthApiClient::new("/v1/tne"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn daily_draws() -> DailyDraws {
|
|
||||||
DailyDraws::new(GrowthApiClient::new("/v1/tne/daily_draw"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn get<T: DeserializeOwned>(&self, url: &str) -> Result<T, ApiClientError> {
|
|
||||||
log::info!(">>> GET {}", url);
|
|
||||||
let proxy = reqwest::Proxy::all("socks5h://127.0.0.1:1080")?;
|
|
||||||
let client = reqwest::Client::builder()
|
|
||||||
.proxy(proxy)
|
|
||||||
.timeout(std::time::Duration::from_secs(10))
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
match client.get(format!("{}{}", self.base_url, url)).send().await {
|
|
||||||
Ok(res) => {
|
|
||||||
if res.status().is_client_error() || res.status().is_server_error() {
|
|
||||||
log::error!("<<< {}", res.status());
|
|
||||||
return Err(ApiClientError::Status(res.status().to_string()));
|
|
||||||
}
|
|
||||||
match res.text().await {
|
|
||||||
Ok(response_body) => {
|
|
||||||
log::info!("<<< {}", response_body);
|
|
||||||
match serde_json::from_str(&response_body) {
|
|
||||||
Ok(res) => Ok(res),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("<<< JSON parsing error: {}", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("<<< Request error: {}", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("<<< Response parsing error: {}", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: use the method in `operations::http` instead
|
|
||||||
pub(crate) async fn post<REQ: Serialize + ?Sized, RESP: DeserializeOwned>(
|
|
||||||
&self,
|
|
||||||
url: &str,
|
|
||||||
body: &REQ,
|
|
||||||
) -> Result<RESP, ApiClientError> {
|
|
||||||
log::info!(">>> POST {}", url);
|
|
||||||
let proxy = reqwest::Proxy::all("socks5h://127.0.0.1:1080")?;
|
|
||||||
let client = reqwest::Client::builder()
|
|
||||||
.proxy(proxy)
|
|
||||||
.timeout(std::time::Duration::from_secs(10))
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
match client
|
|
||||||
.post(format!("{}{}", self.base_url, url))
|
|
||||||
.json(body)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(res) => {
|
|
||||||
if res.status().is_client_error() || res.status().is_server_error() {
|
|
||||||
log::error!("<<< {}", res.status());
|
|
||||||
return Err(ApiClientError::Status(res.status().to_string()));
|
|
||||||
}
|
|
||||||
match res.text().await {
|
|
||||||
Ok(response_body) => {
|
|
||||||
log::info!("<<< {}", response_body);
|
|
||||||
match serde_json::from_str(&response_body) {
|
|
||||||
Ok(res) => Ok(res),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("<<< JSON parsing error: {}", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("<<< Request error: {}", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("<<< Response parsing error: {}", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct ClientIdPartial {
|
|
||||||
pub client_id: String,
|
|
||||||
pub client_id_signature: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct Registration {
|
|
||||||
pub id: String,
|
|
||||||
pub client_id: String,
|
|
||||||
pub timestamp: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct Ping {
|
|
||||||
pub client_id: String,
|
|
||||||
pub timestamp: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Registrations {
|
|
||||||
client: GrowthApiClient,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Registrations {
|
|
||||||
pub fn new(client: GrowthApiClient) -> Self {
|
|
||||||
Registrations { client }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn register(
|
|
||||||
&self,
|
|
||||||
registration: &ClientIdPartial,
|
|
||||||
) -> Result<Registration, ApiClientError> {
|
|
||||||
self.client.post("/register", ®istration).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub async fn unregister(&self, registration: &ClientIdPartial) -> Result<(), ApiClientError> {
|
|
||||||
self.client.post("/unregister", ®istration).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub async fn status(&self, registration: &ClientIdPartial) -> Result<(), ApiClientError> {
|
|
||||||
self.client.post("/status", ®istration).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn ping(&self, registration: &ClientIdPartial) -> Result<(), ApiClientError> {
|
|
||||||
self.client.post("/ping", ®istration).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub async fn health(&self) -> Result<(), ApiClientError> {
|
|
||||||
self.client.get("/health").await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct DrawEntryPartial {
|
|
||||||
pub draw_id: String,
|
|
||||||
pub client_id: String,
|
|
||||||
pub client_id_signature: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct DrawEntry {
|
|
||||||
pub id: String,
|
|
||||||
pub draw_id: String,
|
|
||||||
pub timestamp: String,
|
|
||||||
pub status: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct DrawWithWordOfTheDay {
|
|
||||||
pub id: String,
|
|
||||||
pub start_utc: String,
|
|
||||||
pub end_utc: String,
|
|
||||||
pub word_of_the_day: Option<String>,
|
|
||||||
pub last_modified: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct ClaimPartial {
|
|
||||||
pub draw_id: String,
|
|
||||||
pub registration_id: String,
|
|
||||||
pub client_id: String,
|
|
||||||
pub client_id_signature: String,
|
|
||||||
pub wallet_address: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct Winner {
|
|
||||||
pub id: String,
|
|
||||||
pub client_id: String,
|
|
||||||
pub draw_id: String,
|
|
||||||
pub timestamp: String,
|
|
||||||
pub winner_reg_id: String,
|
|
||||||
pub winner_wallet_address: Option<String>,
|
|
||||||
pub winner_claim_timestamp: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DailyDraws {
|
|
||||||
client: GrowthApiClient,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DailyDraws {
|
|
||||||
pub fn new(client: GrowthApiClient) -> Self {
|
|
||||||
DailyDraws { client }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn current(&self) -> Result<DrawWithWordOfTheDay, ApiClientError> {
|
|
||||||
self.client.get("/current").await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn next(&self) -> Result<DrawWithWordOfTheDay, ApiClientError> {
|
|
||||||
self.client.get("/next").await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub async fn status(&self, draw_id: &str) -> Result<DrawWithWordOfTheDay, ApiClientError> {
|
|
||||||
self.client.get(format!("/status/{draw_id}").as_str()).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn enter(&self, entry: &DrawEntryPartial) -> Result<DrawEntry, ApiClientError> {
|
|
||||||
self.client.post("/enter", entry).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn entries(
|
|
||||||
&self,
|
|
||||||
client_id: &ClientIdPartial,
|
|
||||||
) -> Result<Vec<DrawEntry>, ApiClientError> {
|
|
||||||
self.client.post("/entries", client_id).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn claim(&self, claim: &ClaimPartial) -> Result<Winner, ApiClientError> {
|
|
||||||
self.client.post("/claim", claim).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
use rust_embed::RustEmbed;
|
|
||||||
extern crate yaml_rust;
|
|
||||||
use yaml_rust::YamlLoader;
|
|
||||||
|
|
||||||
#[derive(RustEmbed)]
|
|
||||||
#[folder = "../src/components/Growth/content/"]
|
|
||||||
#[include = "*.yaml"]
|
|
||||||
#[exclude = "*.mdx"]
|
|
||||||
struct Asset;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NotificationContent {
|
|
||||||
pub title: String,
|
|
||||||
pub body: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Notifications {
|
|
||||||
pub you_are_in_draw: NotificationContent,
|
|
||||||
pub take_part: NotificationContent,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Content {}
|
|
||||||
|
|
||||||
const RESOURCE_ERROR: &str = "❌ RESOURCE ERROR";
|
|
||||||
|
|
||||||
fn get_as_string_or_error_message(value: &yaml_rust::Yaml) -> String {
|
|
||||||
value.as_str().unwrap_or(RESOURCE_ERROR).to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Content {
|
|
||||||
pub fn get_notifications() -> Notifications {
|
|
||||||
let content = Asset::get("en.yaml").unwrap();
|
|
||||||
let s = std::str::from_utf8(content.data.as_ref()).unwrap();
|
|
||||||
let content = YamlLoader::load_from_str(s).unwrap();
|
|
||||||
let content = &content[0];
|
|
||||||
|
|
||||||
Notifications {
|
|
||||||
you_are_in_draw: NotificationContent {
|
|
||||||
title: get_as_string_or_error_message(
|
|
||||||
&content["testAndEarn"]["notifications"]["youAreInDraw"]["title"],
|
|
||||||
),
|
|
||||||
body: get_as_string_or_error_message(
|
|
||||||
&content["testAndEarn"]["notifications"]["youAreInDraw"]["body"],
|
|
||||||
),
|
|
||||||
},
|
|
||||||
take_part: NotificationContent {
|
|
||||||
title: get_as_string_or_error_message(
|
|
||||||
&content["testAndEarn"]["notifications"]["takePart"]["title"],
|
|
||||||
),
|
|
||||||
body: get_as_string_or_error_message(
|
|
||||||
&content["testAndEarn"]["notifications"]["takePart"]["body"],
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
pub mod api_client;
|
|
||||||
pub mod assets;
|
|
||||||
pub mod test_and_earn;
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
use crate::error::BackendError;
|
|
||||||
use crate::operations::export::get_identity_key;
|
|
||||||
use crate::operations::growth::api_client::{
|
|
||||||
ClaimPartial, ClientIdPartial, DrawEntry, DrawEntryPartial, DrawWithWordOfTheDay,
|
|
||||||
GrowthApiClient, Registration, Winner,
|
|
||||||
};
|
|
||||||
use crate::State;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::sync::Arc;
|
|
||||||
#[cfg(desktop)]
|
|
||||||
use tauri::api::notification::Notification;
|
|
||||||
use tauri::Manager;
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
async fn get_client_id(
|
|
||||||
state: &tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<ClientIdPartial, BackendError> {
|
|
||||||
let keypair = get_identity_key(state).await?;
|
|
||||||
let client_id = keypair.public_key().to_base58_string();
|
|
||||||
let client_id_signature = keypair
|
|
||||||
.private_key()
|
|
||||||
.sign(client_id.as_bytes())
|
|
||||||
.to_base58_string();
|
|
||||||
Ok(ClientIdPartial {
|
|
||||||
client_id,
|
|
||||||
client_id_signature,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_get_client_id(
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<ClientIdPartial, BackendError> {
|
|
||||||
get_client_id(&state).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_take_part(
|
|
||||||
app_handle: tauri::AppHandle,
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<Registration, BackendError> {
|
|
||||||
let notifications = super::assets::Content::get_notifications();
|
|
||||||
|
|
||||||
let client_id = get_client_id(&state).await?;
|
|
||||||
let registration = GrowthApiClient::registrations()
|
|
||||||
.register(&client_id)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
log::info!("<<< Test&Earn: registration details: {:?}", registration);
|
|
||||||
|
|
||||||
#[cfg(desktop)]
|
|
||||||
if let Err(e) = Notification::new(&app_handle.config().tauri.bundle.identifier)
|
|
||||||
.title(notifications.take_part.title)
|
|
||||||
.body(notifications.take_part.body)
|
|
||||||
.show()
|
|
||||||
{
|
|
||||||
log::error!("Could not show notification. Error = {:?}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(registration)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub struct Draws {
|
|
||||||
pub current: Option<DrawWithWordOfTheDay>,
|
|
||||||
pub next: Option<DrawWithWordOfTheDay>,
|
|
||||||
pub draws: Vec<DrawEntry>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_get_draws(client_details: ClientIdPartial) -> Result<Draws, BackendError> {
|
|
||||||
let draws_api = GrowthApiClient::daily_draws();
|
|
||||||
|
|
||||||
let current = draws_api.current().await.ok();
|
|
||||||
let next = draws_api.next().await.ok();
|
|
||||||
let draws = draws_api.entries(&client_details).await?;
|
|
||||||
|
|
||||||
Ok(Draws {
|
|
||||||
current,
|
|
||||||
next,
|
|
||||||
draws,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_enter_draw(
|
|
||||||
client_details: ClientIdPartial,
|
|
||||||
draw_id: String,
|
|
||||||
) -> Result<DrawEntry, BackendError> {
|
|
||||||
Ok(GrowthApiClient::daily_draws()
|
|
||||||
.enter(&DrawEntryPartial {
|
|
||||||
draw_id,
|
|
||||||
client_id: client_details.client_id,
|
|
||||||
client_id_signature: client_details.client_id_signature,
|
|
||||||
})
|
|
||||||
.await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_submit_wallet_address(
|
|
||||||
client_details: ClientIdPartial,
|
|
||||||
draw_id: String,
|
|
||||||
wallet_address: String,
|
|
||||||
registration_id: String,
|
|
||||||
) -> Result<Winner, BackendError> {
|
|
||||||
Ok(GrowthApiClient::daily_draws()
|
|
||||||
.claim(&ClaimPartial {
|
|
||||||
draw_id,
|
|
||||||
client_id: client_details.client_id,
|
|
||||||
client_id_signature: client_details.client_id_signature,
|
|
||||||
wallet_address,
|
|
||||||
registration_id,
|
|
||||||
})
|
|
||||||
.await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_ping(client_details: ClientIdPartial) -> Result<(), BackendError> {
|
|
||||||
log::info!("Test&Earn is sending a ping...");
|
|
||||||
Ok(GrowthApiClient::registrations()
|
|
||||||
.ping(&client_details)
|
|
||||||
.await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(desktop)]
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn growth_tne_toggle_window(
|
|
||||||
app_handle: tauri::AppHandle,
|
|
||||||
window_title: Option<String>,
|
|
||||||
) -> Result<(), BackendError> {
|
|
||||||
if let Some(window) = app_handle.windows().get("growth") {
|
|
||||||
log::info!("Closing growth window...");
|
|
||||||
if let Err(e) = window.close() {
|
|
||||||
log::error!("Unable to close growth window: {:?}", e);
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("Creating growth window...");
|
|
||||||
match tauri::WindowBuilder::new(
|
|
||||||
&app_handle,
|
|
||||||
"growth",
|
|
||||||
tauri::WindowUrl::App("growth.html".into()),
|
|
||||||
)
|
|
||||||
.title(window_title.unwrap_or_else(|| "NymConnect Test&Earn".to_string()))
|
|
||||||
.build()
|
|
||||||
{
|
|
||||||
Ok(window) => {
|
|
||||||
if let Err(e) = window.set_focus() {
|
|
||||||
log::error!("Unable to focus growth window: {:?}", e);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Unable to create growth window: {:?}", e);
|
|
||||||
Err(BackendError::NewWindowError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
pub mod connection;
|
pub mod connection;
|
||||||
pub mod directory;
|
pub mod directory;
|
||||||
pub mod export;
|
pub mod export;
|
||||||
pub mod growth;
|
|
||||||
pub mod help;
|
pub mod help;
|
||||||
pub mod http;
|
pub mod http;
|
||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user