Compare commits
1 Commits
test_crate2
...
valdiator
| Author | SHA1 | Date | |
|---|---|---|---|
| f95e9a7d37 |
@@ -0,0 +1,6 @@
|
||||
NYMD_URL=https://sandbox-validator.nymtech.net
|
||||
VALIDATOR_API=https://sandbox-validator.nymtech.net/api
|
||||
MIXNET_CONTRACT=nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j
|
||||
VESTING_CONTRACT=nymt1nc5tatafv6eyq7llkr2gv50ff9e22mnfp9pc5s
|
||||
CURRENCY_PREFIX=nymt
|
||||
CHAIN_ID=nym-sandbox
|
||||
@@ -3,26 +3,20 @@ Nym Validator Client
|
||||
|
||||
A TypeScript client for interacting with CosmWasm smart contracts in Nym validators.
|
||||
|
||||
Running examples
|
||||
-----------------
|
||||
|
||||
With the code checked out, `cd examples`. This folder contains runnable example code that will set up a blockchain and allow you to interact with it through the client.
|
||||
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
The tests will be separated into three categories: unit, integration and mock.
|
||||
|
||||
Currently the command to run all tests:
|
||||
|
||||
```
|
||||
npm test
|
||||
```
|
||||
|
||||
You can also trigger test execution with a test watcher. I don't have the centuries of life left to me that are needed to fight through the arcana of wiring up a working TypeScript mocha triggered execution setup, so for now my Cargo-based hack is:
|
||||
The tests require `.env.example` being renamed to `.env`. The variables and their values for these tests are currently pointing to the `nym-sandbox` environment.
|
||||
|
||||
|
||||
```
|
||||
cargo watch -s "cd clients/validator && npm test"
|
||||
```
|
||||
|
||||
It's ugly but works fine if you have Cargo installed. TypeScript setup help happily accepted here.
|
||||
`Tests are still in development` - the test libary is `jest` and the test script will execute currently with: `--coverage --verbosity false`
|
||||
|
||||
Generating Documentation
|
||||
------------------------
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||
setupFiles: ["dotenv/config"]
|
||||
};
|
||||
@@ -6,9 +6,7 @@
|
||||
"main": "./dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "ts-mocha tests/**/*.test.ts",
|
||||
"coverage": "nyc npm test",
|
||||
"test": "jest --coverage --verbose false",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"docs": "typedoc --out docs src/index.ts"
|
||||
@@ -21,27 +19,21 @@
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.15",
|
||||
"@types/expect": "^24.3.0",
|
||||
"@types/mocha": "^8.2.1",
|
||||
"@types/jest": "27.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
||||
"@typescript-eslint/parser": "^5.7.0",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^7.18.0",
|
||||
"eslint-config-airbnb": "^19.0.2",
|
||||
"eslint-config-airbnb-typescript": "^16.1.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-import-resolver-root-import": "^1.0.4",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-mocha": "^10.0.3",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"mocha": "^8.2.1",
|
||||
"moq.ts": "^7.2.0",
|
||||
"nyc": "^15.1.0",
|
||||
"jest": "^27.4.5",
|
||||
"prettier": "^2.5.1",
|
||||
"ts-mocha": "^8.0.0",
|
||||
"ts-jest": "^27.1.2",
|
||||
"typedoc": "^0.20.27",
|
||||
"typescript": "^4.1.3"
|
||||
"typescript": "^4.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/cosmwasm-stargate": "^0.27.0-rc2",
|
||||
@@ -51,6 +43,7 @@
|
||||
"@cosmjs/stargate": "^0.27.0-rc2",
|
||||
"@cosmjs/tendermint-rpc": "^0.27.0-rc2",
|
||||
"axios": "^0.21.1",
|
||||
"cosmjs-types": "^0.4.0"
|
||||
"cosmjs-types": "^0.4.0",
|
||||
"dotenv": "^10.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@ import axios from 'axios';
|
||||
import { GasPrice } from '@cosmjs/stargate';
|
||||
|
||||
export function nymGasPrice(prefix: string): GasPrice {
|
||||
return GasPrice.fromString(`0.025u${prefix}`); // TODO: ideally this ugly conversion shouldn't be hardcoded here.
|
||||
if (typeof prefix === 'string') {
|
||||
return GasPrice.fromString(`0.025u${prefix}`); // TODO: ideally this ugly conversion shouldn't be hardcoded here.
|
||||
}
|
||||
else {
|
||||
throw new Error(`${prefix} is not of type string`);
|
||||
}
|
||||
}
|
||||
|
||||
export const downloadWasm = async (url: string): Promise<Uint8Array> => {
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import validatorClient from "../../src/index";
|
||||
import { config } from '../test-utils/config';
|
||||
|
||||
let client: validatorClient;
|
||||
let mnemonic: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
mnemonic = validatorClient.randomMnemonic();
|
||||
client = await validatorClient.connect(
|
||||
mnemonic,
|
||||
config.NYMD_URL as string,
|
||||
config.VALIDATOR_API as string,
|
||||
config.CURRENCY_PREFIX as string,
|
||||
config.MIXNET_CONTRACT as string,
|
||||
config.VESTING_CONTRACT as string
|
||||
);
|
||||
});
|
||||
|
||||
//todos
|
||||
//we want to mock the majority of these tests
|
||||
//and keep a few integration tests in place
|
||||
|
||||
describe("connect to the nym validator client and perform integration tests against the current testnet", () => {
|
||||
test("get cached mixnodes", async () => {
|
||||
try {
|
||||
const response = await client.getCachedMixnodes();
|
||||
//expect all mixnodes to have their owner address
|
||||
response.forEach(mixnodeDetails => {
|
||||
expect(mixnodeDetails.owner).toHaveLength(43)
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get balance of address and denom of the network", async () => {
|
||||
try {
|
||||
//provide a users address and get their balance
|
||||
//we expect their balance to be zero, as it's a new account
|
||||
const address = await validatorClient.mnemonicToAddress(mnemonic, config.CURRENCY_PREFIX as string);
|
||||
const response = await client.getBalance(address);
|
||||
expect(response.amount).toStrictEqual("0");
|
||||
expect(response.denom).toBe("unymt");
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get minimium pledge amount for a mixnode", async () => {
|
||||
try {
|
||||
const response = await client.minimumMixnodePledge();
|
||||
expect(response.amount).toBe("100000000");
|
||||
expect(response.denom).toBe(config.CURRENCY_PREFIX as string);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get minimium gateway pledge amount", async () => {
|
||||
try {
|
||||
const response = await client.minimumGatewayPledge();
|
||||
expect(response.amount).toBe("100000000");
|
||||
expect(response.denom).toBe(config.CURRENCY_PREFIX as string);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get current mixnet contract address", () => {
|
||||
try {
|
||||
const response = client.mixnetContract;
|
||||
expect(response).toStrictEqual(config.MIXNET_CONTRACT as string)
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get current vesting contract address", () => {
|
||||
try {
|
||||
const response = client.vestingContract;
|
||||
expect(response).toStrictEqual(config.VESTING_CONTRACT as string)
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import SigningClient from '../../src/signing-client';
|
||||
import validator from "../../src/index";
|
||||
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate';
|
||||
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
|
||||
import { config } from '../test-utils/config';
|
||||
|
||||
let cosmWasmClient: CosmWasmClient;
|
||||
let signingClient: SigningClient;
|
||||
let mnemonic: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
cosmWasmClient = await SigningClient.connect(config.NYMD_URL as string);
|
||||
|
||||
mnemonic = validator.randomMnemonic();
|
||||
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic)
|
||||
signingClient = await SigningClient.connectWithNymSigner(
|
||||
wallet,
|
||||
config.NYMD_URL as string,
|
||||
config.VALIDATOR_API as string,
|
||||
config.CURRENCY_PREFIX as string);
|
||||
});
|
||||
|
||||
describe("alternate between the signing clients of nym and perform basic requests", () => {
|
||||
test("retrieve balance using the cosmwasm client", async () => {
|
||||
try {
|
||||
const randomAddress = await validator.mnemonicToAddress(mnemonic, config.CURRENCY_PREFIX as string);
|
||||
const balance = await cosmWasmClient.getBalance(randomAddress, config.CURRENCY_PREFIX as string);
|
||||
expect(balance.denom).toStrictEqual(config.CURRENCY_PREFIX as string);
|
||||
expect(balance.amount).toStrictEqual("0");
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
test("get the chain id of the network", async () => {
|
||||
try {
|
||||
//pass these values in environment variables in the future
|
||||
const chainId = await cosmWasmClient.getChainId();
|
||||
expect(chainId).toStrictEqual(config.CHAIN_ID as string);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
test("get height then search its block", async () => {
|
||||
try {
|
||||
const height = await cosmWasmClient.getHeight()
|
||||
const block = await cosmWasmClient.getBlock(height);
|
||||
expect(block.header.chainId).toStrictEqual(config.CHAIN_ID as string);
|
||||
expect(block.header.height).toStrictEqual(height);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
test("get current reward pool", async () => {
|
||||
try {
|
||||
//this is due to change due to when rewards get distributed
|
||||
const rewards = await signingClient.getRewardPool(config.MIXNET_CONTRACT as string);
|
||||
expect(rewards).toStrictEqual("250000000000000");
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import ValidatorApiQuerier from '../../src/validator-api-querier';
|
||||
import { config } from '../test-utils/config';
|
||||
import { now, elapsed} from '../test-utils/utils';
|
||||
|
||||
let client: ValidatorApiQuerier;
|
||||
|
||||
beforeEach(() => {
|
||||
client = new ValidatorApiQuerier(config.VALIDATOR_API as string);
|
||||
});
|
||||
|
||||
//todos
|
||||
//we want to mock the majority of these tests
|
||||
//and keep a few integration tests in place
|
||||
|
||||
describe("call out to the validator api and run queries", () => {
|
||||
test.skip("build client and get all mixnodes", async () => {
|
||||
try {
|
||||
//this test was currently ran against a set of prefix data
|
||||
//this will change
|
||||
const ownerAddress = "nymt1ydqkmz0ddpvkd3l0vyf8k5xjrqtcnxxvhlpdsr";
|
||||
let response = await client.getActiveMixnodes();
|
||||
expect(response[0].owner).toStrictEqual(ownerAddress);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get rewarded mixnodes", async () => {
|
||||
try {
|
||||
// we assume that all mixnodes will have their owners address
|
||||
// also active sets will determine rewarded mixnodes
|
||||
let response = await client.getRewardedMixnodes();
|
||||
|
||||
response.forEach(rNode => {
|
||||
expect(rNode.owner.length).toStrictEqual(43);
|
||||
})
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
test("get cached gateways and it should be six", async () => {
|
||||
try {
|
||||
//current gateways running in sandbox-testnet 6
|
||||
let response = await client.getCachedGateways();
|
||||
expect(response.length).toStrictEqual(6);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test("get cached mixnodes", async () => {
|
||||
try {
|
||||
const start = now();
|
||||
let response = await client.getCachedMixnodes();
|
||||
response.forEach(mixnode => {
|
||||
expect(mixnode.owner.length).toStrictEqual(43);
|
||||
})
|
||||
console.log(elapsed(start, true));
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export const config = {
|
||||
NYMD_URL: process.env.NYMD_URL,
|
||||
VALIDATOR_API: process.env.VALIDATOR_API,
|
||||
MIXNET_CONTRACT: process.env.MIXNET_CONTRACT,
|
||||
VESTING_CONTRACT: process.env.MIXNET_CONTRACT,
|
||||
USER_MNEMONIC: process.env.MNEMONIC,
|
||||
CURRENCY_PREFIX: process.env.CURRENCY_PREFIX,
|
||||
CHAIN_ID: process.env.CHAIN_ID
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// timer actions
|
||||
// Store current time as `start`
|
||||
export const now = (eventName = null) => {
|
||||
if (eventName) {
|
||||
console.log(`Started ${eventName}..`);
|
||||
}
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
//takes arg of start time
|
||||
export const elapsed = (beginning: number, log = false) => {
|
||||
const duration = new Date().getTime() - beginning;
|
||||
if (log) {
|
||||
console.log(`${duration / 1000}s`);
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
const currency = require('../../src/currency');
|
||||
|
||||
describe("provide unit tests around the the currency module", () => {
|
||||
test.skip("convert to native balance", () => {
|
||||
const decimal = "12.0346";
|
||||
const value = currency.printableBalanceToNative(decimal);
|
||||
expect(value).toStrictEqual("12034600");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
const stargate = require("../../src/stargate-helper");
|
||||
import { config } from '../test-utils/config';
|
||||
|
||||
describe("test the stargate functions within the client", () => {
|
||||
test("test that the gas price is returned correctly", () => {
|
||||
const nymCurrency = config.CURRENCY_PREFIX as string;
|
||||
const getGasPrice = stargate.nymGasPrice(nymCurrency);
|
||||
expect(getGasPrice.denom).toBe(`u${nymCurrency}`);
|
||||
});
|
||||
|
||||
test("provide invalid type returns an error message", () => {
|
||||
//pass invalid type
|
||||
expect(() => {
|
||||
const nymCurrency = 13;
|
||||
stargate.nymGasPrice(nymCurrency);
|
||||
}).toThrow("13 is not of type string");
|
||||
});
|
||||
|
||||
//provide test for downloading wasm
|
||||
//mock this test
|
||||
// test.skip("providing nothing returns", async () => {
|
||||
// //pass invalid type
|
||||
// const downloadWasm = stargate.downloadWasm("http://localhost");
|
||||
// console.log(downloadWasm);
|
||||
// })
|
||||
});
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import validator from "../../src/index";
|
||||
import { config } from '../test-utils/config';
|
||||
|
||||
const NETWORK_DENOM = config.CURRENCY_PREFIX as string;
|
||||
|
||||
describe("perform basic interactions with the validator", () => {
|
||||
test("build client and get all mixnodes", async () => {
|
||||
const mnemonic = validator.randomMnemonic();
|
||||
const mnemonicCount = mnemonic.split(" ").length;
|
||||
expect(mnemonicCount).toStrictEqual(24);
|
||||
});
|
||||
|
||||
test("build client and get all mixnodes", async () => {
|
||||
const buildMnemonic = validator.randomMnemonic();
|
||||
const mnemonic = await validator.mnemonicToAddress(buildMnemonic, NETWORK_DENOM);
|
||||
expect(mnemonic).toHaveLength(43);
|
||||
expect(mnemonic).toContain(NETWORK_DENOM);
|
||||
});
|
||||
});
|
||||
@@ -5,7 +5,11 @@
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"outDir": "./dist"
|
||||
"outDir": "./dist",
|
||||
"types": [
|
||||
"jest",
|
||||
"node",
|
||||
]
|
||||
},
|
||||
"typedocOptions": {
|
||||
"entryPoints": [
|
||||
@@ -16,7 +20,11 @@
|
||||
"exclude": [
|
||||
"dist",
|
||||
"examples",
|
||||
"tests",
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"tests",
|
||||
"./tests/*/*.tsx",
|
||||
"./tests/*/*.ts"
|
||||
]
|
||||
}
|
||||
+3643
-2960
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user