Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c5457468b | |||
| b615f5e75e | |||
| 4366aca21c | |||
| f9b8272691 | |||
| ece15f7c7d | |||
| 3762b4264c | |||
| 1ba04a7eb1 | |||
| b14efb211c | |||
| aabc4e41ba | |||
| 8d9387d3ac | |||
| e8bc2c7a01 | |||
| 0486cd2e63 | |||
| 604098844a | |||
| 65e35bd2b0 |
@@ -24,6 +24,9 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.1.0
|
||||
|
||||
- name: Yarn install in root
|
||||
run: cd ../../ && yarn install
|
||||
|
||||
- name: Install yarn
|
||||
run: yarn install
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
name: ci-nym-node-api-tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- "nym-node/**"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-node/tests
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: nym-node tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install npm
|
||||
run: npm install
|
||||
|
||||
- name: Node v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.1.0
|
||||
|
||||
- name: Yarn install in root
|
||||
run: cd ../../ && yarn install
|
||||
|
||||
- name: Install yarn
|
||||
run: yarn install
|
||||
|
||||
- name: Run yarn
|
||||
run: yarn
|
||||
|
||||
- name: Run tests
|
||||
run: yarn test:sandbox
|
||||
working-directory: nym-node/tests
|
||||
@@ -166,5 +166,11 @@ generate-typescript:
|
||||
yarn types:lint:fix
|
||||
|
||||
run-api-tests:
|
||||
cd nym-api/tests/functional_test && yarn test:qa
|
||||
cd nym-api/tests && yarn test:sandbox
|
||||
|
||||
run-nym-node-tests:
|
||||
cd nym-node/tests && yarn test:sandbox
|
||||
|
||||
run-all-api-tests:
|
||||
cd nym-api/tests && yarn test:sandbox
|
||||
cd nym-node/tests && yarn test:sandbox
|
||||
@@ -15,4 +15,4 @@ prod:
|
||||
mixnode_identity: 3pMCJswCyA19MGYWGDWT5fBk2M8ybSZGXttyAoNY5gBB
|
||||
gateway_identity: 2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh
|
||||
log_level: error
|
||||
time_zone: utc
|
||||
time_zone: utc
|
||||
+27
-12
@@ -1,18 +1,18 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { TLogLevelName } from "tslog";
|
||||
|
||||
import YAML from "yaml";
|
||||
import * as dotenv from 'dotenv';
|
||||
import path from "path";
|
||||
|
||||
class ConfigHandler {
|
||||
private static instance: ConfigHandler;
|
||||
|
||||
private validEnvironments = ["sandbox", "prod"];
|
||||
private baseWorkingDirectory: string;
|
||||
|
||||
public commonConfig: { request_headers: object };
|
||||
|
||||
public environment: string;
|
||||
|
||||
public environmnetConfig: {
|
||||
public environmentConfig: {
|
||||
log_level: TLogLevelName;
|
||||
time_zone: string;
|
||||
api_base_url: string;
|
||||
@@ -22,8 +22,21 @@ class ConfigHandler {
|
||||
};
|
||||
|
||||
private constructor() {
|
||||
this.baseWorkingDirectory = __dirname;
|
||||
const environment = process.env.TEST_ENV || "sandbox" || "prod";
|
||||
this.loadEnvironment(environment);
|
||||
}
|
||||
|
||||
private loadEnvironment(environment: string): void {
|
||||
this.loadEnvironmentVariables(environment);
|
||||
this.setCommonConfig();
|
||||
this.setEnvironmentConfig(process.env.TEST_ENV || "sandbox" || "prod");
|
||||
this.setEnvironmentConfig(environment);
|
||||
}
|
||||
|
||||
private loadEnvironmentVariables(environment: string): void {
|
||||
const envFileName = `${environment}.env`;
|
||||
const envFilePath = path.resolve(this.baseWorkingDirectory, `../${envFileName}`);
|
||||
dotenv.config({ path: envFilePath });
|
||||
}
|
||||
|
||||
public static getInstance(): ConfigHandler {
|
||||
@@ -35,25 +48,27 @@ class ConfigHandler {
|
||||
|
||||
private setCommonConfig(): void {
|
||||
try {
|
||||
this.commonConfig = YAML.parse(
|
||||
readFileSync("src/config/config.yaml", "utf8")
|
||||
).common;
|
||||
this.commonConfig = this.readConfigFile().common;
|
||||
} catch (error) {
|
||||
throw Error(`Error reading common config: (${error})`);
|
||||
}
|
||||
}
|
||||
|
||||
private setEnvironmentConfig(environment: string): void {
|
||||
public setEnvironmentConfig(environment: string): void {
|
||||
this.ensureEnvironmentIsValid(environment);
|
||||
try {
|
||||
this.environmnetConfig = YAML.parse(
|
||||
readFileSync("src/config/config.yaml", "utf8")
|
||||
)[environment];
|
||||
this.environmentConfig = this.readConfigFile()[environment];
|
||||
} catch (error) {
|
||||
throw Error(`Error reading environment config: (${error})`);
|
||||
}
|
||||
}
|
||||
|
||||
private readConfigFile(): any {
|
||||
return YAML.parse(
|
||||
readFileSync(path.join(this.baseWorkingDirectory, "/config.yaml"), "utf8")
|
||||
);
|
||||
}
|
||||
|
||||
private ensureEnvironmentIsValid(environment: string): void {
|
||||
if (this.validEnvironments.indexOf(environment) === -1) {
|
||||
throw Error(`Config environment is not valid: "${environment}"`);
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
ConfigHandler: require('./config/configHandler.ts'),
|
||||
MixFetchClient: require('./restClient/MixFetchClient.ts')
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
import { createMixFetch } from "@nymproject/mix-fetch-node-commonjs";
|
||||
import * as dotenv from 'dotenv';
|
||||
import path from "path";
|
||||
|
||||
dotenv.config({ path: path.join(__dirname, '../.env') });;
|
||||
|
||||
export class MixFetchClient {
|
||||
public static authToken: string;
|
||||
private baseUrl: string;
|
||||
|
||||
constructor(baseUrl: string) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public async sendGet({
|
||||
route,
|
||||
}: any): Promise<any> {
|
||||
|
||||
const extra = {
|
||||
hiddenGateways: [
|
||||
{
|
||||
owner: process.env.HIDDEN_GATEWAY_OWNER,
|
||||
host: process.env.HIDDEN_GATEWAY_HOST,
|
||||
explicitIp: process.env.HIDDEN_GATEWAY_EXPLICIT_IP,
|
||||
identityKey: process.env.HIDDEN_GATEWAY_IDENTITY_KEY,
|
||||
sphinxKey: process.env.HIDDEN_GATEWAY_SPHINX_KEY,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mixFetchOptions = {
|
||||
nymApiUrl: process.env.PREFERRED_VALIDATOR,
|
||||
preferredGateway: process.env.PREFERRED_GATEWAY,
|
||||
preferredNetworkRequester: process.env.PREFFERED_NETWORK_REQUESTER,
|
||||
mixFetchOverride: {
|
||||
requestTimeoutMs: 60_000,
|
||||
},
|
||||
forceTls: true,
|
||||
extra,
|
||||
};
|
||||
|
||||
const { mixFetch } = await createMixFetch(mixFetchOptions);
|
||||
|
||||
let args = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
mode: "unsafe-ignore-cors"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await mixFetch(`${this.baseUrl}${route}`, args);
|
||||
if (response.status == 200) {
|
||||
const json = await response.json();
|
||||
return json;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
public async sendPost({
|
||||
route,
|
||||
data,
|
||||
}: any): Promise<any> {
|
||||
const extra = {
|
||||
hiddenGateways: [
|
||||
{
|
||||
owner: process.env.HIDDEN_GATEWAY_OWNER,
|
||||
host: process.env.HIDDEN_GATEWAY_HOST,
|
||||
explicitIp: process.env.HIDDEN_GATEWAY_EXPLICIT_IP,
|
||||
identityKey: process.env.HIDDEN_GATEWAY_IDENTITY_KEY,
|
||||
sphinxKey: process.env.HIDDEN_GATEWAY_SPHINX_KEY,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mixFetchOptions = {
|
||||
nymApiUrl: process.env.PREFERRED_VALIDATOR,
|
||||
preferredGateway: process.env.PREFERRED_GATEWAY,
|
||||
preferredNetworkRequester: process.env.PREFFERED_NETWORK_REQUESTER,
|
||||
mixFetchOverride: {
|
||||
requestTimeoutMs: 60_000,
|
||||
},
|
||||
forceTls: true,
|
||||
extra,
|
||||
};
|
||||
|
||||
const { mixFetch } = await createMixFetch(mixFetchOptions);
|
||||
|
||||
let args = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
mode: "unsafe-ignore-cors",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
try {
|
||||
const response = await mixFetch(`${this.baseUrl}${route}`, args);
|
||||
if (response.status == 200) {
|
||||
const json = await response.json();
|
||||
return json;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
HIDDEN_GATEWAY_OWNER=n1ns3v70ul9gnl9l9fkyz8cyxfq75vjcmx8el0t3
|
||||
HIDDEN_GATEWAY_EXPLICIT_IP=35.158.238.80
|
||||
HIDDEN_GATEWAY_HOST=sandbox-gateway1.nymtech.net
|
||||
HIDDEN_GATEWAY_SPHINX_KEY=BoXeUD7ERGmzRauMjJD3itVNnQiH42ncUb6kcVLrb3dy
|
||||
HIDDEN_GATEWAY_IDENTITY_KEY=HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua
|
||||
PREFFERED_NETWORK_REQUESTER="AzGdJ4MU78Ex22NEWfeycbN7bt3PFZr1MtKstAdhfELG.GSxnKnvKPjjQm3FdtsgG5KyhP6adGbPHRmFWDH4XfUpP@HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua"
|
||||
PREFERRED_GATEWAY=HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua
|
||||
PREFERRED_VALIDATOR=https://sandbox-nym-api1.nymtech.net/api
|
||||
@@ -1,5 +1,6 @@
|
||||
import ContractCache from "../../src/endpoints/CirculatingSupply";
|
||||
let contract: ContractCache;
|
||||
jest.setTimeout(60000);
|
||||
|
||||
describe("Get circulating supply", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ContractCache from "../../src/endpoints/ContractCache";
|
||||
|
||||
let contract: ContractCache;
|
||||
jest.setTimeout(60000);
|
||||
|
||||
describe("Get epoch info", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ContractCache from "../../../src/endpoints/ContractCache";
|
||||
|
||||
let contract: ContractCache;
|
||||
jest.setTimeout(60000);
|
||||
|
||||
describe("Get gateway data", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import ContractCache from "../../../src/endpoints/ContractCache";
|
||||
import ConfigHandler from "../../../src/config/configHandler";
|
||||
import ConfigHandler from "../../../../../common/api-test-utils/config/configHandler"
|
||||
|
||||
let contract: ContractCache;
|
||||
let config: ConfigHandler;
|
||||
jest.setTimeout(60000);
|
||||
|
||||
describe("Get mixnode data", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ContractCache from "../../src/endpoints/ContractCache";
|
||||
let contract: ContractCache;
|
||||
jest.setTimeout(60000);
|
||||
|
||||
describe("Get service provider info", (): void => {
|
||||
beforeAll(async (): Promise<void> => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Status from "../../src/endpoints/Status";
|
||||
import ConfigHandler from "../../src/config/configHandler";
|
||||
import ConfigHandler from "../../../../common/api-test-utils/config/configHandler"
|
||||
|
||||
let status: Status;
|
||||
let config: ConfigHandler;
|
||||
@@ -29,7 +29,7 @@ describe("Get gateway data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a gateway history", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.gateway_identity;
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayHistory(identity_key);
|
||||
|
||||
if ("identity" in response) {
|
||||
@@ -47,14 +47,14 @@ describe("Get gateway data", (): void => {
|
||||
});
|
||||
|
||||
it("Get gateway core status count", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.gateway_identity;
|
||||
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.environmnetConfig.gateway_identity;
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayAverageUptime(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
expect(identity_key).toStrictEqual(response.identity);
|
||||
@@ -67,7 +67,7 @@ describe("Get gateway data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a gateway status report", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.gateway_identity;
|
||||
const identity_key = config.environmentConfig.gateway_identity;
|
||||
const response = await status.getGatewayStatusReport(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
expect(identity_key).toStrictEqual(response.identity);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Status from "../../src/endpoints/Status";
|
||||
import ConfigHandler from "../../src/config/configHandler";
|
||||
import ConfigHandler from "../../../../common/api-test-utils/config/configHandler"
|
||||
|
||||
let status: Status;
|
||||
let config: ConfigHandler;
|
||||
@@ -11,7 +11,7 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode report", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
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");
|
||||
@@ -22,7 +22,7 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode stake saturation", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
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");
|
||||
@@ -34,7 +34,7 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode average uptime", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
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);
|
||||
@@ -45,7 +45,7 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode history", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
const identity_key = config.environmentConfig.mix_id;
|
||||
const response = await status.getMixnodeHistory(identity_key);
|
||||
if ("mix_id" in response) {
|
||||
response.history.forEach((x) => {
|
||||
@@ -62,14 +62,14 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode core count", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
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.environmnetConfig.mix_id;
|
||||
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(
|
||||
@@ -83,7 +83,7 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode inclusion probability", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
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");
|
||||
@@ -119,7 +119,7 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("Get a mixnode status", async (): Promise<void> => {
|
||||
const identity_key = config.environmnetConfig.mix_id;
|
||||
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(
|
||||
@@ -155,11 +155,11 @@ describe("Get mixnode data", (): void => {
|
||||
});
|
||||
|
||||
it("with correct data", async (): Promise<void> => {
|
||||
const mix_id = config.environmnetConfig.mix_id;
|
||||
const mix_id = config.environmentConfig.mix_id;
|
||||
const response = await status.sendMixnodeRewardEstimatedComputation(
|
||||
mix_id
|
||||
);
|
||||
expect(typeof response.estimation.delegates).toBe("string");
|
||||
expect(typeof response.estimation.total_node_reward).toBe("string");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Generated
-8546
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "validator-api-test-suite",
|
||||
"name": "nym-api-test-suite",
|
||||
"version": "1.0.0",
|
||||
"description": "a basic validator-api suite to test the validator-api",
|
||||
"description": "a test suite to test the nym-api using mixfetch",
|
||||
"main": "dist/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
@@ -24,7 +24,9 @@
|
||||
"npm": "8.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.0",
|
||||
"@nymproject/mix-fetch-node-commonjs": "^1.2.4-rc.1",
|
||||
"axios": "^0.27.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.21.0",
|
||||
"form-data": "4.0.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
|
||||
@@ -10,20 +10,20 @@ export default class ContractCache extends APIClient {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `circulating-supply`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getTotalSupplyValue(): Promise<number> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `circulating-supply/total-supply-value`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getCirculatingSupplyValue(): Promise<number> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `circulating-supply/circulating-supply-value`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default class ContractCache extends APIClient {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodesDetailed(): Promise<MixnodesDetailed[]> {
|
||||
@@ -26,83 +26,83 @@ export default class ContractCache extends APIClient {
|
||||
route: `mixnodes/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getGateways(): Promise<AllGateways[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateways`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getActiveMixnodes(): Promise<AllMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/active`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getActiveMixnodesDetailed(): Promise<MixnodesDetailed[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/active/detailed`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getRewardedMixnodes(): Promise<AllMixnodes[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/rewarded`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getRewardedMixnodesDetailed(): Promise<MixnodesDetailed[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/rewarded/detailed`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getBlacklistedMixnodes(): Promise<[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnodes/blacklisted`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getBlacklistedGateways(): Promise<[]> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateways/blacklisted`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getEpochRewardParams(): Promise<EpochRewardParams> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `epoch/reward_params`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getCurrentEpoch(): Promise<CurrentEpoch> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `epoch/current`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getServiceProviders(): Promise<ServiceProviders> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `services`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getNymAddressNames(): Promise<NymAddressNames> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `names`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,20 +10,20 @@ export default class NetworkTypes extends APIClient {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `network/details`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getNymContractInfo(): Promise<NymContracts> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `network/nym-contracts`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getNymContractDetailedInfo(): Promise<NymContractsDetailed> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `network/nym-contracts-detailed`,
|
||||
});
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export default class Status extends APIClient {
|
||||
route: `/gateways/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getUnfilteredGateways(): Promise<DetailedGateway[]> {
|
||||
@@ -34,7 +34,7 @@ export default class Status extends APIClient {
|
||||
route: `/gateways/detailed-unfiltered`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getGatewayStatusReport(
|
||||
@@ -44,7 +44,7 @@ export default class Status extends APIClient {
|
||||
route: `/gateway/${identity_key}/report`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getGatewayHistory(
|
||||
@@ -54,7 +54,7 @@ export default class Status extends APIClient {
|
||||
route: `/gateway/${identity_key}/history`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getGatewayCoreCount(identity_key: string): Promise<CoreCount> {
|
||||
@@ -62,7 +62,7 @@ export default class Status extends APIClient {
|
||||
route: `/gateway/${identity_key}/core-status-count`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getGatewayAverageUptime(
|
||||
@@ -72,7 +72,7 @@ export default class Status extends APIClient {
|
||||
route: `/gateway/${identity_key}/avg_uptime`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
// MIXNODES
|
||||
@@ -84,7 +84,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/report`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeStakeSaturation(
|
||||
@@ -94,7 +94,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/stake-saturation`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeCoreCount(mix_id: number): Promise<CoreCount> {
|
||||
@@ -102,7 +102,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/core-status-count`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeRewardComputation(
|
||||
@@ -112,7 +112,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/reward-estimation`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async sendMixnodeRewardEstimatedComputation(
|
||||
@@ -132,8 +132,7 @@ export default class Status extends APIClient {
|
||||
// profit_margin_percent: 10
|
||||
},
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeHistory(
|
||||
@@ -143,7 +142,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/history`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeAverageUptime(
|
||||
@@ -153,7 +152,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/avg_uptime`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeInclusionProbability(
|
||||
@@ -163,7 +162,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/inclusion-probability`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnodeStatus(mix_id: number): Promise<ActiveStatus> {
|
||||
@@ -171,7 +170,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnode/${mix_id}/status`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getAllMixnodeInclusionProbability(): Promise<InclusionProbabilities> {
|
||||
@@ -179,7 +178,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnodes/inclusion_probability`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getDetailedMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
@@ -187,7 +186,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnodes/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getDetailedRewardedMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
@@ -195,7 +194,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnodes/rewarded/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getUnfilteredMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
@@ -203,7 +202,7 @@ export default class Status extends APIClient {
|
||||
route: `/mixnodes/detailed-unfiltered`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getDetailedActiveMixnodes(): Promise<DetailedMixnodes[]> {
|
||||
@@ -211,6 +210,6 @@ export default class Status extends APIClient {
|
||||
route: `/mixnodes/active/detailed`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Logger } from "tslog";
|
||||
import ConfigHandler from "../../config/configHandler";
|
||||
import { RestClient } from "../../restClient/RestClient";
|
||||
import ConfigHandler from "../../../../../common/api-test-utils/config/configHandler";
|
||||
import { MixFetchClient } from "../../../../../common/api-test-utils/restClient/MixFetchClient";
|
||||
|
||||
export abstract class APIClient {
|
||||
protected constructor(serviceUrl: string) {
|
||||
const baseUrl: string = this.config.environmnetConfig.api_base_url;
|
||||
const baseUrl: string = this.config.environmentConfig.api_base_url;
|
||||
this.url = baseUrl + serviceUrl;
|
||||
this.restClient = new RestClient(this.url);
|
||||
this.restClient = new MixFetchClient(this.url);
|
||||
this.serviceName = this.constructor.toString().match(/\w+/g)[1];
|
||||
this.log.info(`The Service URL for ${this.serviceName} is ${this.url}`);
|
||||
}
|
||||
@@ -16,15 +16,15 @@ export abstract class APIClient {
|
||||
protected config = ConfigHandler.getInstance();
|
||||
|
||||
protected log: Logger = new Logger({
|
||||
minLevel: this.config.environmnetConfig.log_level,
|
||||
minLevel: this.config.environmentConfig.log_level,
|
||||
dateTimeTimezone:
|
||||
this.config.environmnetConfig.time_zone ||
|
||||
this.config.environmentConfig.time_zone ||
|
||||
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
});
|
||||
|
||||
protected url: string;
|
||||
|
||||
public restClient: RestClient;
|
||||
public restClient: MixFetchClient;
|
||||
|
||||
protected serviceName: string;
|
||||
}
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
import axios, {
|
||||
AxiosInstance,
|
||||
AxiosRequestConfig,
|
||||
AxiosResponse,
|
||||
Method,
|
||||
} from "axios";
|
||||
import { Logger } from "tslog";
|
||||
import { stringify } from "yaml";
|
||||
|
||||
import https from "https";
|
||||
|
||||
import ConfigHandler from "../config/configHandler";
|
||||
|
||||
const config = ConfigHandler.getInstance();
|
||||
const log = new Logger({
|
||||
minLevel: config.environmnetConfig.log_level,
|
||||
dateTimeTimezone:
|
||||
config.environmnetConfig.time_zone ||
|
||||
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
});
|
||||
|
||||
function isSet(property): boolean {
|
||||
return property !== undefined && property !== null;
|
||||
}
|
||||
|
||||
export class RestClient {
|
||||
private static authToken: string;
|
||||
|
||||
private axiosInstance: AxiosInstance;
|
||||
|
||||
constructor(baseUrl: string) {
|
||||
this.axiosInstance = axios.create({ baseURL: baseUrl });
|
||||
}
|
||||
|
||||
private httpsAgent = new https.Agent({
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
|
||||
// Not returning an actual auth token for this example project.
|
||||
// Just showing how it can be done!
|
||||
static async getToken(requestHeaders: object) {
|
||||
requestHeaders["Authorization"] = `asdf`;
|
||||
}
|
||||
|
||||
public async callEndpoint({
|
||||
route,
|
||||
method,
|
||||
authToken,
|
||||
headers,
|
||||
data,
|
||||
additionalConfigs,
|
||||
params,
|
||||
}: IAxiosCallEndpointArgs): Promise<AxiosResponse> {
|
||||
let response;
|
||||
let responseLog = "Response: ";
|
||||
let requestHeaders = headers;
|
||||
|
||||
// if headers are not passed in, use the default headers
|
||||
if (requestHeaders == undefined) {
|
||||
requestHeaders = { ...config.commonConfig.request_headers };
|
||||
}
|
||||
|
||||
// if authToken is passed in, add it to the request headers
|
||||
if (authToken !== undefined) {
|
||||
requestHeaders = {
|
||||
...requestHeaders,
|
||||
...{
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// if we have not set the auth headers yet, set them
|
||||
else if (!requestHeaders.Authorization) {
|
||||
await RestClient.getToken(requestHeaders);
|
||||
}
|
||||
|
||||
log.debug(
|
||||
RestClient.prepareLogRecord({
|
||||
route,
|
||||
method,
|
||||
headers: requestHeaders,
|
||||
data,
|
||||
additionalConfigs,
|
||||
params,
|
||||
})
|
||||
);
|
||||
|
||||
await this.axiosInstance
|
||||
.request({
|
||||
url: route,
|
||||
method,
|
||||
data,
|
||||
headers: requestHeaders,
|
||||
httpsAgent: this.httpsAgent,
|
||||
params,
|
||||
...additionalConfigs,
|
||||
})
|
||||
.then((res) => {
|
||||
response = res;
|
||||
responseLog = `<Success> Status = ${res.status} ${res.statusText}`;
|
||||
})
|
||||
.catch((error) => {
|
||||
response = error.response;
|
||||
if (response === undefined)
|
||||
responseLog = `<Error> Something wrong happened, did not get proper error from server! (${error.message})`;
|
||||
else
|
||||
responseLog = `<Error> Status = ${response.status} ${response.statusText}, ${error.message}`;
|
||||
});
|
||||
log.debug(responseLog);
|
||||
return response;
|
||||
}
|
||||
|
||||
public async sendPost({
|
||||
route,
|
||||
authToken,
|
||||
data,
|
||||
params,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
}: IAxiosHttpRequestArgs): Promise<any> {
|
||||
return this.callEndpoint({
|
||||
route,
|
||||
method: "POST",
|
||||
authToken,
|
||||
data,
|
||||
params,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
});
|
||||
}
|
||||
|
||||
public async sendGet({
|
||||
route,
|
||||
authToken,
|
||||
params,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
}: IAxiosHttpRequestArgs): Promise<any> {
|
||||
return this.callEndpoint({
|
||||
route,
|
||||
method: "GET",
|
||||
authToken,
|
||||
params,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
});
|
||||
}
|
||||
|
||||
public async sendDelete({
|
||||
route,
|
||||
authToken,
|
||||
params,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
}: IAxiosHttpRequestArgs): Promise<any> {
|
||||
return this.callEndpoint({
|
||||
route,
|
||||
method: "DELETE",
|
||||
authToken,
|
||||
params,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
});
|
||||
}
|
||||
|
||||
public async sendPatch({
|
||||
route,
|
||||
authToken,
|
||||
data,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
}: IAxiosHttpRequestArgs): Promise<any> {
|
||||
return this.callEndpoint({
|
||||
route,
|
||||
method: "PATCH",
|
||||
authToken,
|
||||
data,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
});
|
||||
}
|
||||
|
||||
public async sendPut({
|
||||
route,
|
||||
authToken,
|
||||
data,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
}: IAxiosHttpRequestArgs): Promise<any> {
|
||||
return this.callEndpoint({
|
||||
route,
|
||||
method: "PUT",
|
||||
authToken,
|
||||
data,
|
||||
headers,
|
||||
additionalConfigs,
|
||||
});
|
||||
}
|
||||
|
||||
private static prepareLogRecord({
|
||||
route,
|
||||
method,
|
||||
headers,
|
||||
data,
|
||||
additionalConfigs,
|
||||
params,
|
||||
}: IAxiosCallEndpointArgs): string {
|
||||
let logRecord = `Request: ${method} ${route}`;
|
||||
if (isSet(headers))
|
||||
logRecord = `${logRecord}\nHeaders: ${stringify(headers)}`;
|
||||
|
||||
if (isSet(params)) logRecord = `${logRecord}\nParams: ${stringify(params)}`;
|
||||
|
||||
if (isSet(additionalConfigs)) {
|
||||
logRecord = `${logRecord}\nAdditional Configuration: ${stringify(
|
||||
additionalConfigs
|
||||
)}`;
|
||||
}
|
||||
|
||||
if (isSet(data)) {
|
||||
const jsonData = stringify(data);
|
||||
// We don't want to log anything that isn't json data
|
||||
logRecord = `${logRecord}\nData: ${
|
||||
jsonData === undefined ? "Some data, not JSON!" : jsonData
|
||||
}`;
|
||||
}
|
||||
return logRecord;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IAxiosHttpRequestArgs {
|
||||
route: string;
|
||||
authToken?: string;
|
||||
data?: object;
|
||||
params?: object;
|
||||
headers?: any;
|
||||
additionalConfigs?: AxiosRequestConfig;
|
||||
}
|
||||
|
||||
export interface IAxiosCallEndpointArgs extends IAxiosHttpRequestArgs {
|
||||
method: Method;
|
||||
}
|
||||
+822
-862
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"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"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
dist
|
||||
coverage/
|
||||
.DS_Store
|
||||
.idea/
|
||||
junit.xml
|
||||
@@ -0,0 +1,71 @@
|
||||
import Gateway from "../../src/endpoints/Gateways";
|
||||
import { getGatewayIPAddresses } from "../../src/helpers/helper";
|
||||
|
||||
describe("Get gateway related info", (): void => {
|
||||
let contract: Gateway;
|
||||
let gatewayHosts: string[];
|
||||
beforeAll(async (): Promise<void> => {
|
||||
try {
|
||||
gatewayHosts = await getGatewayIPAddresses();
|
||||
} catch (error) {
|
||||
throw new Error(`Error fetching gateway IP addresses: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async (): Promise<void> => {
|
||||
// Testing only 3 nodes from the list
|
||||
for (let i = 3; i < gatewayHosts.length; i++) {
|
||||
console.log("currently trying gateway host", gatewayHosts[i]);
|
||||
contract = new Gateway(gatewayHosts[i]);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO this test is failing, it's incorrectly entering the else statement
|
||||
it.skip("Get root gateway information", async (): Promise<void> => {
|
||||
const response = await contract.getGatewayInformation();
|
||||
console.log(response);
|
||||
console.log(response.wireguard);
|
||||
if (response.wireguard === null) {
|
||||
console.log("This is the code I should be entering............");
|
||||
expect(response.wireguard).toBeNull();
|
||||
expect(typeof response.mixnet_websockets.ws_port).toBe("number");
|
||||
expect(typeof response.mixnet_websockets.wss_port).toBe("number");
|
||||
return;
|
||||
} else {
|
||||
console.log(
|
||||
"This is wrong, I shouldn't be in the else statement.........",
|
||||
);
|
||||
console.log(response.wireguard);
|
||||
expect(typeof response.wireguard.port).toBe("number");
|
||||
expect(typeof response.wireguard.public_key).toBe("string");
|
||||
expect(typeof response.mixnet_websockets.ws_port).toBe("number");
|
||||
expect(typeof response.mixnet_websockets.wss_port).toBe("number");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get client interfaces supported by gateway", async (): Promise<void> => {
|
||||
const response = await contract.getGatewayClientInterfaces();
|
||||
if (response.wireguard === null) {
|
||||
expect(response.wireguard).toBeNull();
|
||||
} else {
|
||||
expect(typeof response.wireguard.port).toBe("number");
|
||||
expect(typeof response.wireguard.public_key).toBe("string");
|
||||
expect(typeof response.mixnet_websockets.ws_port).toBe("number");
|
||||
expect(typeof response.mixnet_websockets.wss_port).toBe("number");
|
||||
}
|
||||
});
|
||||
|
||||
it("Get mixnet websocket info", async (): Promise<void> => {
|
||||
const response = await contract.getMixnetWebsocketInfo();
|
||||
expect(typeof response.ws_port).toBe("number");
|
||||
expect(
|
||||
typeof response.wss_port === "number" || response.wss_port === null,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
// it("Get wireguard info", async (): Promise<void> => {
|
||||
// const response = await contract.getWireguardInfo();
|
||||
// expect(typeof response.port).toBe("number");
|
||||
// expect(typeof response.public_key).toBe("string");
|
||||
// });
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import Mixnode from "../../src/endpoints/Mixnodes";
|
||||
import { getMixnodeIPAddresses } from '../../src/helpers/helper';
|
||||
|
||||
describe("Get mixnode related info", (): void => {
|
||||
let contract: Mixnode;
|
||||
let mixnodeHosts: string[];
|
||||
beforeAll(async (): Promise<void> => {
|
||||
try {
|
||||
mixnodeHosts = await getMixnodeIPAddresses();
|
||||
console.log(mixnodeHosts)
|
||||
} catch (error) {
|
||||
throw new Error(`Error fetching mixnode IP addresses: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async (): Promise<void> => {
|
||||
// Testing only 3 nodes from the list
|
||||
for (let i = 3; i < mixnodeHosts.length; i++) {
|
||||
console.log("currently trying mixnode host", mixnodeHosts[i])
|
||||
contract = new Mixnode(mixnodeHosts[i]);
|
||||
}
|
||||
});
|
||||
|
||||
it("Get mixnode details", async (): Promise<void> => {
|
||||
const response = await contract.getMixnodeInfo();
|
||||
// This response is currently just empty {}, amend it when it changes
|
||||
expect(response).toEqual({});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import Nodes from "../../src/endpoints/Node";
|
||||
import { getGatewayIPAddresses } from "../../src/helpers/helper";
|
||||
|
||||
describe("Get Node information", (): void => {
|
||||
let contract: Nodes;
|
||||
let gatewayHosts: string[];
|
||||
beforeAll(async (): Promise<void> => {
|
||||
try {
|
||||
gatewayHosts = await getGatewayIPAddresses();
|
||||
// console.log(gatewayHosts);
|
||||
} catch (error) {
|
||||
throw new Error(`Error fetching gateway IP addresses: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async (): Promise<void> => {
|
||||
for (let i = 0; i < gatewayHosts.length; i++) {
|
||||
// console.log("currently trying gateway host", gatewayHosts[i]);
|
||||
contract = new Nodes(gatewayHosts[i]);
|
||||
}
|
||||
});
|
||||
|
||||
it("Get build data for the binary running the API", async (): Promise<void> => {
|
||||
const response = await contract.getBuildInformation();
|
||||
expect(typeof response.binary_name).toBe("string");
|
||||
expect(typeof response.build_timestamp).toBe("string");
|
||||
expect(typeof response.build_version).toBe("string");
|
||||
expect(typeof response.cargo_profile).toBe("string");
|
||||
expect(typeof response.commit_branch).toBe("string");
|
||||
expect(typeof response.commit_sha).toBe("string");
|
||||
expect(typeof response.commit_timestamp).toBe("string");
|
||||
expect(typeof response.rustc_channel).toBe("string");
|
||||
expect(typeof response.rustc_version).toBe("string");
|
||||
});
|
||||
|
||||
it("Get host information for the node", async (): Promise<void> => {
|
||||
const response = await contract.getHostInformation();
|
||||
response.data.ip_address.forEach((x) => {
|
||||
expect(typeof x).toBe("string");
|
||||
});
|
||||
// expect(typeof response.data.hostname).toBe("string" || "null");
|
||||
expect(
|
||||
typeof response.data.hostname === "string" ||
|
||||
response.data.hostname === null,
|
||||
).toBe(true);
|
||||
expect(typeof response.data.keys.ed25519).toBe("string");
|
||||
expect(typeof response.data.keys.x25519).toBe("string");
|
||||
expect(typeof response.signature).toBe("string");
|
||||
});
|
||||
|
||||
it("Get roles supported by the node", async (): Promise<void> => {
|
||||
const response = await contract.getSupportedRoles();
|
||||
expect(typeof response.gateway_enabled).toBe("boolean");
|
||||
expect(typeof response.mixnode_enabled).toBe("boolean");
|
||||
expect(typeof response.network_requester_enabled).toBe("boolean");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
reporters: ["default", "jest-junit"],
|
||||
collectCoverageFrom: ["src/**/*.ts"],
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "nym-node-test-suite",
|
||||
"version": "1.0.0",
|
||||
"description": "a basic nym-node-api suite to test the nym-node-api using mixfetch",
|
||||
"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 --fix --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": {
|
||||
"@nymproject/mix-fetch-node-commonjs": "^1.2.4-rc.1",
|
||||
"eslint": "^8.51.0",
|
||||
"form-data": "4.0.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"tslog": "../../node_modules/tslog",
|
||||
"uuid": "8.3.2",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.5",
|
||||
"@types/node": "^20.8.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
"axios-mock-adapter": "^1.20.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"jest": "^28.1.3",
|
||||
"jest-junit": "^14.0.0",
|
||||
"prettier": "^3.0.3",
|
||||
"process": "0.11.10",
|
||||
"ts-jest": "28.0.7",
|
||||
"typescript": "^4.7.4",
|
||||
"uuidv4": "^6.2.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
ClientInterfaces,
|
||||
MixnetWebsockets,
|
||||
Wireguard,
|
||||
} from "../types/GatewayTypes";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class Gateway extends APIClient {
|
||||
constructor(baseUrl: string) {
|
||||
super(baseUrl, "/");
|
||||
}
|
||||
|
||||
public async getGatewayInformation(): Promise<ClientInterfaces> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateway`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getGatewayClientInterfaces(): Promise<ClientInterfaces> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateway/client-interfaces`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getMixnetWebsocketInfo(): Promise<MixnetWebsockets> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateway/client-interfaces/mixnet-websockets`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getWireguardInfo(): Promise<Wireguard> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `gateway/client-interfaces/wireguard`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Mixnodes } from "../types/MixnodeTypes";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class Mixnode extends APIClient {
|
||||
constructor(baseUrl: string) {
|
||||
super(baseUrl, "/");
|
||||
}
|
||||
|
||||
public async getMixnodeInfo(): Promise<Mixnodes> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `mixnode`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { BuildInformation, HostInformation, Roles } from "../types/NodeTypes";
|
||||
import { APIClient } from "./abstracts/APIClient";
|
||||
|
||||
export default class Nodes extends APIClient {
|
||||
constructor(baseUrl: string) {
|
||||
super(baseUrl, "/");
|
||||
}
|
||||
|
||||
public async getBuildInformation(): Promise<BuildInformation> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `build-information`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getHostInformation(): Promise<HostInformation> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `host-information`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
public async getSupportedRoles(): Promise<Roles> {
|
||||
const response = await this.restClient.sendGet({
|
||||
route: `roles`,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Logger } from "tslog";
|
||||
import ConfigHandler from "../../../../../common/api-test-utils/config/configHandler";
|
||||
import { MixFetchClient } from "../../../../../common/api-test-utils/restClient/MixFetchClient";
|
||||
|
||||
export abstract class APIClient {
|
||||
protected constructor(baseUrl: string, serviceUrl: string) {
|
||||
this.url = baseUrl + serviceUrl;
|
||||
this.restClient = new MixFetchClient(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: MixFetchClient;
|
||||
|
||||
protected serviceName: string;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { APIClient } from "../../src/endpoints/abstracts/APIClient";
|
||||
import ConfigHandler from "../../../../common/api-test-utils/config/configHandler";
|
||||
|
||||
const configHandler = ConfigHandler.getInstance();
|
||||
|
||||
let helper: Helper;
|
||||
const apiBaseUrl = configHandler.environmentConfig.api_base_url;
|
||||
export default class Helper extends APIClient {
|
||||
constructor() {
|
||||
super(apiBaseUrl, "");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getGatewayIPAddresses(): Promise<string[]> {
|
||||
helper = new Helper();
|
||||
try {
|
||||
const response = await helper.restClient.sendGet({
|
||||
route: `/gateways`,
|
||||
});
|
||||
const hosts = response.map((item: { gateway: { host: string } }) => {
|
||||
const host = item.gateway.host;
|
||||
const apiUrl = `http://${host}:8080/api/v1`;
|
||||
return apiUrl;
|
||||
});
|
||||
return hosts;
|
||||
} catch (error) {
|
||||
throw new Error(`Error fetching gateway IP addresses: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getMixnodeIPAddresses(): Promise<string[]> {
|
||||
helper = new Helper();
|
||||
try {
|
||||
const response = await helper.restClient.sendGet({
|
||||
route: `/mixnodes`,
|
||||
});
|
||||
const hosts = response.map((item: { bond_information: { mix_node: { host: string } } } ) => {
|
||||
const host = item.bond_information.mix_node.host;
|
||||
const apiUrl = `http://${host}:8000/api/v1`;
|
||||
return apiUrl;
|
||||
});
|
||||
return hosts;
|
||||
} catch (error) {
|
||||
throw new Error(`Error fetching mixnode IP addresses: ${error.message}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export interface ClientInterfaces {
|
||||
mixnet_websockets: MixnetWebsockets;
|
||||
wireguard: Wireguard;
|
||||
}
|
||||
|
||||
export interface MixnetWebsockets {
|
||||
ws_port: number | null;
|
||||
wss_port: number | null;
|
||||
}
|
||||
|
||||
export interface Wireguard {
|
||||
port: number | null;
|
||||
public_key: string;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export interface Mixnodes {}
|
||||
@@ -0,0 +1,33 @@
|
||||
export interface BuildInformation {
|
||||
binary_name: string;
|
||||
build_timestamp: string;
|
||||
build_version: string;
|
||||
cargo_profile: string;
|
||||
commit_branch: string;
|
||||
commit_sha: string;
|
||||
commit_timestamp: string;
|
||||
rustc_channel: string;
|
||||
rustc_version: string;
|
||||
}
|
||||
|
||||
export interface HostInformation {
|
||||
data: Data;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
export interface Data {
|
||||
hostname: string | null;
|
||||
ip_address: string[];
|
||||
keys: Keys;
|
||||
}
|
||||
|
||||
export interface Keys {
|
||||
ed25519: string;
|
||||
x25519: string;
|
||||
}
|
||||
|
||||
export interface Roles {
|
||||
gateway_enabled: boolean;
|
||||
mixnode_enabled: boolean;
|
||||
network_requester_enabled: boolean;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"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/*"],
|
||||
"common/api-test-utils": ["../../common/api-test-utils/index.ts"]
|
||||
},
|
||||
"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
+5
-1
@@ -51,6 +51,10 @@
|
||||
"lerna": "^7.3.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"@npmcli/node-gyp": "^3.0.0",
|
||||
"node-gyp": "^9.3.1"
|
||||
"node-gyp": "^9.3.1",
|
||||
"tslog": "3.3.3",
|
||||
"@nymproject/mix-fetch-node-commonjs": "^1.2.4-rc.1",
|
||||
"fake-indexeddb": "^5.0.0",
|
||||
"ws": "^8.14.2"
|
||||
}
|
||||
}
|
||||
@@ -17575,7 +17575,7 @@ source-map-resolve@^0.5.0:
|
||||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.21, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||
@@ -18660,6 +18660,13 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
|
||||
tslog@3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.3.3.tgz#751a469e0d36841bd7e03676c27e53e7ffe9bc3d"
|
||||
integrity sha512-lGrkndwpAohZ9ntQpT+xtUw5k9YFV1DjsksiWQlBSf82TTqsSAWBARPRD9juI730r8o3Awpkjp2aXy9k+6vr+g==
|
||||
dependencies:
|
||||
source-map-support "^0.5.21"
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
||||
|
||||
Reference in New Issue
Block a user