From a6774afd7b2298e0504b1cc7a2a8847b7a4276b1 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Thu, 27 Jul 2023 20:26:23 +0800 Subject: [PATCH 1/5] tests Signed-off-by: zqhxuyuan --- .github/workflows/integration_test_manta.yml | 7 + tests/package.json | 7 +- tests/tests/test-assets.ts | 47 +++++ tests/tests/test-balance.ts | 17 ++ tests/tests/util.ts | 183 +++++++++++++++++++ tests/yarn.lock | 29 +++ 6 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 tests/tests/test-assets.ts create mode 100644 tests/tests/test-balance.ts create mode 100644 tests/tests/util.ts diff --git a/.github/workflows/integration_test_manta.yml b/.github/workflows/integration_test_manta.yml index d71ec786c..c1538659d 100644 --- a/.github/workflows/integration_test_manta.yml +++ b/.github/workflows/integration_test_manta.yml @@ -414,6 +414,13 @@ jobs: with: name: ${{ matrix.chain-spec.id }}-alice-stress.log path: ${{ github.workspace }}/polkadot-launch/9921.log + - name: run tests + run: | + sleep 120 + cd ${{ github.workspace }}/Manta/tests + yarn install + yarn + yarn tests docker-image-test: timeout-minutes: 120 if: contains(github.event.pull_request.labels.*.name, 'A-manta' || github.ref == 'refs/heads/manta') diff --git a/tests/package.json b/tests/package.json index 584dd67d7..b4c3d3245 100644 --- a/tests/package.json +++ b/tests/package.json @@ -10,6 +10,7 @@ "runtime_upgrade_test": "mocha -r ts-node/register runtime_upgrade_test.ts", "parachain_lease_test": "mocha -r ts-node/register check_parachain_lease_expiration.ts", "test_farming": "mocha -r ts-node/register test-farming.ts", + "tests": "mocha -r ts-node/register --timeout 50000 tests/test-*.ts", "lint": "eslint ." }, "keywords": [], @@ -27,12 +28,16 @@ }, "devDependencies": { "@types/chai": "^4.3.1", + "@types/chai-as-promised": "^7.1.4", "@types/mocha": "^9.1.1", "@typescript-eslint/eslint-plugin": "^5.29.0", "@typescript-eslint/parser": "^5.29.0", "chai": "^4.3.6", + "chai-as-promised": "^7.1.1", "eslint": "^8.18.0", "eslint-config-prettier": "8.5.0", - "mocha": "^10.0.0" + "mocha": "^10.0.0", + "mocha-steps": "^1.3.0", + "get-port": "^5.1.1" } } diff --git a/tests/tests/test-assets.ts b/tests/tests/test-assets.ts new file mode 100644 index 000000000..78759823f --- /dev/null +++ b/tests/tests/test-assets.ts @@ -0,0 +1,47 @@ +import { expect } from "chai"; +import { step } from "mocha-steps"; +import {describeWithManta, executeTx, remark} from "./util"; +import '@polkadot/api-augment'; + +const location = { + V1: { + parents: 1, + interior: { + X3: [ + { + Parachain: 1000 + }, + { + PalletInstance: 50 + }, + { + GeneralIndex: 1984 + } + ] + } + } +}; + +const metadata = { + metadata: { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + isFrozen: false + }, + minBalance: 1, + isSufficient: true +}; + +describeWithManta("Manta RPC (Assets)", (context) => { + step("asset manager", async function () { + const parachainId = Number(await context.api.query.parachainInfo.parachainId()); + console.log(new Date() + " parachain:" + parachainId); + + let callData = await context.api.tx.assetManager.registerAsset(location, metadata); + await executeTx(context, callData, true); + + let state: any = await context.api.query.assetManager.assetIdMetadata(8); + console.log(new Date() + " Register Asset8:" + JSON.stringify(state)); + }); +}); \ No newline at end of file diff --git a/tests/tests/test-balance.ts b/tests/tests/test-balance.ts new file mode 100644 index 000000000..a91e93934 --- /dev/null +++ b/tests/tests/test-balance.ts @@ -0,0 +1,17 @@ +import { expect } from "chai"; +import { step } from "mocha-steps"; +import {describeWithManta, remark} from "./util"; +import '@polkadot/api-augment'; + +describeWithManta("Manta RPC (Balance)", (context) => { + step("genesis balance is setup correctly", async function () { + expect((await context.api.query.system.number()).toString()).to.equal("0"); + + const aliceBalance = (await context.api.query.system.account(context.alice.address)).data.free.toString(); + expect(aliceBalance.toString()).to.equal("1000000000000000000000000000"); + + await remark(context); + + expect((await context.api.query.system.number()).toString()).to.equal("1"); + }); +}); \ No newline at end of file diff --git a/tests/tests/util.ts b/tests/tests/util.ts new file mode 100644 index 000000000..3ca456c56 --- /dev/null +++ b/tests/tests/util.ts @@ -0,0 +1,183 @@ +import { spawn, ChildProcess } from "child_process"; +import chaiAsPromised from "chai-as-promised"; +import chai from "chai"; +import getPort from 'get-port'; +import {ApiPromise, WsProvider} from '@polkadot/api'; +import {Keyring} from "@polkadot/keyring"; +import {KeyringPair} from "@polkadot/keyring/types"; +import {cryptoWaitReady} from '@polkadot/util-crypto'; + +export interface TestContext { + api: ApiPromise; + alice: KeyringPair +} + +chai.use(chaiAsPromised); + +export const DISPLAY_LOG = process.env.MANTA_LOG || false; +export const MANTA_LOG = process.env.MANTA_LOG || "info"; +export const MANTA_BUILD = process.env.MANTA_BUILD || "release"; + +export const BINARY_PATH = `../target/${MANTA_BUILD}/manta`; +export const SPAWNING_TIME = 120000; + +export async function startMantaNode(): Promise<{ binary: ChildProcess; } & TestContext> { + const P2P_PORT = await getPort({ port: getPort.makeRange(19931, 22000) }); + const RPC_PORT = await getPort({ port: getPort.makeRange(19931, 22000) }); + const WS_PORT = await getPort({ port: getPort.makeRange(19931, 22000) }); + + console.log(`P2P: ${P2P_PORT}, RPC: ${RPC_PORT}, WS: ${WS_PORT}`); + + const cmd = BINARY_PATH; + const args = [ + `--chain=manta-localdev`, + `--alice`, + `-lruntime=debug`, + `--execution=native`, // Faster execution using native + `--no-telemetry`, + `--no-prometheus`, + `--port=${P2P_PORT}`, + `--rpc-port=${RPC_PORT}`, + `--rpc-external`, + `--ws-port=${WS_PORT}`, + `--ws-external`, + `--rpc-cors=all`, + `--rpc-methods=unsafe`, + `--pruning=archive`, + `--keep-blocks=archive`, + `--tmp`, + ]; + const binary = spawn(cmd, args); + + binary.on("error", (err) => { + if ((err as any).errno == "ENOENT") { + console.error( + `\x1b[31mMissing Acala binary (${BINARY_PATH}).\nPlease compile the Acala project:\nmake test-ts\x1b[0m` + ); + } else { + console.error(err); + } + process.exit(1); + }); + + const binaryLogs = [] as any; + const { api, alice } = await new Promise((resolve, reject) => { + const timer = setTimeout(() => { + console.error(`\x1b[31m Failed to start Acala Node.\x1b[0m`); + console.error(`Command: ${cmd} ${args.join(" ")}`); + console.error(`Logs:`); + console.error(binaryLogs.map((chunk: any) => chunk.toString()).join("\n")); + process.exit(1); + }, SPAWNING_TIME - 2000); + + const onData = async (chunk: any) => { + if (DISPLAY_LOG) { + console.log(chunk.toString()); + } + binaryLogs.push(chunk); + if (chunk.toString().match(/best: #0/)) { + try { + const { api, alice } = await getTestUtils(`ws://127.0.0.1:${WS_PORT}`); + + clearTimeout(timer); + if (!DISPLAY_LOG) { + binary.stderr.off("data", onData); + binary.stdout.off("data", onData); + } + resolve({ api, alice }); + } catch(e) { + binary.kill(); + reject(e); + } + } + }; + binary.stderr.on("data", onData); + binary.stdout.on("data", onData); + }); + + return { api, alice, binary }; +} + +export function describeWithManta(title: string, cb: (context: TestContext) => void) { + let context = {} as TestContext; + + describe(title, () => { + let binary: ChildProcess; + before("Starting Manta Test Node", async function () { + console.log('starting manta node ...') + this.timeout(SPAWNING_TIME); + + const init = await startMantaNode(); + + context.api = init.api; + context.alice = init.alice; + binary = init.binary; + + console.log('manta node started!') + }); + + after(async function () { + console.log(`\x1b[31m Killing RPC\x1b[0m`); + await context.api.disconnect(); + binary.kill(); + }); + + cb(context); + }); +} + +export const getTestUtils = async ( + url = 'ws://localhost:9944', +): Promise<{ + api: ApiPromise; + alice: KeyringPair +}> => { + const provider = new WsProvider(url); + const api = await ApiPromise.create({provider: provider}); + await cryptoWaitReady(); + await api.isReady; + + const alice = new Keyring({type: 'sr25519'}).addFromUri("//Alice"); + + return { + api, + alice + }; +}; + +export const remark = async(context: TestContext) => { + const alice = context.alice; + + const tx = await context.api.tx.system.remark("0x00"); + await tx.signAndSend(alice, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { + if (dispatchError) { + console.log(`extrinsic has error: ${dispatchError.toString()}, hex:${tx.toHex()}`); + } + }); + await new Promise(res => setTimeout(res, 200)) +} + +export const executeTx = async( + context: TestContext, + tx: any, + sudo: boolean = false +) => { + const alice = context.alice; + + if (sudo) { + const rootCall = context.api.tx.sudo.sudo(tx); + await rootCall.signAndSend(alice, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { + if (dispatchError) { + console.log(`root extrinsic has error: ${dispatchError.toString()}, hex:${tx.toHex()}`); + } + }); + } else { + // @ts-ignore + await tx.signAndSend(alice, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { + if (dispatchError) { + console.log(`extrinsic has error: ${dispatchError.toString()}, hex:${tx.toHex()}`); + } + }); + } + await new Promise(res => setTimeout(res, 200)) +} diff --git a/tests/yarn.lock b/tests/yarn.lock index f36a1782e..7d47b1e61 100644 --- a/tests/yarn.lock +++ b/tests/yarn.lock @@ -479,6 +479,18 @@ dependencies: "@types/node" "*" +"@types/chai-as-promised@^7.1.4": + version "7.1.5" + resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + dependencies: + "@types/chai" "*" + +"@types/chai@*": + version "4.3.5" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== + "@types/chai@^4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" @@ -750,6 +762,13 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + chai@^4.3.6: version "4.3.6" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" @@ -1215,6 +1234,11 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== +get-port@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1480,6 +1504,11 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +mocha-steps@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/mocha-steps/-/mocha-steps-1.3.0.tgz#2449231ec45ec56810f65502cb22e2571862957f" + integrity sha512-KZvpMJTqzLZw3mOb+EEuYi4YZS41C9iTnb7skVFRxHjUd1OYbl64tCMSmpdIRM9LnwIrSOaRfPtNpF5msgv6Eg== + mocha@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9" From 68e0c0dfdfa486f7c25bdb58408a8438618cbb01 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Thu, 27 Jul 2023 22:57:07 +0800 Subject: [PATCH 2/5] update binary env Signed-off-by: zqhxuyuan --- tests/tests/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/util.ts b/tests/tests/util.ts index 3ca456c56..1577ab7d5 100644 --- a/tests/tests/util.ts +++ b/tests/tests/util.ts @@ -18,7 +18,7 @@ export const DISPLAY_LOG = process.env.MANTA_LOG || false; export const MANTA_LOG = process.env.MANTA_LOG || "info"; export const MANTA_BUILD = process.env.MANTA_BUILD || "release"; -export const BINARY_PATH = `../target/${MANTA_BUILD}/manta`; +export const BINARY_PATH = process.env.MANTA_BINARY || `../target/${MANTA_BUILD}/manta`; export const SPAWNING_TIME = 120000; export async function startMantaNode(): Promise<{ binary: ChildProcess; } & TestContext> { From 8065c3fcee9945ae7820445724973ada7881f226 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Thu, 27 Jul 2023 23:17:27 +0800 Subject: [PATCH 3/5] update binary env workflow Signed-off-by: zqhxuyuan --- .github/workflows/integration_test_manta.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration_test_manta.yml b/.github/workflows/integration_test_manta.yml index c1538659d..bd6644218 100644 --- a/.github/workflows/integration_test_manta.yml +++ b/.github/workflows/integration_test_manta.yml @@ -420,7 +420,7 @@ jobs: cd ${{ github.workspace }}/Manta/tests yarn install yarn - yarn tests + MANTA_BINARY=$HOME/.local/bin/manta yarn tests docker-image-test: timeout-minutes: 120 if: contains(github.event.pull_request.labels.*.name, 'A-manta' || github.ref == 'refs/heads/manta') From 7109a91effc27a4c726670b11743fcd3e6907a85 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Fri, 28 Jul 2023 17:37:48 +0800 Subject: [PATCH 4/5] add dex test Signed-off-by: zqhxuyuan --- tests/constants.ts | 82 +++++++++++++++++++++++++++++++++ tests/test-farming.ts | 92 +++++--------------------------------- tests/tests/test-assets.ts | 35 ++------------- tests/tests/test-dex.ts | 77 +++++++++++++++++++++++++++++++ tests/tests/util.ts | 33 +++++++++----- 5 files changed, 196 insertions(+), 123 deletions(-) create mode 100644 tests/constants.ts create mode 100644 tests/tests/test-dex.ts diff --git a/tests/constants.ts b/tests/constants.ts new file mode 100644 index 000000000..0422dd002 --- /dev/null +++ b/tests/constants.ts @@ -0,0 +1,82 @@ + +export const USDT_LOCATION = { + V1: { + parents: 1, + interior: { + X3: [ + { + Parachain: 1000 + }, + { + PalletInstance: 50 + }, + { + GeneralIndex: 1984 + } + ] + } + } +}; + +export const USDT_METADATA = { + metadata: { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + isFrozen: false + }, + minBalance: 1, + isSufficient: true +}; + +export const USDC_LOCATION = { + V1: { + parents: 1, + interior: { + X3: [ + { + Parachain: 1000 + }, + { + PalletInstance: 50 + }, + { + GeneralIndex: 1985 + } + ] + } + } +}; + +export const USDC_METADATA = { + metadata: { + name: "USDC", + symbol: "USDC", + decimals: 10, + isFrozen: false + }, + minBalance: 1, + isSufficient: true +}; + +export const MANDEX_METADATA = { + metadata: { + name: "MANDEX", + symbol: "MANDEX", + decimals: 18, + isFrozen: false + }, + minBalance: 1, + isSufficient: true +}; + +export const LP_USDT_USDC_METADATA = { + metadata: { + name: "LP-USDC-USDT", + symbol: "LP", + decimals: 12, + isFrozen: false + }, + minBalance: 1, + isSufficient: true +}; \ No newline at end of file diff --git a/tests/test-farming.ts b/tests/test-farming.ts index badea83cb..57fbcecc7 100644 --- a/tests/test-farming.ts +++ b/tests/test-farming.ts @@ -5,87 +5,19 @@ import { farming_rpc_api, farming_types } from './types'; import { expect } from 'chai'; import minimist, { ParsedArgs } from 'minimist'; import {execute_transaction, execute_via_governance,timer } from "./chain-util"; +import { + LP_USDT_USDC_METADATA, + MANDEX_METADATA, + USDC_LOCATION, + USDC_METADATA, + USDT_LOCATION, + USDT_METADATA +} from "./constants"; const test_config = { ws_address: "ws://127.0.0.1:9800", timeout: 2000000 } -const location = { - V1: { - parents: 1, - interior: { - X3: [ - { - Parachain: 1000 - }, - { - PalletInstance: 50 - }, - { - GeneralIndex: 1984 - } - ] - } - } -}; -const location2 = { - V1: { - parents: 1, - interior: { - X3: [ - { - Parachain: 1000 - }, - { - PalletInstance: 50 - }, - { - GeneralIndex: 1985 - } - ] - } - } -}; -const metadata = { - metadata: { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - isFrozen: false - }, - minBalance: 1, - isSufficient: true -}; -const metadata2 = { - metadata: { - name: "USDC", - symbol: "USDC", - decimals: 10, - isFrozen: false - }, - minBalance: 1, - isSufficient: true -}; -const metadata3 = { - metadata: { - name: "MANDEX", - symbol: "MANDEX", - decimals: 18, - isFrozen: false - }, - minBalance: 1, - isSufficient: true -}; -const lp_metadata = { - metadata: { - name: "LP-USDC-USDT", - symbol: "LP", - decimals: 12, - isFrozen: false - }, - minBalance: 1, - isSufficient: true -}; function local_asset(parachainId: number, generalKey: string) { let location = { @@ -129,7 +61,7 @@ describe('Node RPC Test', () => { console.log(new Date() + " parachain:" + parachainId); // register asset 8(decimal:6) - let callData = api.tx.assetManager.registerAsset(location, metadata); + let callData = api.tx.assetManager.registerAsset(USDT_LOCATION, USDT_METADATA); await execute_via_governance(api, alice, callData); let state: any = await api.query.assetManager.assetIdMetadata(8); @@ -140,7 +72,7 @@ describe('Node RPC Test', () => { console.log(new Date() + " Register Asset8:" + JSON.stringify(state)); // 9(decimal:10) - callData = api.tx.assetManager.registerAsset(location2, metadata2); + callData = api.tx.assetManager.registerAsset(USDC_LOCATION, USDC_METADATA); await execute_via_governance(api, alice, callData); state = await api.query.assetManager.assetIdMetadata(9); while(state.isNone) { @@ -150,7 +82,7 @@ describe('Node RPC Test', () => { console.log(new Date() + " Register Asset9:" + JSON.stringify(state)); // 10(decimal:18) - callData = api.tx.assetManager.registerAsset(local_asset(parachainId, "MANDEX"), metadata3); + callData = api.tx.assetManager.registerAsset(local_asset(parachainId, "MANDEX"), MANDEX_METADATA); await execute_via_governance(api, alice, callData); let mandexId = 10; state = await api.query.assetManager.assetIdMetadata(mandexId); @@ -161,7 +93,7 @@ describe('Node RPC Test', () => { console.log(new Date() + " Register Asset10:" + JSON.stringify(state)); // register lp asset 11(decimal:12) - callData = api.tx.assetManager.registerLpAsset(8, 9, lp_metadata); + callData = api.tx.assetManager.registerLpAsset(8, 9, LP_USDT_USDC_METADATA); await execute_via_governance(api, alice, callData); let lpAssetId = 11; state = await api.query.assetManager.assetIdMetadata(lpAssetId); diff --git a/tests/tests/test-assets.ts b/tests/tests/test-assets.ts index 78759823f..1b84fee0b 100644 --- a/tests/tests/test-assets.ts +++ b/tests/tests/test-assets.ts @@ -2,43 +2,14 @@ import { expect } from "chai"; import { step } from "mocha-steps"; import {describeWithManta, executeTx, remark} from "./util"; import '@polkadot/api-augment'; - -const location = { - V1: { - parents: 1, - interior: { - X3: [ - { - Parachain: 1000 - }, - { - PalletInstance: 50 - }, - { - GeneralIndex: 1984 - } - ] - } - } -}; - -const metadata = { - metadata: { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - isFrozen: false - }, - minBalance: 1, - isSufficient: true -}; +import {USDT_LOCATION, USDT_METADATA} from "../constants"; describeWithManta("Manta RPC (Assets)", (context) => { - step("asset manager", async function () { + step("asset manager register asset should work", async function () { const parachainId = Number(await context.api.query.parachainInfo.parachainId()); console.log(new Date() + " parachain:" + parachainId); - let callData = await context.api.tx.assetManager.registerAsset(location, metadata); + let callData = await context.api.tx.assetManager.registerAsset(USDT_LOCATION, USDT_METADATA); await executeTx(context, callData, true); let state: any = await context.api.query.assetManager.assetIdMetadata(8); diff --git a/tests/tests/test-dex.ts b/tests/tests/test-dex.ts new file mode 100644 index 000000000..fc4c38150 --- /dev/null +++ b/tests/tests/test-dex.ts @@ -0,0 +1,77 @@ +import { expect } from "chai"; +import { step } from "mocha-steps"; +import {describeWithManta, executeTx, remark} from "./util"; +import '@polkadot/api-augment'; +import {LP_USDT_USDC_METADATA, USDC_LOCATION, USDC_METADATA, USDT_LOCATION, USDT_METADATA} from "../constants"; +import {BN} from "@polkadot/util"; + +describeWithManta("Manta RPC (Dex)", (context) => { + step("dex add liquidity should work", async function () { + const api = context.api; + const alice = context.alice.address; + const bob = context.bob.address; + + const parachainId = Number(await api.query.parachainInfo.parachainId()); + console.log(new Date() + " parachain:" + parachainId); + + let callData = await api.tx.assetManager.registerAsset(USDT_LOCATION, USDT_METADATA); + await executeTx(context, callData, true); + + callData = await api.tx.assetManager.registerAsset(USDC_LOCATION, USDC_METADATA); + await executeTx(context, callData, true); + + callData = api.tx.assetManager.registerLpAsset(8, 9, LP_USDT_USDC_METADATA); + await executeTx(context, callData, true); + + callData = api.tx.zenlinkProtocol.createPair([parachainId,2,8], [parachainId,2,9]); + await executeTx(context, callData, true); + + callData = api.tx.balances.transfer(bob, new BN("1000000000000000000000")); + await executeTx(context, callData); + + callData = api.tx.assetManager.mintAsset(8, alice, new BN("20000000000000")); + await executeTx(context, callData, true); + callData = api.tx.assetManager.mintAsset(8, bob, new BN("20000000000000")); + await executeTx(context, callData, true); + + callData = api.tx.assetManager.mintAsset(9, alice, new BN("200000000000000000")); + await executeTx(context, callData, true); + callData = api.tx.assetManager.mintAsset(9, bob, new BN("200000000000000000")); + await executeTx(context, callData, true); + + callData = api.tx.zenlinkProtocol.addLiquidity([parachainId,2,8], [parachainId,2,9], + new BN("10000000000000"), new BN("100000000000000000"), + new BN("10000000000000"), new BN("100000000000000000"), 1000); + await executeTx(context, callData); + + let state = await api.query.zenlinkProtocol.pairStatuses([[parachainId,2,8], [parachainId,2,9]]); + expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal("1000000000000000"); + + callData = api.tx.zenlinkProtocol.addLiquidity([parachainId,2,8], [parachainId,2,9], + new BN("10000000000000"), new BN("100000000000000000"), + new BN("10000000000000"), new BN("100000000000000000"), 1000); + await executeTx(context, callData, false, false); + + state = await api.query.zenlinkProtocol.pairStatuses([[parachainId,2,8], [parachainId,2,9]]); + expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal("2000000000000000"); + + state = await api.query.assets.account(10, alice); + expect(JSON.parse(JSON.stringify(state)).balance.toString()).to.equal("1000000000000000"); + + state = await api.query.assets.account(10, bob); + expect(JSON.parse(JSON.stringify(state)).balance.toString()).to.equal("1000000000000000"); + + callData = api.tx.zenlinkProtocol.removeLiquidity([parachainId,2,8], [parachainId,2,9], + new BN("1000000000000000"), + new BN("10000000000000"), new BN("100000000000000000"), + alice, + 1000); + await executeTx(context, callData); + + state = await api.query.zenlinkProtocol.pairStatuses([[parachainId,2,8], [parachainId,2,9]]); + expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal("1000000000000000"); + + state = await api.query.assets.account(10, alice); + expect(JSON.parse(JSON.stringify(state))).to.equal(null); + }); +}); \ No newline at end of file diff --git a/tests/tests/util.ts b/tests/tests/util.ts index 1577ab7d5..c39265037 100644 --- a/tests/tests/util.ts +++ b/tests/tests/util.ts @@ -9,7 +9,8 @@ import {cryptoWaitReady} from '@polkadot/util-crypto'; export interface TestContext { api: ApiPromise; - alice: KeyringPair + alice: KeyringPair; + bob: KeyringPair; } chai.use(chaiAsPromised); @@ -61,7 +62,7 @@ export async function startMantaNode(): Promise<{ binary: ChildProcess; } & Test }); const binaryLogs = [] as any; - const { api, alice } = await new Promise((resolve, reject) => { + const { api, alice, bob } = await new Promise((resolve, reject) => { const timer = setTimeout(() => { console.error(`\x1b[31m Failed to start Acala Node.\x1b[0m`); console.error(`Command: ${cmd} ${args.join(" ")}`); @@ -77,14 +78,14 @@ export async function startMantaNode(): Promise<{ binary: ChildProcess; } & Test binaryLogs.push(chunk); if (chunk.toString().match(/best: #0/)) { try { - const { api, alice } = await getTestUtils(`ws://127.0.0.1:${WS_PORT}`); + const { api, alice, bob } = await getTestUtils(`ws://127.0.0.1:${WS_PORT}`); clearTimeout(timer); if (!DISPLAY_LOG) { binary.stderr.off("data", onData); binary.stdout.off("data", onData); } - resolve({ api, alice }); + resolve({ api, alice, bob }); } catch(e) { binary.kill(); reject(e); @@ -95,7 +96,7 @@ export async function startMantaNode(): Promise<{ binary: ChildProcess; } & Test binary.stdout.on("data", onData); }); - return { api, alice, binary }; + return { api, alice, bob, binary }; } export function describeWithManta(title: string, cb: (context: TestContext) => void) { @@ -111,6 +112,7 @@ export function describeWithManta(title: string, cb: (context: TestContext) => v context.api = init.api; context.alice = init.alice; + context.bob = init.bob; binary = init.binary; console.log('manta node started!') @@ -130,7 +132,8 @@ export const getTestUtils = async ( url = 'ws://localhost:9944', ): Promise<{ api: ApiPromise; - alice: KeyringPair + alice: KeyringPair; + bob: KeyringPair; }> => { const provider = new WsProvider(url); const api = await ApiPromise.create({provider: provider}); @@ -138,10 +141,12 @@ export const getTestUtils = async ( await api.isReady; const alice = new Keyring({type: 'sr25519'}).addFromUri("//Alice"); + const bob = new Keyring({type: 'sr25519'}).addFromUri("//Bob"); return { api, - alice + alice, + bob }; }; @@ -160,20 +165,26 @@ export const remark = async(context: TestContext) => { export const executeTx = async( context: TestContext, tx: any, - sudo: boolean = false + sudo: boolean = false, + useAlice: boolean = true ) => { - const alice = context.alice; + let account; + if(useAlice) { + account = context.alice; + } else { + account = context.bob; + } if (sudo) { const rootCall = context.api.tx.sudo.sudo(tx); - await rootCall.signAndSend(alice, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { + await rootCall.signAndSend(context.alice, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { if (dispatchError) { console.log(`root extrinsic has error: ${dispatchError.toString()}, hex:${tx.toHex()}`); } }); } else { // @ts-ignore - await tx.signAndSend(alice, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { + await tx.signAndSend(account, {nonce: -1}, async ({ events = [], status, txHash, dispatchError }) => { if (dispatchError) { console.log(`extrinsic has error: ${dispatchError.toString()}, hex:${tx.toHex()}`); } From 860947b0748e9f504be49ae1cc4802d714cf5ade Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Thu, 3 Aug 2023 12:57:32 +0800 Subject: [PATCH 5/5] use constant Signed-off-by: zqhxuyuan --- tests/constants.ts | 10 +++++++++ tests/tests/test-balance.ts | 3 ++- tests/tests/test-dex.ts | 42 ++++++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/tests/constants.ts b/tests/constants.ts index 0422dd002..67ad95a23 100644 --- a/tests/constants.ts +++ b/tests/constants.ts @@ -1,3 +1,13 @@ +import {BN} from "@polkadot/util"; + +export const MANTA_1B = "1000000000000000000000000000"; +export const MANTA_1K = new BN("1000000000000000000000"); +export const LP_1K = "1000000000000000"; +export const LP_2K = "2000000000000000"; +export const USDT_10M = new BN("10000000000000"); +export const USDT_20M = new BN("20000000000000"); +export const USDC_10M = new BN("100000000000000000"); +export const USDC_20M = new BN("200000000000000000"); export const USDT_LOCATION = { V1: { diff --git a/tests/tests/test-balance.ts b/tests/tests/test-balance.ts index a91e93934..8fa2bc1c2 100644 --- a/tests/tests/test-balance.ts +++ b/tests/tests/test-balance.ts @@ -2,13 +2,14 @@ import { expect } from "chai"; import { step } from "mocha-steps"; import {describeWithManta, remark} from "./util"; import '@polkadot/api-augment'; +import {MANTA_1B} from "../constants"; describeWithManta("Manta RPC (Balance)", (context) => { step("genesis balance is setup correctly", async function () { expect((await context.api.query.system.number()).toString()).to.equal("0"); const aliceBalance = (await context.api.query.system.account(context.alice.address)).data.free.toString(); - expect(aliceBalance.toString()).to.equal("1000000000000000000000000000"); + expect(aliceBalance.toString()).to.equal(MANTA_1B); await remark(context); diff --git a/tests/tests/test-dex.ts b/tests/tests/test-dex.ts index fc4c38150..0cdacdca3 100644 --- a/tests/tests/test-dex.ts +++ b/tests/tests/test-dex.ts @@ -2,7 +2,15 @@ import { expect } from "chai"; import { step } from "mocha-steps"; import {describeWithManta, executeTx, remark} from "./util"; import '@polkadot/api-augment'; -import {LP_USDT_USDC_METADATA, USDC_LOCATION, USDC_METADATA, USDT_LOCATION, USDT_METADATA} from "../constants"; +import { + LP_1K, LP_2K, + LP_USDT_USDC_METADATA, MANTA_1K, USDC_10M, USDC_20M, + USDC_LOCATION, + USDC_METADATA, + USDT_10M, USDT_20M, + USDT_LOCATION, + USDT_METADATA +} from "../constants"; import {BN} from "@polkadot/util"; describeWithManta("Manta RPC (Dex)", (context) => { @@ -26,50 +34,50 @@ describeWithManta("Manta RPC (Dex)", (context) => { callData = api.tx.zenlinkProtocol.createPair([parachainId,2,8], [parachainId,2,9]); await executeTx(context, callData, true); - callData = api.tx.balances.transfer(bob, new BN("1000000000000000000000")); + callData = api.tx.balances.transfer(bob, MANTA_1K); await executeTx(context, callData); - callData = api.tx.assetManager.mintAsset(8, alice, new BN("20000000000000")); + callData = api.tx.assetManager.mintAsset(8, alice, USDT_20M); await executeTx(context, callData, true); - callData = api.tx.assetManager.mintAsset(8, bob, new BN("20000000000000")); + callData = api.tx.assetManager.mintAsset(8, bob, USDT_20M); await executeTx(context, callData, true); - callData = api.tx.assetManager.mintAsset(9, alice, new BN("200000000000000000")); + callData = api.tx.assetManager.mintAsset(9, alice, USDC_20M); await executeTx(context, callData, true); - callData = api.tx.assetManager.mintAsset(9, bob, new BN("200000000000000000")); + callData = api.tx.assetManager.mintAsset(9, bob, USDC_20M); await executeTx(context, callData, true); + // Alice add liquidity callData = api.tx.zenlinkProtocol.addLiquidity([parachainId,2,8], [parachainId,2,9], - new BN("10000000000000"), new BN("100000000000000000"), - new BN("10000000000000"), new BN("100000000000000000"), 1000); + USDT_10M, USDC_10M, USDT_10M, USDC_10M, 1000); await executeTx(context, callData); let state = await api.query.zenlinkProtocol.pairStatuses([[parachainId,2,8], [parachainId,2,9]]); - expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal("1000000000000000"); + expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal(LP_1K); + // Bob add liquidity callData = api.tx.zenlinkProtocol.addLiquidity([parachainId,2,8], [parachainId,2,9], - new BN("10000000000000"), new BN("100000000000000000"), - new BN("10000000000000"), new BN("100000000000000000"), 1000); + USDT_10M, USDC_10M, USDT_10M, USDC_10M, 1000); await executeTx(context, callData, false, false); state = await api.query.zenlinkProtocol.pairStatuses([[parachainId,2,8], [parachainId,2,9]]); - expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal("2000000000000000"); + expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal(LP_2K); state = await api.query.assets.account(10, alice); - expect(JSON.parse(JSON.stringify(state)).balance.toString()).to.equal("1000000000000000"); + expect(JSON.parse(JSON.stringify(state)).balance.toString()).to.equal(LP_1K); state = await api.query.assets.account(10, bob); - expect(JSON.parse(JSON.stringify(state)).balance.toString()).to.equal("1000000000000000"); + expect(JSON.parse(JSON.stringify(state)).balance.toString()).to.equal(LP_1K); callData = api.tx.zenlinkProtocol.removeLiquidity([parachainId,2,8], [parachainId,2,9], - new BN("1000000000000000"), - new BN("10000000000000"), new BN("100000000000000000"), + new BN(LP_1K), + USDT_10M, USDC_10M, alice, 1000); await executeTx(context, callData); state = await api.query.zenlinkProtocol.pairStatuses([[parachainId,2,8], [parachainId,2,9]]); - expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal("1000000000000000"); + expect(JSON.parse(JSON.stringify(state)).trading.totalSupply.toString()).to.equal(LP_1K); state = await api.query.assets.account(10, alice); expect(JSON.parse(JSON.stringify(state))).to.equal(null);