Getting all our nym-api tests to run via mixfetch

This commit is contained in:
benedettadavico
2023-11-10 17:43:15 +01:00
parent aabc4e41ba
commit b14efb211c
18 changed files with 150 additions and 215 deletions
+22 -22
View File
@@ -1,21 +1,17 @@
import { dir } from "console";
import { readFileSync } from "fs";
import { dirname } from "path";
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 };
private currentEnvironment: string;
public environment: string;
public environmentConfig: {
log_level: TLogLevelName;
time_zone: string;
@@ -26,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 {
@@ -39,10 +48,7 @@ class ConfigHandler {
private setCommonConfig(): void {
try {
const baseWorkingDirectory = __dirname;
this.commonConfig = YAML.parse(
readFileSync(baseWorkingDirectory + "/config.yaml", "utf8"),
).common;
this.commonConfig = this.readConfigFile().common;
} catch (error) {
throw Error(`Error reading common config: (${error})`);
}
@@ -51,21 +57,15 @@ class ConfigHandler {
private setEnvironmentConfig(environment: string): void {
this.ensureEnvironmentIsValid(environment);
try {
const baseWorkingDirectory = __dirname;
this.environmentConfig = YAML.parse(
readFileSync(baseWorkingDirectory + "/config.yaml", "utf8"),
)[environment];
this.environmentConfig = this.readConfigFile()[environment];
} catch (error) {
console.log("fadsfasdfasdfsdfsa")
throw Error(`Error reading environment config: (${error})`);
}
}
public getEnvironmentConfig(environment: string): any {
const baseWorkingDirectory = __dirname;
return (
this.environmentConfig ||
YAML.parse(readFileSync(baseWorkingDirectory + "/config.yaml", "utf8"))[environment]
private readConfigFile(): any {
return YAML.parse(
readFileSync(path.join(this.baseWorkingDirectory, "/config.yaml"), "utf8")
);
}
+1 -1
View File
@@ -1,4 +1,4 @@
module.exports = {
ConfigHandler: require('./config/configHandler.ts'),
RestClient: require('./restClient/RestClient.ts')
MixFetchClient: require('./restClient/MixFetchClient.ts')
};
+8
View File
@@ -0,0 +1,8 @@
HIDDEN_GATEWAY_OWNER=n1kymvkx6vsq7pvn6hfurkpg06h3j4gxj4em7tlg
HIDDEN_GATEWAY_EXPLICIT_IP=213.219.38.119
HIDDEN_GATEWAY_HOST=mainnet-gateway.nymte.ch
HIDDEN_GATEWAY_SPHINX_KEY=CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX
HIDDEN_GATEWAY_IDENTITY_KEY=E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM
PREFFERED_NETWORK_REQUESTER="RwMHfHBCxSYprzPPSayzJeTGThAVJdohfJfMBhv7JnK.2XTA2PpFqxWNUHT1QdGvHjGSkciEcre1rbzdRnjmAvnZ@EmksoVk8Q7RZZH8atvZspDShD7Ekq6vDPnjK4LCQ7DUv"
PREFERRED_GATEWAY=E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM
PREFERRED_VALIDATOR=https://validator.nymtech.net/api
@@ -0,0 +1,59 @@
import ConfigHandler from "../config/configHandler";
import { createMixFetch } from "@nymproject/mix-fetch-node-commonjs";
import * as dotenv from 'dotenv';
import path from "path";
dotenv.config({ path: path.join(__dirname, '../.env') });;
const config = ConfigHandler.getInstance();
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"
};
const response = await mixFetch(`${this.baseUrl}${route}`, args);
const json = await response.json();
return json;
};
}
@@ -1,147 +0,0 @@
import { Logger } from "tslog";
import { stringify } from "yaml";
import https from "https";
import ConfigHandler from "../config/configHandler";
const { createMixFetch } = require("@nymproject/mix-fetch-node-commonjs");
const config = ConfigHandler.getInstance();
const log = new Logger({
minLevel: config.environmentConfig.log_level,
dateTimeTimezone:
config.environmentConfig.time_zone ||
Intl.DateTimeFormat().resolvedOptions().timeZone,
});
export class RestClient {
public static authToken: string;
private baseUrl: string;
private mixFetch: any;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
this.mixFetch = this.initialiseMixFetch
}
// MIXFETCH
private initialiseMixFetch() {
const extra = {
hiddenGateways: [
{
owner: "n1ns3v70ul9gnl9l9fkyz8cyxfq75vjcmx8el0t3",
host: "sandbox-gateway1.nymtech.net",
explicitIp: "35.158.238.80",
identityKey: "HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua",
sphinxKey: "BoXeUD7ERGmzRauMjJD3itVNnQiH42ncUb6kcVLrb3dy",
},
],
};
const mixFetchOptions = {
nymApiUrl: "https://sandbox-nym-api1.nymtech.net/api",
preferredGateway: "HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua",
preferredNetworkRequester:
"AzGdJ4MU78Ex22NEWfeycbN7bt3PFZr1MtKstAdhfELG.GSxnKnvKPjjQm3FdtsgG5KyhP6adGbPHRmFWDH4XfUpP@HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua",
mixFetchOverride: {
requestTimeoutMs: 60_000,
},
forceTls: true,
extra,
};
const { mixFetch } = await createMixFetch(mixFetchOptions);
return mixFetch;
}
static async getToken(requestHeaders: object) {
requestHeaders["Authorization"] = `asdf`;
}
public async callEndpoint({
route,
method,
authToken,
headers,
data,
additionalConfigs,
params,
}: any): Promise<any> {
let response;
let responseLog = "Response: ";
let requestHeaders = headers || {};
// if authToken is passed in, add it to the request headers
if (authToken !== undefined) {
requestHeaders = {
...requestHeaders,
...{
Authorization: `Bearer ${authToken}`,
},
};
} else if (!requestHeaders.Authorization) {
await RestClient.getToken(requestHeaders);
}
log.debug(
RestClient.prepareLogRecord({
route,
method,
headers: requestHeaders,
data,
additionalConfigs,
params,
}),
);
const mixRequestInit: MixRequestInit = {
method,
headers: requestHeaders,
agent: new https.Agent({
rejectUnauthorized: false,
}),
body: data,
params,
...additionalConfigs,
};
try {
const res = await this.mixFetch(`${this.baseUrl}${route}`, mixRequestInit);
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 the server! (${error.message})`;
else
responseLog = `<Error> Status = ${response.status} ${response.statusText}, ${error.message}`;
}
log.debug(responseLog);
return response;
}
private static prepareLogRecord({
route,
method,
headers,
data,
additionalConfigs,
params,
}: any): string {
let logRecord = `Request: ${method} ${route}`;
if (headers) logRecord = `${logRecord}\nHeaders: ${stringify(headers)}`;
if (params) logRecord = `${logRecord}\nParams: ${stringify(params)}`;
if (additionalConfigs)
logRecord = `${logRecord}\nAdditional Configuration: ${stringify(
additionalConfigs,
)}`;
if (data) {
const jsonData = stringify(data);
logRecord = `${logRecord}\nData: ${
jsonData === undefined ? "Some data, not JSON!" : jsonData
}`;
}
return logRecord;
}
}
+8
View File
@@ -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> => {
@@ -3,6 +3,7 @@ import ConfigHandler from "../../../../../common/api-test-utils/config/configHan
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
View File
@@ -28,6 +28,7 @@
"@nymproject/mix-fetch-node-commonjs": "^1.2.4-rc.0",
"@nymproject/mix-fetch-wasm-node": ">=1.2.1-rc.0 || ^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;
}
}
+13 -13
View File
@@ -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;
}
}
+3 -3
View File
@@ -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;
}
}
+20 -20
View File
@@ -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(
@@ -133,7 +133,7 @@ export default class Status extends APIClient {
},
});
return response.data;
return response;
}
public async getMixnodeHistory(
@@ -143,7 +143,7 @@ export default class Status extends APIClient {
route: `/mixnode/${mix_id}/history`,
});
return response.data;
return response;
}
public async getMixnodeAverageUptime(
@@ -153,7 +153,7 @@ export default class Status extends APIClient {
route: `/mixnode/${mix_id}/avg_uptime`,
});
return response.data;
return response;
}
public async getMixnodeInclusionProbability(
@@ -163,7 +163,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 +171,7 @@ export default class Status extends APIClient {
route: `/mixnode/${mix_id}/status`,
});
return response.data;
return response;
}
public async getAllMixnodeInclusionProbability(): Promise<InclusionProbabilities> {
@@ -179,7 +179,7 @@ export default class Status extends APIClient {
route: `/mixnodes/inclusion_probability`,
});
return response.data;
return response;
}
public async getDetailedMixnodes(): Promise<DetailedMixnodes[]> {
@@ -187,7 +187,7 @@ export default class Status extends APIClient {
route: `/mixnodes/detailed`,
});
return response.data;
return response;
}
public async getDetailedRewardedMixnodes(): Promise<DetailedMixnodes[]> {
@@ -195,7 +195,7 @@ export default class Status extends APIClient {
route: `/mixnodes/rewarded/detailed`,
});
return response.data;
return response;
}
public async getUnfilteredMixnodes(): Promise<DetailedMixnodes[]> {
@@ -203,7 +203,7 @@ export default class Status extends APIClient {
route: `/mixnodes/detailed-unfiltered`,
});
return response.data;
return response;
}
public async getDetailedActiveMixnodes(): Promise<DetailedMixnodes[]> {
@@ -211,6 +211,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 "../../../../../common/api-test-utils/config/configHandler";
import { RestClient } from "../../../../../common/api-test-utils/restClient/RestClient";
import { MixFetchClient } from "../../../../../common/api-test-utils/restClient/MixFetchClient";
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.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}`);
}
@@ -24,7 +24,7 @@ export abstract class APIClient {
protected url: string;
public restClient: RestClient;
public restClient: MixFetchClient;
protected serviceName: string;
}
+4 -1
View File
@@ -52,6 +52,9 @@
"npm-run-all": "^4.1.5",
"@npmcli/node-gyp": "^3.0.0",
"node-gyp": "^9.3.1",
"tslog": "3.3.3"
"tslog": "3.3.3",
"@nymproject/mix-fetch-node-commonjs": "^1.2.4-rc.0",
"fake-indexeddb": "^5.0.0",
"ws": "^8.14.2"
}
}