Merge pull request #5659 from nymtech/benny/revamp-api-tests
Adding fresh nym-api tests and workflow
This commit is contained in:
@@ -102,6 +102,8 @@ jobs:
|
||||
- name: Run all tests
|
||||
if: contains(matrix.os, 'ubuntu')
|
||||
uses: actions-rs/cargo@v1
|
||||
env:
|
||||
NYM_API: https://sandbox-nym-api1.nymtech.net/api
|
||||
with:
|
||||
command: test
|
||||
args: --workspace
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Integration Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "nym-api/**"
|
||||
- "tests/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
integration-tests:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
API_BASE_URL: http://localhost:8000
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev
|
||||
|
||||
- name: Build nym-api
|
||||
run: cargo build --package nym-api
|
||||
|
||||
- name: Run nym-api in the background
|
||||
run: |
|
||||
./target/debug/nym-api &
|
||||
|
||||
- name: Wait for nym-api to come alive
|
||||
run: |
|
||||
for i in {1..20}; do
|
||||
curl -sSf http://localhost:8000/v1/status/config-score-details && break
|
||||
echo "Waiting for nym-api to start..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Run integration tests
|
||||
env:
|
||||
NYM_API: https://sandbox-nym-api1.nymtech.net/api
|
||||
run: cargo test --test public-api-tests -- --nocapture
|
||||
Generated
+15
-7
@@ -2185,6 +2185,12 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.7"
|
||||
@@ -4697,7 +4703,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -4708,6 +4714,7 @@ dependencies = [
|
||||
"bip39",
|
||||
"bs58",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap",
|
||||
"console-subscriber",
|
||||
"cosmwasm-std",
|
||||
@@ -4717,6 +4724,7 @@ dependencies = [
|
||||
"cw4",
|
||||
"dashmap",
|
||||
"dirs",
|
||||
"dotenv",
|
||||
"futures",
|
||||
"getset",
|
||||
"humantime-serde",
|
||||
@@ -4949,7 +4957,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.52"
|
||||
version = "1.1.53"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
@@ -5032,7 +5040,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.52"
|
||||
version = "1.1.53"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -6067,7 +6075,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.53"
|
||||
version = "1.1.54"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -6118,7 +6126,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -6513,7 +6521,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.52"
|
||||
version = "1.1.53"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -7116,7 +7124,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.17"
|
||||
version = "0.1.18"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
||||
@@ -168,8 +168,9 @@ generate-typescript:
|
||||
cd tools/ts-rs-cli && cargo run && cd ../..
|
||||
yarn types:lint:fix
|
||||
|
||||
# Run the integration tests for public nym-api endpoints
|
||||
run-api-tests:
|
||||
cd nym-api/tests/functional_test && yarn test:qa
|
||||
dotenv -f envs/sandbox.env -- cargo test --test public-api-tests
|
||||
|
||||
# Build debian package, and update PPA
|
||||
deb-cli: build-nym-cli
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.52"
|
||||
version = "1.1.53"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.52"
|
||||
version = "1.1.53"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.55"
|
||||
version = "1.1.56"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
rust-version.workspace = true
|
||||
@@ -120,6 +120,7 @@ nym-http-api-common = { path = "../common/http-api-common", features = ["utoipa"
|
||||
nym-serde-helpers = { path = "../common/serde-helpers", features = ["date"] }
|
||||
nym-ticketbooks-merkle = { path = "../common/ticketbooks-merkle" }
|
||||
nym-statistics-common = { path = "../common/statistics" }
|
||||
chrono.workspace = true
|
||||
|
||||
[features]
|
||||
no-reward = []
|
||||
@@ -142,6 +143,7 @@ cw3 = { workspace = true }
|
||||
cw-utils = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
dotenv = "0.15"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.vscode
|
||||
node_modules
|
||||
build
|
||||
coverage
|
||||
dist
|
||||
.cache
|
||||
jest.config.js
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"import/extensions": "off",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }],
|
||||
"import/prefer-default-export": "off",
|
||||
"prettier/prettier": ["error"]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.ts", "**/*.tsx"],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"no-shadow": "off",
|
||||
"@typescript-eslint/no-shadow": ["error"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
node_modules
|
||||
dist
|
||||
coverage/
|
||||
.DS_Store
|
||||
.idea/
|
||||
junit.xml
|
||||
@@ -1,30 +0,0 @@
|
||||
<!-- ABOUT THE PROJECT -->
|
||||
## nym-api-test suite
|
||||
|
||||
A Typescript test framework utilising Jest and Node to perform tests against the NYM validator-apis.
|
||||
|
||||
<!-- GETTING STARTED -->
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
1. Having `yarn` install on your machine
|
||||
1. Install all the packages - `yarn install`
|
||||
2. Peeping the package.json will show you the commands to run for the tests
|
||||
|
||||
|
||||
<!-- USAGE EXAMPLES -->
|
||||
## Usage
|
||||
|
||||
1. Run the testsuite - currently the configuration hasn't fully been set up to switch envs
|
||||
```
|
||||
yarn test
|
||||
```
|
||||
|
||||
## ToDo
|
||||
1. Finish happy and negative test scenarios
|
||||
2. Full reporting
|
||||
3. Fully functioniting env switching
|
||||
4. Run in CI
|
||||
5. Docker?
|
||||
|
||||
Kudos to jmfiola21@gmail.com for the baseline of this framework
|
||||
@@ -1,29 +0,0 @@
|
||||
import ContractCache from "../../src/endpoints/CirculatingSupply";
|
||||
let contract: ContractCache;
|
||||
|
||||
describe("Get circulating supply", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
contract = new ContractCache();
|
||||
});
|
||||
|
||||
it("Get circulating supply amounts", async (): Promise<void> => {
|
||||
const response = await contract.getCirculatingSupply();
|
||||
const totalsupply: number = +response.total_supply.amount;
|
||||
const mixmining: number = +response.mixmining_reserve.amount;
|
||||
const vest: number = +response.vesting_tokens.amount;
|
||||
const circsupply: number = +response.circulating_supply.amount;
|
||||
|
||||
expect(typeof response.vesting_tokens.amount).toBe("string");
|
||||
expect(totalsupply - mixmining - vest).toStrictEqual(circsupply);
|
||||
});
|
||||
|
||||
it("Get total supply value", async (): Promise<void> => {
|
||||
const response = await contract.getTotalSupplyValue();
|
||||
expect(response).toStrictEqual(1000000000);
|
||||
});
|
||||
|
||||
it("Get circulating supply value", async (): Promise<void> => {
|
||||
const response = await contract.getCirculatingSupplyValue();
|
||||
expect(typeof response).toBe("number");
|
||||
});
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
import ContractCache from "../../src/endpoints/ContractCache";
|
||||
|
||||
let contract: ContractCache;
|
||||
|
||||
describe("Get epoch info", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
contract = new ContractCache();
|
||||
});
|
||||
|
||||
it("Get epoch reward params", async (): Promise<void> => {
|
||||
const response = await contract.getEpochRewardParams();
|
||||
expect(typeof response.interval.reward_pool).toBe("string");
|
||||
expect(typeof response.interval.staking_supply_scale_factor).toBe("string");
|
||||
expect(typeof response.interval.staking_supply).toBe("string");
|
||||
expect(typeof response.interval.epoch_reward_budget).toBe("string");
|
||||
expect(typeof response.interval.stake_saturation_point).toBe("string");
|
||||
expect(typeof response.interval.sybil_resistance).toBe("string");
|
||||
expect(typeof response.interval.active_set_work_factor).toBe("string");
|
||||
expect(typeof response.interval.interval_pool_emission).toBe("string");
|
||||
expect(typeof response.active_set_size).toBe("number");
|
||||
expect(typeof response.rewarded_set_size).toBe("number");
|
||||
});
|
||||
|
||||
it("Get current epoch", async (): Promise<void> => {
|
||||
const response = await contract.getCurrentEpoch();
|
||||
expect(typeof response.id).toBe("number");
|
||||
expect(typeof response.epochs_in_interval).toBe("number");
|
||||
expect(typeof response.current_epoch_id).toBe("number");
|
||||
expect(typeof response.current_epoch_start).toBe("string");
|
||||
expect(typeof response.epoch_length.secs).toBe("number");
|
||||
expect(typeof response.epoch_length.nanos).toBe("number");
|
||||
expect(typeof response.total_elapsed_epochs).toBe("number");
|
||||
});
|
||||
});
|
||||
@@ -1,49 +0,0 @@
|
||||
import ContractCache from "../../../src/endpoints/ContractCache";
|
||||
|
||||
let contract: ContractCache;
|
||||
|
||||
describe("Get gateway data", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
contract = new ContractCache();
|
||||
});
|
||||
|
||||
it("Get all gateways", async (): Promise<void> => {
|
||||
const response = await contract.getGateways();
|
||||
response.forEach((gateway) => {
|
||||
//overview
|
||||
expect(typeof gateway.owner).toBe("string");
|
||||
expect(typeof gateway.block_height).toBe("number");
|
||||
|
||||
if (gateway.proxy === null) {
|
||||
return true;
|
||||
} else {
|
||||
expect(typeof gateway.proxy).toBe("string");
|
||||
}
|
||||
|
||||
//pledge_amount
|
||||
expect(typeof gateway.pledge_amount.denom).toBe("string");
|
||||
expect(typeof gateway.pledge_amount.amount).toBe("string");
|
||||
|
||||
//gateway
|
||||
expect(typeof gateway.gateway.host).toBe("string");
|
||||
expect(typeof gateway.gateway.mix_port).toBe("number");
|
||||
expect(typeof gateway.gateway.clients_port).toBe("number");
|
||||
expect(typeof gateway.gateway.location).toBe("string");
|
||||
expect(typeof gateway.gateway.sphinx_key).toBe("string");
|
||||
expect(typeof gateway.gateway.identity_key).toBe("string");
|
||||
expect(typeof gateway.gateway.version).toBe("string");
|
||||
});
|
||||
});
|
||||
|
||||
it("Get blacklisted gateways", async (): Promise<void> => {
|
||||
const response = await contract.getBlacklistedGateways();
|
||||
if (response === null) {
|
||||
// no blacklisted gateways returns an empty array
|
||||
expect(response).toBeNull();
|
||||
} else {
|
||||
response.forEach(function (value) {
|
||||
expect(typeof value).toBe("string");
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,248 +0,0 @@
|
||||
import ContractCache from "../../../src/endpoints/ContractCache";
|
||||
import ConfigHandler from "../../../../../common/api-test-utils/config/configHandler"
|
||||
|
||||
let contract: ContractCache;
|
||||
let config: ConfigHandler;
|
||||
|
||||
describe("Get mixnode data", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
contract = new ContractCache();
|
||||
config = ConfigHandler.getInstance();
|
||||
});
|
||||
|
||||
it("Get all mixnodes", async (): Promise<void> => {
|
||||
const response = await contract.getMixnodes();
|
||||
response.forEach((mixnode) => {
|
||||
//bond information overview
|
||||
expect(typeof mixnode.bond_information.mix_id).toBe("number");
|
||||
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.denom).toBe(
|
||||
"string"
|
||||
);
|
||||
expect(typeof mixnode.bond_information.layer).toBe("number");
|
||||
expect(typeof mixnode.bond_information.bonding_height).toBe("number");
|
||||
expect(typeof mixnode.bond_information.is_unbonding).toBe("boolean");
|
||||
|
||||
if (mixnode.bond_information.proxy === null) {
|
||||
return true;
|
||||
} else {
|
||||
expect(typeof mixnode.bond_information.proxy).toBe("string");
|
||||
}
|
||||
|
||||
//mixnode
|
||||
expect(typeof mixnode.bond_information.mix_node.host).toBe("string");
|
||||
expect(mixnode.bond_information.mix_node.http_api_port).toStrictEqual(
|
||||
8000
|
||||
);
|
||||
expect(typeof mixnode.bond_information.mix_node.verloc_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(typeof mixnode.bond_information.mix_node.verloc_port).toBe(
|
||||
"number"
|
||||
);
|
||||
|
||||
const identitykey = mixnode.bond_information.mix_node.identity_key;
|
||||
if (typeof identitykey === "string") {
|
||||
if (identitykey.length === 43) {
|
||||
return true;
|
||||
} else expect(identitykey).toHaveLength(44);
|
||||
}
|
||||
|
||||
const sphinx = mixnode.bond_information.mix_node.sphinx_key;
|
||||
if (typeof sphinx === "string") {
|
||||
if (sphinx.length === 43) {
|
||||
return true;
|
||||
} else expect(sphinx).toHaveLength(44);
|
||||
}
|
||||
|
||||
//rewarding details
|
||||
expect(
|
||||
typeof mixnode.rewarding_details.cost_params.profit_margin_percent
|
||||
).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.delegates).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.last_rewarded_epoch).toBe(
|
||||
"number"
|
||||
);
|
||||
expect(typeof mixnode.rewarding_details.unique_delegations).toBe(
|
||||
"number"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("Get all mixnodes detailed", async (): Promise<void> => {
|
||||
const response = await contract.getMixnodesDetailed();
|
||||
response.forEach((mixnode) => {
|
||||
// overview details
|
||||
expect(typeof mixnode.estimated_delegators_apy).toBe("string");
|
||||
expect(typeof mixnode.estimated_operator_apy).toBe("string");
|
||||
expect(typeof mixnode.performance).toBe("string");
|
||||
expect(typeof mixnode.uncapped_stake_saturation).toBe("string");
|
||||
expect(typeof mixnode.stake_saturation).toBe("string");
|
||||
// TODO why family is tempermental
|
||||
// expect(typeof mixnode.family).toBe("string");
|
||||
|
||||
//mixnode details bond info
|
||||
expect(typeof mixnode.mixnode_details.bond_information.mix_id).toBe(
|
||||
"number"
|
||||
);
|
||||
expect(typeof mixnode.mixnode_details.bond_information.owner).toBe(
|
||||
"string"
|
||||
);
|
||||
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) {
|
||||
return true;
|
||||
} else {
|
||||
expect(typeof mixnode.mixnode_details.bond_information.proxy).toBe(
|
||||
"string"
|
||||
);
|
||||
}
|
||||
|
||||
//mixnode
|
||||
expect(
|
||||
typeof mixnode.mixnode_details.bond_information.mix_node.host
|
||||
).toBe("string");
|
||||
expect(
|
||||
mixnode.mixnode_details.bond_information.mix_node.http_api_port
|
||||
).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(
|
||||
typeof mixnode.mixnode_details.bond_information.mix_node.verloc_port
|
||||
).toBe("number");
|
||||
|
||||
const identitykey2 =
|
||||
mixnode.mixnode_details.bond_information.mix_node.identity_key;
|
||||
if (typeof identitykey2 === "string") {
|
||||
if (identitykey2.length === 43) {
|
||||
return true;
|
||||
} else expect(identitykey2).toHaveLength(44);
|
||||
}
|
||||
|
||||
const sphinx2 =
|
||||
mixnode.mixnode_details.bond_information.mix_node.sphinx_key;
|
||||
if (typeof sphinx2 === "string") {
|
||||
if (sphinx2.length === 43) {
|
||||
return true;
|
||||
} else expect(sphinx2).toHaveLength(44);
|
||||
}
|
||||
|
||||
//mixnode rewarding info
|
||||
expect(
|
||||
typeof mixnode.mixnode_details.rewarding_details.cost_params
|
||||
.profit_margin_percent
|
||||
).toBe("string");
|
||||
expect(
|
||||
typeof mixnode.mixnode_details.rewarding_details.cost_params
|
||||
.interval_operating_cost.denom
|
||||
).toBe("string");
|
||||
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> => {
|
||||
const response = await contract.getActiveMixnodes();
|
||||
response.forEach(function (mixnode) {
|
||||
expect(
|
||||
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> => {
|
||||
const response = await contract.getActiveMixnodesDetailed();
|
||||
response.forEach(function (mixnode) {
|
||||
expect(
|
||||
mixnode.mixnode_details.rewarding_details.cost_params
|
||||
.profit_margin_percent
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it("Get rewarded mixnodes", async (): Promise<void> => {
|
||||
const response = await contract.getRewardedMixnodes();
|
||||
response.forEach(function (mixnode) {
|
||||
expect(mixnode.rewarding_details.last_rewarded_epoch).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it("Get rewarded mixnodes detailed", async (): Promise<void> => {
|
||||
const response = await contract.getRewardedMixnodesDetailed();
|
||||
response.forEach(function (mixnode) {
|
||||
expect(
|
||||
mixnode.mixnode_details.rewarding_details.last_rewarded_epoch
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it("Get blacklisted mixnodes", async (): Promise<void> => {
|
||||
const response = await contract.getBlacklistedMixnodes();
|
||||
if (response === null) {
|
||||
// no blacklisted mixnodes returns an empty array
|
||||
expect(response).toBeNull();
|
||||
} else {
|
||||
response.forEach(function (value) {
|
||||
expect(typeof value).toBe("number");
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
import ContractCache from "../../src/endpoints/ContractCache";
|
||||
let contract: ContractCache;
|
||||
|
||||
describe("Get service provider info", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
contract = new ContractCache();
|
||||
});
|
||||
|
||||
it("Get service providers", async (): Promise<void> => {
|
||||
const response = await contract.getServiceProviders();
|
||||
if ("[service_id]" in response) {
|
||||
response.services.forEach((x) => {
|
||||
expect(typeof x.service.nym_address.address).toBe("string");
|
||||
expect(typeof x.service.service_type).toBe("string");
|
||||
expect(typeof x.service.block_height).toBe("number");
|
||||
expect(typeof x.service.announcer).toBe("string");
|
||||
expect(typeof x.service.deposit.amount).toBe("string");
|
||||
expect(typeof x.service.deposit.denom).toBe("string");
|
||||
});
|
||||
} else if ("[ ]" in response) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
it("Get Nym address names", async (): Promise<void> => {
|
||||
const response = await contract.getNymAddressNames();
|
||||
if ("[id]" in response) {
|
||||
response.names.forEach((x) => {
|
||||
expect(typeof x.name.name).toBe("string");
|
||||
expect(typeof x.name.address.gateway_id).toBe("string");
|
||||
expect(typeof x.id).toBe("number");
|
||||
|
||||
});
|
||||
} else if ("[ ]" in response) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,47 +0,0 @@
|
||||
import NetworkTypes from "../../src/endpoints/Network";
|
||||
let contract: NetworkTypes;
|
||||
|
||||
describe("Get network and contract details", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
contract = new NetworkTypes();
|
||||
});
|
||||
|
||||
it("Get network details", async (): Promise<void> => {
|
||||
const response = await contract.getNetworkDetails();
|
||||
expect(typeof response.network.network_name).toBe("string");
|
||||
});
|
||||
|
||||
it("Get nym contract info", async (): Promise<void> => {
|
||||
const response = await contract.getNymContractInfo();
|
||||
for (const key in response) {
|
||||
if (response.hasOwnProperty(key)) {
|
||||
const additionalProp = response[key];
|
||||
expect(typeof additionalProp.address).toBe("string");
|
||||
if ("build_timestamp" in response) {
|
||||
expect(typeof additionalProp.details.contract).toBe("string");
|
||||
expect(typeof additionalProp.details.version).toBe("string");
|
||||
}
|
||||
else if (additionalProp.details === null) {
|
||||
expect(additionalProp.details).toBeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("Get nym contract info detailed", async (): Promise<void> => {
|
||||
const response = await contract.getNymContractDetailedInfo();
|
||||
for (const key in response) {
|
||||
if (response.hasOwnProperty(key)) {
|
||||
const additionalProp = response[key];
|
||||
expect(typeof additionalProp.address).toBe("string");
|
||||
if ("build_timestamp" in response) {
|
||||
expect(typeof additionalProp.details.build_timestamp).toBe("string");
|
||||
expect(typeof additionalProp.details.rustc_version).toBe("string");
|
||||
}
|
||||
else if (additionalProp.details === null) {
|
||||
expect(additionalProp.details).toBeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,80 +0,0 @@
|
||||
import Status from "../../src/endpoints/Status";
|
||||
import ConfigHandler from "../../../../common/api-test-utils/config/configHandler"
|
||||
|
||||
let status: Status;
|
||||
let config: ConfigHandler;
|
||||
|
||||
describe("Get gateway data", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
status = new Status();
|
||||
config = ConfigHandler.getInstance();
|
||||
});
|
||||
|
||||
it("Get all gateways detailed", async (): Promise<void> => {
|
||||
const response = await status.getDetailedGateways();
|
||||
response.forEach((x) => {
|
||||
expect(typeof x.gateway_bond.owner).toBe("string");
|
||||
expect(typeof x.performance).toBe("string");
|
||||
expect(typeof x.node_performance.last_24h).toBe("string");
|
||||
});
|
||||
});
|
||||
|
||||
it("Get all gateways unfiltered", async (): Promise<void> => {
|
||||
const response = await status.getUnfilteredGateways();
|
||||
response.forEach((x) => {
|
||||
expect(typeof x.gateway_bond.owner).toBe("string");
|
||||
expect(typeof x.performance).toBe("string");
|
||||
expect(typeof x.node_performance.last_24h).toBe("string");
|
||||
});
|
||||
});
|
||||
|
||||
it("Get a gateway history", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayHistory(identity_key);
|
||||
|
||||
if ("identity" in response) {
|
||||
response.history.forEach((x) => {
|
||||
expect(typeof x.date).toBe("string");
|
||||
expect(typeof x.uptime).toBe("number");
|
||||
});
|
||||
expect(identity_key).toStrictEqual(response.identity);
|
||||
expect(typeof response.owner).toBe("string");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain(
|
||||
"could not find uptime history associated with gateway"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Get gateway core status count", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayCoreCount(identity_key);
|
||||
expect(identity_key).toStrictEqual(response.identity);
|
||||
expect(typeof response.count).toBe("number");
|
||||
});
|
||||
|
||||
it("Get gateway average uptime", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayAverageUptime(identity_key);
|
||||
if ("identity" in response) {
|
||||
expect(identity_key).toStrictEqual(response.identity);
|
||||
expect(typeof response.avg_uptime).toBe("number");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("gateway bond not found");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get a gateway status report", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayStatusReport(identity_key);
|
||||
if ("identity" in response) {
|
||||
expect(identity_key).toStrictEqual(response.identity);
|
||||
expect(typeof response.owner).toBe("string");
|
||||
expect(typeof response.most_recent).toBe("number");
|
||||
expect(typeof response.last_hour).toBe("number");
|
||||
expect(typeof response.last_day).toBe("number");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("gateway bond not found");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,165 +0,0 @@
|
||||
import Status from "../../src/endpoints/Status";
|
||||
import ConfigHandler from "../../../../common/api-test-utils/config/configHandler";
|
||||
|
||||
let status: Status;
|
||||
let config: ConfigHandler;
|
||||
|
||||
describe("Get mixnode data", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
status = new Status();
|
||||
config = ConfigHandler.getInstance();
|
||||
});
|
||||
|
||||
it("Get a mixnode report", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeStatusReport(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
expect(typeof response.last_day).toBe("number");
|
||||
expect(typeof response.owner).toBe("string");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("mixnode bond not found");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get a mixnode stake saturation", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeStakeSaturation(identity_key);
|
||||
if ("saturation" in response) {
|
||||
expect(typeof response.as_at).toBe("number");
|
||||
expect(typeof response.saturation).toBe("string");
|
||||
expect(typeof response.uncapped_saturation).toBe("string");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("mixnode bond not found");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get a mixnode average uptime", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeAverageUptime(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
expect(identity_key).toStrictEqual(response.mix_id);
|
||||
expect(typeof response.avg_uptime).toBe("number");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("mixnode bond not found");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get a mixnode history", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeHistory(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
response.history.forEach((x) => {
|
||||
expect(typeof x.date).toBe("string");
|
||||
expect(typeof x.uptime).toBe("number");
|
||||
});
|
||||
expect(identity_key).toStrictEqual(response.mix_id);
|
||||
expect(typeof response.owner).toBe("string");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain(
|
||||
"could not find uptime history associated with mixnode"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Get a mixnode core count", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeCoreCount(identity_key);
|
||||
expect(identity_key).toStrictEqual(response.mix_id);
|
||||
expect(typeof response.count).toBe("number");
|
||||
});
|
||||
|
||||
it("Get a mixnode reward estimation", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeRewardComputation(identity_key);
|
||||
if ("estimation" in response) {
|
||||
expect(response.reward_params.interval.sybil_resistance).toStrictEqual(
|
||||
"0.3"
|
||||
);
|
||||
expect(response.reward_params.active_set_size).toStrictEqual(240);
|
||||
expect(typeof response.reward_params.interval.reward_pool).toBe("string");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("mixnode bond not found");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get a mixnode inclusion probability", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeInclusionProbability(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
expect(typeof response.in_active).toBe("string");
|
||||
} else if ("message" in response) {
|
||||
expect(response.message).toContain("mixnode bond not found");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get all mixnodes inclusion probabilities", async (): Promise<void> => {
|
||||
const response = await status.getAllMixnodeInclusionProbability();
|
||||
response.inclusion_probabilities.forEach((x) => {
|
||||
expect(typeof x.mix_id).toBe("number");
|
||||
expect(typeof x.in_active).toBe("number");
|
||||
});
|
||||
expect(typeof response.delta_max).toBe("number");
|
||||
});
|
||||
|
||||
it("Get all mixnodes", async (): Promise<void> => {
|
||||
const response = await status.getDetailedMixnodes();
|
||||
response.forEach((x) => {
|
||||
expect(typeof x.stake_saturation).toBe("string");
|
||||
});
|
||||
});
|
||||
|
||||
it("Get all mixnodes unfiltered", async (): Promise<void> => {
|
||||
const response = await status.getUnfilteredMixnodes();
|
||||
response.forEach((x) => {
|
||||
expect(typeof x.stake_saturation).toBe("string");
|
||||
expect(
|
||||
typeof x.mixnode_details.rewarding_details.last_rewarded_epoch
|
||||
).toBe("number");
|
||||
});
|
||||
});
|
||||
|
||||
it("Get a mixnode status", async (): Promise<void> => {
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeStatus(identity_key);
|
||||
const unfiltered_mixnodes_response = await status.getUnfilteredMixnodes();
|
||||
const mixnode = unfiltered_mixnodes_response.find(
|
||||
(x) => x.mixnode_details.bond_information.mix_id === identity_key
|
||||
);
|
||||
if (mixnode) {
|
||||
expect(response.status).toStrictEqual("active");
|
||||
} else {
|
||||
expect(response.status).toStrictEqual("not_found");
|
||||
}
|
||||
}, 7000);
|
||||
|
||||
it("Get all rewarded mixnodes", async (): Promise<void> => {
|
||||
const response = await status.getDetailedRewardedMixnodes();
|
||||
response.forEach((x) => {
|
||||
expect(
|
||||
typeof x.mixnode_details.rewarding_details.last_rewarded_epoch
|
||||
).toBe("number");
|
||||
});
|
||||
});
|
||||
|
||||
it("Get all active mixnodes", async (): Promise<void> => {
|
||||
const response = await status.getDetailedActiveMixnodes();
|
||||
response.forEach((x) => {
|
||||
expect(typeof x.mixnode_details.bond_information.layer).toBe("number");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Compute mixnode reward estimation", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
status = new Status();
|
||||
config = ConfigHandler.getInstance();
|
||||
});
|
||||
// TODO - this test needs fixing
|
||||
it.skip("with correct data", async (): Promise<void> => {
|
||||
const mix_id = config.environmentConfig.mix_id;
|
||||
const response = await status.sendMixnodeRewardEstimatedComputation(
|
||||
mix_id
|
||||
);
|
||||
expect(typeof response.estimation.delegates).toBe("string");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
reporters: ["default", "jest-junit"],
|
||||
collectCoverageFrom: ["src/**/*.ts"]
|
||||
};
|
||||
Generated
-8546
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"name": "validator-api-test-suite",
|
||||
"version": "1.0.0",
|
||||
"description": "a basic validator-api suite to test the validator-api",
|
||||
"main": "dist/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test:sandbox": "TEST_ENV=sandbox jest --forceExit --detectOpenHandles --passWithNoTests",
|
||||
"test:prod": "TEST_ENV=prod jest --forceExit --detectOpenHandles --passWithNoTests",
|
||||
"build": "tsc",
|
||||
"lint": "eslint --ext .js,.ts,.tsx .",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"cleanup": "rm -rf node_modules; rm -rf dist; yarn install"
|
||||
},
|
||||
"author": "Nymtech",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"engines": {
|
||||
"node": "18.1.0",
|
||||
"npm": "8.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.5",
|
||||
"eslint": "^8.21.0",
|
||||
"form-data": "4.0.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"tslog": "3.3.3",
|
||||
"uuid": "8.3.2",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "28.1.6",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
"axios-mock-adapter": "^1.20.0",
|
||||
"eslint-config-prettier": "^8.4.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^28.1.3",
|
||||
"jest-junit": "^14.0.0",
|
||||
"prettier": "^2.8.7",
|
||||
"process": "0.11.10",
|
||||
"ts-jest": "28.0.7",
|
||||
"typescript": "^4.7.4",
|
||||
"uuidv4": "^6.2.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#[path = "public-api/utils.rs"]
|
||||
mod utils;
|
||||
|
||||
#[path = "public-api/api_status.rs"]
|
||||
mod api_status;
|
||||
|
||||
#[path = "public-api/circulating_supply.rs"]
|
||||
mod circulating_supply;
|
||||
|
||||
#[path = "public-api/contract_cache.rs"]
|
||||
mod contract_cache;
|
||||
|
||||
#[path = "public-api/network.rs"]
|
||||
mod network;
|
||||
|
||||
#[path = "public-api/nym_nodes.rs"]
|
||||
mod nym_nodes;
|
||||
|
||||
#[path = "public-api/status.rs"]
|
||||
mod status;
|
||||
|
||||
#[path = "public-api/unstable_nym_nodes.rs"]
|
||||
mod unstable_nym_nodes;
|
||||
|
||||
#[path = "public-api/unstable_status.rs"]
|
||||
mod unstable_status;
|
||||
@@ -0,0 +1,40 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_health() -> Result<(), String> {
|
||||
let url = format!("{}/v1/api-status/health", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert_eq!(json["status"], "up", "Expected status is 'up'");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_build_information() -> Result<(), String> {
|
||||
let url = format!("{}/v1/api-status/build-information", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("build_version").is_some(),
|
||||
"Expected a value for 'build_version'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ECASH API Test
|
||||
/*
|
||||
#[tokio::test]
|
||||
async fn test_signer_information() -> Result<(), String> {
|
||||
let url = format!("{}/v1/api-status/signer-information", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("signer_address").is_some(),
|
||||
"Expected a value for 'signer_address'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,44 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_circulating_supply() -> Result<(), String> {
|
||||
let url = format!("{}/v1/circulating-supply", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("circulating_supply").is_some(),
|
||||
"Expected a value for 'circulating_supply'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_circulating_supply_value() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/circulating-supply/circulating-supply-value",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.is_number(),
|
||||
"Expected a number for the circulating supply value"
|
||||
);
|
||||
let number = json.as_f64().unwrap_or(-1.0);
|
||||
assert!(number >= 0.0, "Circulating supply should not be negative");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_total_supply_value() -> Result<(), String> {
|
||||
let url = format!("{}/v1/circulating-supply/total-supply-value", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(json.is_number(), "Expected a number for total supply value");
|
||||
let number = json.as_f64().unwrap_or(-1.0);
|
||||
assert!(number >= 0.0, "Total supply shouldn't be negative");
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_current_epoch() -> Result<(), String> {
|
||||
let url = format!("{}/v1/epoch/current", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(json.get("id").is_some(), "Expected a value for 'id'");
|
||||
assert!(
|
||||
json.get("current_epoch_start").is_some(),
|
||||
"Expected a value for `current_epoch_start`"
|
||||
);
|
||||
assert!(
|
||||
json.get("total_elapsed_epochs").is_some(),
|
||||
"Expected a value for `total_elapsed_epochs`"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_reward_params() -> Result<(), String> {
|
||||
let url = format!("{}/v1/epoch/reward_params", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let interval = json
|
||||
.get("interval")
|
||||
.ok_or("Expected a value for 'interval'")?;
|
||||
assert!(
|
||||
interval.get("reward_pool").is_some(),
|
||||
"Expected a value for 'interval.reward_pool'"
|
||||
);
|
||||
|
||||
let rewarded_set = json
|
||||
.get("rewarded_set")
|
||||
.ok_or("Expected a value for 'rewarded_set'")?;
|
||||
assert!(
|
||||
rewarded_set.get("exit_gateways").is_some(),
|
||||
"Expected a value for 'rewarded_set.exit_gateways'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
use crate::utils::{base_url, test_client, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_chain_status() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/chain-status", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
let block_header = json
|
||||
.get("status")
|
||||
.and_then(|s| s.get("latest_block"))
|
||||
.and_then(|b| b.get("block"))
|
||||
.and_then(|b| b.get("header"))
|
||||
.ok_or("Expected a value for 'status.block.header'")?;
|
||||
|
||||
assert!(
|
||||
block_header.get("chain_id").is_some(),
|
||||
"Expected a value for 'chain_id'"
|
||||
);
|
||||
assert!(
|
||||
block_header.get("height").is_some(),
|
||||
"Expected a value for 'height'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_network_details() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/details", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("connected_nyxd").is_some(),
|
||||
"Expected a value for 'connected_nyxd'"
|
||||
);
|
||||
let contracts = json
|
||||
.get("network")
|
||||
.and_then(|s| s.get("contracts"))
|
||||
.ok_or("Expected a value for 'contracts'")?;
|
||||
assert!(
|
||||
contracts.get("mixnet_contract_address").is_some(),
|
||||
"Expected a value for 'mixnet_contract_address'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_nym_contracts() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/nym-contracts", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("nym-mixnet-contract").is_some(),
|
||||
"Expected a value for 'nym-mixnet-contract'"
|
||||
);
|
||||
assert!(
|
||||
json.get("nym-ecash-contract").is_some(),
|
||||
"Expected a value for 'nym-ecash-contract'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_nym_contracts_detailed() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/nym-contracts-detailed", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
let mixnet_contract = json
|
||||
.get("nym-mixnet-contract")
|
||||
.and_then(|s| s.get("details"))
|
||||
.ok_or("Expected details for the mixnet contract")?;
|
||||
assert!(
|
||||
mixnet_contract.get("commit_branch").is_some(),
|
||||
"Expected a value for 'commit_branch'"
|
||||
);
|
||||
|
||||
let ecash_contract = json
|
||||
.get("nym-ecash-contract")
|
||||
.and_then(|s| s.get("details"))
|
||||
.ok_or("Expected details for the ecash contract")?;
|
||||
assert!(
|
||||
ecash_contract.get("commit_branch").is_some(),
|
||||
"Expected a value for 'commit_branch'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
use crate::utils::{base_url, get_any_node_id, make_request, test_client, validate_json_response};
|
||||
use chrono::Utc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_bonded_nodes() -> Result<(), String> {
|
||||
let url = format!("{}/v1/nym-nodes/bonded", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data = json
|
||||
.get("data")
|
||||
.ok_or("Expected a value for 'data' field")?;
|
||||
|
||||
assert!(data.is_array(), "Expected 'data' to be an array");
|
||||
assert!(
|
||||
!data.as_array().unwrap().is_empty(),
|
||||
"Expected at least one bonded node"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_described_nodes() -> Result<(), String> {
|
||||
let url = format!("{}/v1/nym-nodes/described", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data = json
|
||||
.get("data")
|
||||
.ok_or("Expected a value for 'data' field")?;
|
||||
|
||||
assert!(data.is_array(), "Expected 'data' to be an array");
|
||||
assert!(
|
||||
!data.as_array().unwrap().is_empty(),
|
||||
"Expected at least one node to appear"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO enable this once noise is properly integrated
|
||||
// #[tokio::test]
|
||||
// async fn test_get_noise() -> Result<(), String> {
|
||||
// let url = format!("{}/v1/nym-nodes/noise", base_url()?);
|
||||
// let res = test_client().get(&url).send().await.map_err(|err| panic!("Failed to send request to {}: {}", url, err))?;
|
||||
// let json = validate_json_response(res).await;
|
||||
// }
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_rewarded_set() -> Result<(), String> {
|
||||
let url = format!("{}/v1/nym-nodes/rewarded-set", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let exit_gateways = json
|
||||
.get("exit_gateways")
|
||||
.ok_or("Expected a value for 'exit_gateways' field")?;
|
||||
|
||||
assert!(
|
||||
exit_gateways.is_array(),
|
||||
"Expected 'exit_gateways' to be an array"
|
||||
);
|
||||
assert!(
|
||||
!exit_gateways.as_array().unwrap().is_empty(),
|
||||
"We have no exit gateways!!"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_annotation_for_node() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/annotation/{}", base_url()?, id);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let annotation = json
|
||||
.get("annotation")
|
||||
.ok_or("Expected a value for 'annotation' field")?;
|
||||
|
||||
assert!(
|
||||
annotation.get("last_24h_performance").is_some(),
|
||||
"Expected a value for 'last_24h_performance'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_historical_performance() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let date = Utc::now().date_naive().to_string();
|
||||
let url = format!("{}/v1/nym-nodes/historical-performance/{}", base_url()?, id);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.query(&[("date", date)])
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("performance").is_some(),
|
||||
"Expected a value for 'performance' field"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_performance_history() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/performance-history/{}", base_url()?, id);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data = json
|
||||
.get("history")
|
||||
.and_then(|h| h.get("data"))
|
||||
.ok_or("Expected a value for 'history.data'")?;
|
||||
|
||||
assert!(data.is_array(), "Expected 'history.data' to be an array");
|
||||
assert!(
|
||||
!data.as_array().unwrap().is_empty(),
|
||||
"Expected at least one performance history entry"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_performance() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/performance/{}", base_url()?, id);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
assert!(
|
||||
json.get("node_id").is_some(),
|
||||
"Expected a value for 'node_id'"
|
||||
);
|
||||
assert!(
|
||||
json.get("performance").is_some(),
|
||||
"Expected a value for 'performance'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_uptime_history() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/uptime-history/{}", base_url()?, id);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data = json
|
||||
.get("history")
|
||||
.and_then(|h| h.get("data"))
|
||||
.ok_or("Expected a value for 'history.data'")?;
|
||||
|
||||
assert!(data.is_array(), "Expected 'history.data' to be an array");
|
||||
assert!(
|
||||
!data.as_array().unwrap().is_empty(),
|
||||
"Expected at least one performance history entry"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO add the POST request test for `refresh-described`
|
||||
@@ -0,0 +1,38 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_config_score_details() -> Result<(), String> {
|
||||
let url = format!("{}/v1/status/config-score-details", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
|
||||
let version_history = json
|
||||
.get("version_history")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or("Missing or invalid 'version_history' array")?;
|
||||
|
||||
assert!(
|
||||
!version_history.is_empty(),
|
||||
"'version_history' should not be empty"
|
||||
);
|
||||
|
||||
let max_entry = version_history
|
||||
.iter()
|
||||
.max_by_key(|entry| entry.get("id").and_then(|id| id.as_u64()).unwrap_or(0))
|
||||
.ok_or("Unable to find max id entry")?;
|
||||
|
||||
let semver = max_entry
|
||||
.get("version_information")
|
||||
.and_then(|v| v.get("semver"))
|
||||
.and_then(|v| v.as_str());
|
||||
|
||||
assert!(
|
||||
semver.is_some(),
|
||||
"Expected a value for 'semver' in the highest id entry"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO add the POST request tests for:
|
||||
// submit-gateway-monitoring-results
|
||||
// submit-node-monitoring-results
|
||||
@@ -0,0 +1,168 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_nodes_active() -> Result<(), String> {
|
||||
let url = format!("{}/v1/unstable/nym-nodes/skimmed/active", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data = json
|
||||
.get("nodes")
|
||||
.and_then(|r| r.get("data"))
|
||||
.ok_or("Missing 'data' field")?;
|
||||
|
||||
assert!(data.is_array(), "Expected 'data' to be an array");
|
||||
assert!(
|
||||
!data.as_array().unwrap().is_empty(),
|
||||
"Expected at least one node to appear"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_active_mixnodes() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/mixnodes/active",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let current_epoch_id = json
|
||||
.get("status")
|
||||
.and_then(|r| r.get("fresh"))
|
||||
.and_then(|r| r.get("current_epoch_id"))
|
||||
.ok_or("Missing 'current_epoch_id'")?;
|
||||
|
||||
assert!(
|
||||
current_epoch_id.is_number(),
|
||||
"Expected 'current_epoch_id' to be a number"
|
||||
);
|
||||
assert!(
|
||||
json.get("refreshed_at").is_some(),
|
||||
"Expected a value for 'refreshed_at'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_all_mixnodes() -> Result<(), String> {
|
||||
let url = format!("{}/v1/unstable/nym-nodes/skimmed/mixnodes/all", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let current_epoch_id = json
|
||||
.get("status")
|
||||
.and_then(|r| r.get("fresh"))
|
||||
.and_then(|r| r.get("current_epoch_id"))
|
||||
.ok_or("Missing 'current_epoch_id'")?;
|
||||
|
||||
assert!(
|
||||
current_epoch_id.is_number(),
|
||||
"Expected 'current_epoch_id' to be a number"
|
||||
);
|
||||
assert!(
|
||||
json.get("refreshed_at").is_some(),
|
||||
"Expected a value for 'refreshed_at'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_active_exit_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/exit-gateways/active",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let current_epoch_id = json
|
||||
.get("status")
|
||||
.and_then(|r| r.get("fresh"))
|
||||
.and_then(|r| r.get("current_epoch_id"))
|
||||
.ok_or("Missing 'current_epoch_id'")?;
|
||||
|
||||
assert!(
|
||||
current_epoch_id.is_number(),
|
||||
"Expected 'current_epoch_id' to be a number"
|
||||
);
|
||||
assert!(
|
||||
json.get("refreshed_at").is_some(),
|
||||
"Expected a value for 'refreshed_at'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_all_exit_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/exit-gateways/all",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let current_epoch_id = json
|
||||
.get("status")
|
||||
.and_then(|r| r.get("fresh"))
|
||||
.and_then(|r| r.get("current_epoch_id"))
|
||||
.ok_or("Missing 'current_epoch_id'")?;
|
||||
|
||||
assert!(
|
||||
current_epoch_id.is_number(),
|
||||
"Expected 'current_epoch_id' to be a number"
|
||||
);
|
||||
assert!(
|
||||
json.get("refreshed_at").is_some(),
|
||||
"Expected a value for 'refreshed_at'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_active_entry_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/entry-gateways/active",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let current_epoch_id = json
|
||||
.get("status")
|
||||
.and_then(|r| r.get("fresh"))
|
||||
.and_then(|r| r.get("current_epoch_id"))
|
||||
.ok_or("Missing 'current_epoch_id'")?;
|
||||
|
||||
assert!(
|
||||
current_epoch_id.is_number(),
|
||||
"Expected 'current_epoch_id' to be a number"
|
||||
);
|
||||
assert!(
|
||||
json.get("refreshed_at").is_some(),
|
||||
"Expected a value for 'refreshed_at'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_skimmed_all_entry_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/entry-gateways/all",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let current_epoch_id = json
|
||||
.get("status")
|
||||
.and_then(|r| r.get("fresh"))
|
||||
.and_then(|r| r.get("current_epoch_id"))
|
||||
.ok_or("Missing 'current_epoch_id'")?;
|
||||
|
||||
assert!(
|
||||
current_epoch_id.is_number(),
|
||||
"Expected 'current_epoch_id' to be a number"
|
||||
);
|
||||
assert!(
|
||||
json.get("refreshed_at").is_some(),
|
||||
"Expected a value for 'refreshed_at'"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Add the remining tests as the endpoints become active
|
||||
@@ -0,0 +1,93 @@
|
||||
use crate::utils::{
|
||||
base_url, get_gateway_identity_key, get_mixnode_node_id, make_request, test_client,
|
||||
validate_json_response,
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_gateway_unstable_test_results() -> Result<(), String> {
|
||||
let identity = get_gateway_identity_key().await?;
|
||||
let url = format!(
|
||||
"{}/v1/status/gateways/unstable/{}/test-results",
|
||||
base_url()?,
|
||||
identity
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data_array = json
|
||||
.get("data")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or("Missing or invalid 'data' array")?;
|
||||
assert!(!data_array.is_empty(), "'data' array is empty");
|
||||
|
||||
let gateway = data_array[0]
|
||||
.get("test_routes")
|
||||
.and_then(|r| r.get("gateway"))
|
||||
.ok_or("Expected a value for 'test_routes.gateway'")?;
|
||||
assert!(
|
||||
gateway.get("node_id").is_some(),
|
||||
"Expected a value for 'node_id' in gateway"
|
||||
);
|
||||
assert!(
|
||||
gateway.get("identity_key").is_some(),
|
||||
"Expected a value for 'identity_key' in gateway"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mixnode_unstable_test_results() -> Result<(), String> {
|
||||
let mix_id = get_mixnode_node_id().await?;
|
||||
let url = format!(
|
||||
"{}/v1/status/mixnodes/unstable/{}/test-results",
|
||||
base_url()?,
|
||||
mix_id
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let data_array = json
|
||||
.get("data")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or("Missing or invalid 'data' array")?;
|
||||
assert!(!data_array.is_empty(), "'data' array is empty");
|
||||
|
||||
let layer3 = data_array[0]
|
||||
.get("test_routes")
|
||||
.and_then(|r| r.get("layer3"))
|
||||
.ok_or("Expected a value for 'test_routes.layer3'")?;
|
||||
assert!(
|
||||
layer3.get("node_id").is_some(),
|
||||
"Expected a value for 'node_id' in layer3"
|
||||
);
|
||||
assert!(
|
||||
layer3.get("identity_key").is_some(),
|
||||
"Expected a value for 'identity_key' in layer3"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_latest_network_monitor_run_details() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/status/network-monitor/unstable/run/latest/details",
|
||||
base_url()?
|
||||
);
|
||||
let res = make_request(&url).await?;
|
||||
let json = validate_json_response(res).await?;
|
||||
let monitor_run_id = json
|
||||
.get("monitor_run_id")
|
||||
.and_then(|v| v.as_u64())
|
||||
.ok_or("Missing or invalid 'monitor_run_id'")?;
|
||||
|
||||
let follow_up_url = format!(
|
||||
"{}/v1/status/network-monitor/unstable/run/{}/details",
|
||||
base_url()?,
|
||||
monitor_run_id
|
||||
);
|
||||
let follow_up_res = test_client()
|
||||
.get(&follow_up_url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to follow up with URL {}: {}", follow_up_url, err))?;
|
||||
assert!(follow_up_res.status().is_success());
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
use dotenv::dotenv;
|
||||
use reqwest::{Client, Response};
|
||||
use serde_json::Value;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub fn test_client() -> Client {
|
||||
Client::new()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub fn base_url() -> Result<String, String> {
|
||||
dotenv().ok();
|
||||
|
||||
std::env::var("NYM_API")
|
||||
.map(|url| url.trim_end_matches('/').to_string())
|
||||
.map_err(|_| "Couldn't find NYM_API env var".to_string())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub async fn make_request(url: &str) -> Result<Response, String> {
|
||||
let res = test_client()
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
|
||||
if res.status().is_success() {
|
||||
Ok(res)
|
||||
} else {
|
||||
Err(format!("Expected 2xx but got {}", res.status()))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub async fn validate_json_response(res: Response) -> Result<Value, String> {
|
||||
if !res.status().is_success() {
|
||||
return Err(format!("Expected 2xx but got {}", res.status()));
|
||||
}
|
||||
|
||||
res.json::<Value>()
|
||||
.await
|
||||
.map_err(|err| format!("Invalid JSON response: {}", err))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub async fn get_any_node_id() -> Result<String, String> {
|
||||
let url = format!("{}/v1/nym-nodes/bonded", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json: Value = res
|
||||
.json()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to parse response as JSON: {}", err))?;
|
||||
|
||||
let id = json
|
||||
.get("data")
|
||||
.and_then(|list| list.as_array())
|
||||
.and_then(|arr| arr.first())
|
||||
.and_then(|node| node.get("bond_information"))
|
||||
.and_then(|n| n.get("node_id"))
|
||||
.and_then(|v| v.as_u64())
|
||||
.unwrap_or(0);
|
||||
|
||||
Ok(id.to_string())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub async fn get_mixnode_node_id() -> Result<u64, String> {
|
||||
let url = format!("{}/v1/nym-nodes/described", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json: Value = res
|
||||
.json()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to parse response as JSON: {}", err))?;
|
||||
|
||||
json.get("data")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or("Expected 'data' to be an array".to_string())?
|
||||
.iter()
|
||||
.find(|entry| {
|
||||
entry
|
||||
.get("description")
|
||||
.and_then(|d| d.get("declared_role"))
|
||||
.and_then(|r| r.get("mixnode"))
|
||||
.and_then(|m| m.as_bool())
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.and_then(|node| node.get("node_id").and_then(|v| v.as_u64()))
|
||||
.ok_or("Unable to find mixnode node id".to_string())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(clippy::panic)]
|
||||
pub async fn get_gateway_identity_key() -> Result<String, String> {
|
||||
let url = format!("{}/v1/nym-nodes/described", base_url()?);
|
||||
let res = test_client()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to send request to {}: {}", url, err))?;
|
||||
let json: Value = res
|
||||
.json()
|
||||
.await
|
||||
.map_err(|err| format!("Failed to parse response as JSON: {}", err))?;
|
||||
|
||||
let key = json
|
||||
.get("data")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or("Expected 'data' to be an array".to_string())?
|
||||
.iter()
|
||||
.find(|entry| {
|
||||
entry
|
||||
.get("description")
|
||||
.and_then(|d| d.get("declared_role"))
|
||||
.and_then(|r| r.get("mixnode"))
|
||||
.and_then(|m| m.as_bool())
|
||||
.map(|is_mixnode| !is_mixnode)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.and_then(|node| {
|
||||
node.get("description")
|
||||
.and_then(|d| d.get("host_information"))
|
||||
.and_then(|h| h.get("keys"))
|
||||
.and_then(|k| k.get("ed25519"))
|
||||
.and_then(|v| v.as_str())
|
||||
})
|
||||
.ok_or("Unable to find gateway identity key with mixnode = false".to_string())?;
|
||||
|
||||
Ok(key.to_string())
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Detailed } from "../types/CirculatingSupplyTypes";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class ContractCache extends APIClient {
|
||||
constructor() {
|
||||
super("/");
|
||||
}
|
||||
|
||||
public async getCirculatingSupply(): Promise<Detailed> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `circulating-supply`,
|
||||
});
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
import {
|
||||
MixnodesDetailed,
|
||||
AllGateways,
|
||||
AllMixnodes,
|
||||
EpochRewardParams,
|
||||
CurrentEpoch,
|
||||
ServiceProviders,
|
||||
NymAddressNames,
|
||||
} from "../types/ContractCacheTypes";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class ContractCache extends APIClient {
|
||||
constructor() {
|
||||
super("/");
|
||||
}
|
||||
|
||||
public async getMixnodes(): Promise<AllMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodesDetailed(): Promise<MixnodesDetailed[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getGateways(): Promise<AllGateways[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateways`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getActiveMixnodes(): Promise<AllMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/active`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getActiveMixnodesDetailed(): Promise<MixnodesDetailed[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/active/detailed`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getRewardedMixnodes(): Promise<AllMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/rewarded`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getRewardedMixnodesDetailed(): Promise<MixnodesDetailed[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/rewarded/detailed`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getBlacklistedMixnodes(): Promise<[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/blacklisted`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getBlacklistedGateways(): Promise<[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateways/blacklisted`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getEpochRewardParams(): Promise<EpochRewardParams> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `epoch/reward_params`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getCurrentEpoch(): Promise<CurrentEpoch> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `epoch/current`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getServiceProviders(): Promise<ServiceProviders> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `services`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getNymAddressNames(): Promise<NymAddressNames> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `names`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { NetworkDetails, NymContracts, NymContractsDetailed } from "../types/NetworkTypes";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class NetworkTypes extends APIClient {
|
||||
constructor() {
|
||||
super("/");
|
||||
}
|
||||
|
||||
public async getNetworkDetails(): Promise<NetworkDetails> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `network/details`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getNymContractInfo(): Promise<NymContracts> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `network/nym-contracts`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getNymContractDetailedInfo(): Promise<NymContractsDetailed> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `network/nym-contracts-detailed`,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
import {
|
||||
ActiveStatus,
|
||||
AvgUptime,
|
||||
CoreCount,
|
||||
DetailedGateway,
|
||||
DetailedMixnodes,
|
||||
GatewayUptimeResponse,
|
||||
InclusionProbabilities,
|
||||
InclusionProbability,
|
||||
NodeHistory,
|
||||
ErrorMsg,
|
||||
Report,
|
||||
RewardEstimation,
|
||||
StakeSaturation,
|
||||
} from "../types/StatusInterfaces";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class Status extends APIClient {
|
||||
constructor() {
|
||||
super("/status");
|
||||
}
|
||||
|
||||
// GATEWAYS
|
||||
|
||||
public async getDetailedGateways(): Promise<DetailedGateway[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/gateways/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getUnfilteredGateways(): Promise<DetailedGateway[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/gateways/detailed-unfiltered`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getGatewayStatusReport(
|
||||
identity_key: string
|
||||
): Promise<Report | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/gateway/${identity_key}/report`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getGatewayHistory(
|
||||
identity_key: string
|
||||
): Promise<NodeHistory | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/gateway/${identity_key}/history`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getGatewayCoreCount(identity_key: string): Promise<CoreCount> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/gateway/${identity_key}/core-status-count`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getGatewayAverageUptime(
|
||||
identity_key: string
|
||||
): Promise<GatewayUptimeResponse | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/gateway/${identity_key}/avg_uptime`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
// MIXNODES
|
||||
|
||||
public async getMixnodeStatusReport(
|
||||
mix_id: number
|
||||
): Promise<Report | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/report`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeStakeSaturation(
|
||||
mix_id: number
|
||||
): Promise<StakeSaturation | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/stake-saturation`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeCoreCount(mix_id: number): Promise<CoreCount> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/core-status-count`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeRewardComputation(
|
||||
mix_id: number
|
||||
): Promise<RewardEstimation | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/reward-estimation`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async sendMixnodeRewardEstimatedComputation(
|
||||
mix_id: number
|
||||
): Promise<RewardEstimation> {
|
||||
const response = await this.restClient.sendPost({
|
||||
route: `/mixnode/${mix_id}/compute-reward-estimation`,
|
||||
data: {
|
||||
// performance: "10",
|
||||
active_in_rewarded_set: true,
|
||||
// pledge_amount: 10,
|
||||
// total_delegation: 2000,
|
||||
// interval_operating_cost: {
|
||||
// denom: "unym",
|
||||
// amount: "250000000"
|
||||
// },
|
||||
// profit_margin_percent: 10
|
||||
},
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeHistory(
|
||||
mix_id: number
|
||||
): Promise<NodeHistory | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/history`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeAverageUptime(
|
||||
mix_id: number
|
||||
): Promise<AvgUptime | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/avg_uptime`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeInclusionProbability(
|
||||
mix_id: number
|
||||
): Promise<InclusionProbability | ErrorMsg> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/inclusion-probability`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMixnodeStatus(mix_id: number): Promise<ActiveStatus> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnode/${mix_id}/status`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getAllMixnodeInclusionProbability(): Promise<InclusionProbabilities> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnodes/inclusion_probability`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getDetailedMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnodes/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getDetailedRewardedMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnodes/rewarded/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getUnfilteredMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnodes/detailed-unfiltered`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getDetailedActiveMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `/mixnodes/active/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Logger } from "tslog";
|
||||
import ConfigHandler from "../../../../../common/api-test-utils/config/configHandler";
|
||||
import { RestClient } from "../../../../../common/api-test-utils/restClient/RestClient";
|
||||
|
||||
export abstract class APIClient {
|
||||
protected constructor(serviceUrl: string) {
|
||||
const baseUrl: string = this.config.environmentConfig.api_base_url;
|
||||
this.url = baseUrl + serviceUrl;
|
||||
this.restClient = new RestClient(this.url);
|
||||
this.serviceName = this.constructor.toString().match(/\w+/g)[1];
|
||||
this.log.info(`The Service URL for ${this.serviceName} is ${this.url}`);
|
||||
}
|
||||
|
||||
public createdItemIds: Set<string> = new Set();
|
||||
|
||||
protected config = ConfigHandler.getInstance();
|
||||
|
||||
protected log: Logger = new Logger({
|
||||
minLevel: this.config.environmentConfig.log_level,
|
||||
dateTimeTimezone:
|
||||
this.config.environmentConfig.time_zone ||
|
||||
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
});
|
||||
|
||||
protected url: string;
|
||||
|
||||
public restClient: RestClient;
|
||||
|
||||
protected serviceName: string;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
export type Detailed = {
|
||||
total_supply: InitialSupply;
|
||||
mixmining_reserve: MixminingReserve;
|
||||
vesting_tokens: VestingTokens;
|
||||
circulating_supply: CirculatingSupply;
|
||||
};
|
||||
|
||||
export type InitialSupply = {
|
||||
demon: "unym";
|
||||
amount: string;
|
||||
};
|
||||
|
||||
export type MixminingReserve = {
|
||||
demon: "unym";
|
||||
amount: string;
|
||||
};
|
||||
|
||||
export type VestingTokens = {
|
||||
demon: "unym";
|
||||
amount: string;
|
||||
};
|
||||
|
||||
export type CirculatingSupply = {
|
||||
demon: "unym";
|
||||
amount: string;
|
||||
};
|
||||
@@ -1,154 +0,0 @@
|
||||
export interface AllMixnodes {
|
||||
bond_information: BondInformation;
|
||||
rewarding_details: RewardingDetails;
|
||||
}
|
||||
|
||||
export interface BondInformation {
|
||||
mix_id: number;
|
||||
owner: string;
|
||||
original_pledge: DenominationAndAmount;
|
||||
layer: number;
|
||||
mix_node: Mixnode;
|
||||
proxy: string;
|
||||
bonding_height: number;
|
||||
is_unbonding: boolean;
|
||||
}
|
||||
|
||||
export interface RewardingDetails {
|
||||
cost_params: CostParams;
|
||||
operator: string;
|
||||
delegates: string;
|
||||
total_unit_reward: string;
|
||||
unit_delegation: string;
|
||||
last_rewarded_epoch: number;
|
||||
unique_delegations: number;
|
||||
}
|
||||
|
||||
export interface CostParams {
|
||||
profit_margin_percent: string;
|
||||
interval_operating_cost: DenominationAndAmount;
|
||||
}
|
||||
|
||||
export interface DenominationAndAmount {
|
||||
denom: string;
|
||||
amount: string;
|
||||
}
|
||||
export interface Mixnode {
|
||||
host: string;
|
||||
mix_port: number;
|
||||
verloc_port: number;
|
||||
http_api_port: number;
|
||||
sphinx_key: string;
|
||||
identity_key: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface MixnodeBond {
|
||||
pledge_amount: DenominationAndAmount;
|
||||
total_delegation: DenominationAndAmount;
|
||||
owner: string;
|
||||
layer: string;
|
||||
block_height: string;
|
||||
mix_node: Mixnode;
|
||||
proxy: string;
|
||||
accumulated_rewards: string;
|
||||
}
|
||||
|
||||
export interface MixnodesDetailed {
|
||||
mixnode_details: AllMixnodes;
|
||||
stake_saturation: string;
|
||||
uncapped_stake_saturation: string;
|
||||
performance: string;
|
||||
estimated_operator_apy: string;
|
||||
estimated_delegators_apy: string;
|
||||
family: string;
|
||||
}
|
||||
|
||||
export interface Gateway {
|
||||
host: string;
|
||||
mix_port: number;
|
||||
clients_port: number;
|
||||
location: string;
|
||||
sphinx_key: string;
|
||||
identity_key: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface AllGateways {
|
||||
pledge_amount: DenominationAndAmount;
|
||||
owner: string;
|
||||
block_height: number;
|
||||
gateway: Gateway;
|
||||
proxy: string;
|
||||
}
|
||||
|
||||
export interface EpochRewardParams {
|
||||
interval: Interval;
|
||||
rewarded_set_size: number;
|
||||
active_set_size: number;
|
||||
}
|
||||
|
||||
export interface Interval {
|
||||
reward_pool: string;
|
||||
staking_supply: string;
|
||||
staking_supply_scale_factor: string;
|
||||
epoch_reward_budget: string;
|
||||
stake_saturation_point: string;
|
||||
sybil_resistance: string;
|
||||
active_set_work_factor: string;
|
||||
interval_pool_emission: string;
|
||||
}
|
||||
|
||||
export interface CurrentEpoch {
|
||||
id: number;
|
||||
epochs_in_interval: number;
|
||||
current_epoch_start: string;
|
||||
current_epoch_id: number;
|
||||
epoch_length: EpochLength;
|
||||
total_elapsed_epochs: number;
|
||||
}
|
||||
|
||||
export interface EpochLength {
|
||||
secs: number;
|
||||
nanos: number;
|
||||
}
|
||||
|
||||
export interface ServiceProviders {
|
||||
services: Services[];
|
||||
}
|
||||
export interface Services {
|
||||
service_id: number;
|
||||
service: Service;
|
||||
}
|
||||
export interface Service {
|
||||
nym_address: NymAddress;
|
||||
service_type: string;
|
||||
announcer: string;
|
||||
block_height: number;
|
||||
deposit: DenominationAndAmount;
|
||||
}
|
||||
export interface NymAddress {
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface NymAddressNames {
|
||||
names: Names[];
|
||||
}
|
||||
export interface Names {
|
||||
id: number;
|
||||
name: Name;
|
||||
owner: string;
|
||||
block_height: number;
|
||||
deposit: DenominationAndAmount;
|
||||
}
|
||||
export interface Name {
|
||||
name: string;
|
||||
address: NameAddress;
|
||||
identity_key: string;
|
||||
}
|
||||
|
||||
export interface NameAddress {
|
||||
client_id: string;
|
||||
client_enc: string;
|
||||
gateway_id: string;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
export interface NetworkDetails {
|
||||
connected_nyxd: string;
|
||||
network: Network;
|
||||
}
|
||||
|
||||
export interface Network {
|
||||
network_name: string;
|
||||
chain_details: ChainDetails;
|
||||
endpoints: Endpoint[];
|
||||
contracts: Contracts;
|
||||
explorer_api: string;
|
||||
}
|
||||
|
||||
export interface ChainDetails {
|
||||
bech32_account_prefix: string;
|
||||
mix_denom: Denom;
|
||||
stake_denom: Denom;
|
||||
}
|
||||
|
||||
export interface Denom {
|
||||
base: string;
|
||||
display: string;
|
||||
display_exponent: number;
|
||||
}
|
||||
|
||||
export interface Contracts {
|
||||
mixnet_contract_address: string;
|
||||
vesting_contract_address: string;
|
||||
coconut_bandwidth_contract_address: string;
|
||||
group_contract_address: string;
|
||||
multisig_contract_address: string;
|
||||
coconut_dkg_contract_address: string;
|
||||
}
|
||||
|
||||
export interface Endpoint {
|
||||
nyxd_url: string;
|
||||
api_url: string;
|
||||
}
|
||||
|
||||
|
||||
export interface NymContracts {
|
||||
[additionalProp: string]: AdditionalProp;
|
||||
}
|
||||
|
||||
export interface AdditionalProp {
|
||||
address: string;
|
||||
details: Info;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
contract: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
|
||||
export interface NymContractsDetailed {
|
||||
[additionalProp: string]: AdditionalPropDetailed;
|
||||
}
|
||||
|
||||
export interface AdditionalPropDetailed {
|
||||
address: string;
|
||||
details: InfoDetailed;
|
||||
}
|
||||
|
||||
export interface InfoDetailed {
|
||||
build_timestamp: string;
|
||||
build_version: string;
|
||||
commit_sha: string;
|
||||
commit_timestamp: string;
|
||||
commit_branch: string;
|
||||
rustc_version: string;
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
export interface CurrentEpoch {
|
||||
epoch_reward_pool: string;
|
||||
rewarded_set_size: string;
|
||||
active_set_size: string;
|
||||
staking_supply: string;
|
||||
sybil_resistance_percent: number;
|
||||
active_set_work_factor: number;
|
||||
}
|
||||
|
||||
export interface Epoch {
|
||||
id: number;
|
||||
epochs_in_interval: number;
|
||||
current_epoch_start: string;
|
||||
current_epoch_id: number;
|
||||
epoch_length: EpochLength;
|
||||
total_elapsed_epochs: number;
|
||||
}
|
||||
|
||||
export interface EpochLength {
|
||||
secs: number;
|
||||
nanos: number;
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
reward_blockstamp: number;
|
||||
uptime: string;
|
||||
in_active_set: boolean;
|
||||
}
|
||||
|
||||
export interface Estimation {
|
||||
total_node_reward: string;
|
||||
operator: string;
|
||||
delegates: string;
|
||||
operating_cost: string;
|
||||
}
|
||||
|
||||
export interface RewardEstimation {
|
||||
estimation: Estimation;
|
||||
reward_params: RewardParams;
|
||||
epoch: Epoch;
|
||||
as_at: number;
|
||||
}
|
||||
|
||||
export interface RewardParams {
|
||||
interval: Interval;
|
||||
rewarded_set_size: number;
|
||||
active_set_size: number;
|
||||
}
|
||||
|
||||
export interface ComputeRewardEstimation {
|
||||
performance: string;
|
||||
active_in_rewarded_set: boolean;
|
||||
pledge_amount: number;
|
||||
total_delegation: number;
|
||||
interval_operating_cost: DenominationAndAmount;
|
||||
profit_margin_percent: string;
|
||||
}
|
||||
|
||||
export interface DenominationAndAmount {
|
||||
denom: string;
|
||||
amount: string;
|
||||
}
|
||||
|
||||
export interface Interval {
|
||||
reward_pool: string;
|
||||
staking_supply: string;
|
||||
staking_supply_scale_factor: string;
|
||||
epoch_reward_budget: string;
|
||||
stake_saturation_point: string;
|
||||
sybil_resistance: string;
|
||||
active_set_work_factor: string;
|
||||
interval_pool_emission: string;
|
||||
}
|
||||
|
||||
export interface StakeSaturation {
|
||||
saturation: string;
|
||||
uncapped_saturation: string;
|
||||
as_at: number;
|
||||
}
|
||||
|
||||
export interface SingleInclusionProbability {
|
||||
in_active: number;
|
||||
in_reserve: number;
|
||||
}
|
||||
|
||||
export interface InclusionProbability {
|
||||
mix_id: number;
|
||||
in_active: string;
|
||||
in_reserve: string;
|
||||
}
|
||||
|
||||
export interface InclusionProbabilities {
|
||||
inclusion_probabilities: InclusionProbability[];
|
||||
samples: number;
|
||||
elapsed: Elapsed;
|
||||
delta_max: number;
|
||||
delta_l2: number;
|
||||
as_at: number;
|
||||
}
|
||||
|
||||
export interface Elapsed {
|
||||
secs: number;
|
||||
nanos: number;
|
||||
}
|
||||
|
||||
export interface Report {
|
||||
mix_id: number;
|
||||
identity: string;
|
||||
owner: string;
|
||||
most_recent: number;
|
||||
last_hour: number;
|
||||
last_day: number;
|
||||
}
|
||||
|
||||
export interface History {
|
||||
date: string;
|
||||
uptime: number;
|
||||
}
|
||||
|
||||
export interface NodeHistory {
|
||||
mix_id: number;
|
||||
identity: string;
|
||||
owner: string;
|
||||
history: History[];
|
||||
}
|
||||
|
||||
export interface ErrorMsg {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface CoreCount {
|
||||
mix_id: number;
|
||||
identity: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface ActiveStatus {
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface Gateway {
|
||||
host: string;
|
||||
mix_port: number;
|
||||
clients_port: number;
|
||||
location: string;
|
||||
sphinx_key: string;
|
||||
identity_key: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface GatewayBond {
|
||||
pledge_amount: DenominationAndAmount;
|
||||
owner: string;
|
||||
block_height: number;
|
||||
gateway: Gateway;
|
||||
proxy?: any;
|
||||
}
|
||||
|
||||
export interface nodePerformance {
|
||||
most_recent: string;
|
||||
last_hour: string;
|
||||
last_24h: string;
|
||||
}
|
||||
|
||||
export interface AvgUptime {
|
||||
mix_id: number;
|
||||
avg_uptime: number;
|
||||
node_performance: nodePerformance;
|
||||
}
|
||||
|
||||
export interface GatewayUptimeResponse {
|
||||
identity: string;
|
||||
avg_uptime: number;
|
||||
node_performance: nodePerformance;
|
||||
}
|
||||
|
||||
export interface DetailedGateway {
|
||||
gateway_bond: GatewayBond;
|
||||
performance: string;
|
||||
node_performance: nodePerformance;
|
||||
}
|
||||
|
||||
export interface MixNode {
|
||||
host: string;
|
||||
mix_port: number;
|
||||
verloc_port: number;
|
||||
http_api_port: number;
|
||||
sphinx_key: string;
|
||||
identity_key: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface BondInformation {
|
||||
mix_id: number;
|
||||
owner: string;
|
||||
original_pledge: DenominationAndAmount;
|
||||
layer: string;
|
||||
mix_node: MixNode;
|
||||
proxy: string;
|
||||
bonding_height: number;
|
||||
is_unbonding: boolean;
|
||||
}
|
||||
|
||||
export interface CostParams {
|
||||
profit_margin_percent: string;
|
||||
interval_operating_cost: DenominationAndAmount;
|
||||
}
|
||||
|
||||
export interface RewardingDetails {
|
||||
cost_params: CostParams;
|
||||
operator: string;
|
||||
delegates: string;
|
||||
total_unit_reward: string;
|
||||
unit_delegation: string;
|
||||
last_rewarded_epoch: number;
|
||||
unique_delegations: number;
|
||||
}
|
||||
|
||||
export interface MixnodeDetails {
|
||||
bond_information: BondInformation;
|
||||
rewarding_details: RewardingDetails;
|
||||
}
|
||||
|
||||
export interface DetailedMixnodes {
|
||||
mixnode_details: MixnodeDetails;
|
||||
stake_saturation: string;
|
||||
uncapped_stake_saturation: string;
|
||||
performance: string;
|
||||
estimated_operator_apy: string;
|
||||
estimated_delegators_apy: string;
|
||||
family: string;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["src/**/*", "functional_test/**/*", "unit_test/**/*", "*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"removeComments": true,
|
||||
"allowJs": true,
|
||||
"preserveConstEnums": true,
|
||||
"module": "commonjs",
|
||||
"target": "ES2019",
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"lib": ["esnext"],
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true,
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"paths": {
|
||||
"*": ["types/*"]
|
||||
},
|
||||
"baseUrl": "./",
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"alwaysStrict": true
|
||||
},
|
||||
"include": ["src/**/*", "tests/functional_test/*/*"],
|
||||
"exclude": ["unit_test/**/*"]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-network-requester"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.53"
|
||||
version = "1.1.54"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version = "1.70"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-cli"
|
||||
version = "1.1.52"
|
||||
version = "1.1.53"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nymvisor"
|
||||
version = "0.1.17"
|
||||
version = "0.1.18"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user