From 6730c621caef4685e7d907e25effa56f6ebc3dad Mon Sep 17 00:00:00 2001 From: bee344 Date: Fri, 12 Jan 2024 17:09:41 -0300 Subject: [PATCH] housekeeping and README --- README.md | 4 + e2e-tests/README.md | 36 +++++++++ e2e-tests/balance.ts | 12 ++- e2e-tests/consts.ts | 7 +- e2e-tests/executor.ts | 36 +++------ e2e-tests/logger.ts | 36 +++++++++ e2e-tests/tests/assets.ts | 32 ++++++-- e2e-tests/tests/foreignAssets.ts | 56 ++++++++++++-- e2e-tests/tests/index.ts | 105 +++++++++++++++----------- e2e-tests/tests/liquidPools.ts | 24 ++++-- e2e-tests/tests/local.ts | 111 ++++++++++++++++++++++++++-- e2e-tests/verification.ts | 8 ++ scripts/consts.ts | 2 +- scripts/testNetworkForeignAssets.ts | 54 +++++++------- scripts/testNetworkLiquidAssets.ts | 4 - zombienet/medium-network.toml | 18 ----- 16 files changed, 391 insertions(+), 154 deletions(-) create mode 100644 e2e-tests/README.md diff --git a/README.md b/README.md index 969b26e6..a05a0f95 100644 --- a/README.md +++ b/README.md @@ -323,3 +323,7 @@ From the root directory run `./ -p native spawn ./zombien ### Create an asset From the root directory run `yarn start:zombienet-post-script`. You can run this right after running your zombienet network. + +## E2E Testing + +You can access the E2E tests and its documentation [here](./e2e-tests/). diff --git a/e2e-tests/README.md b/e2e-tests/README.md new file mode 100644 index 00000000..55abafc5 --- /dev/null +++ b/e2e-tests/README.md @@ -0,0 +1,36 @@ +## E2E Tests + +End-to-end tests that run on a zombienet testnet. + +**NOTE: tested using polkadot v1.4.0** + +### Setup + +To setup the testing environment you need to first download the `polkadot`, `polkadot-execute-worker`, `polkadot-prepare-worker` and `polkadot-parachain` from the `polkadot-sdk` [release page](https://github.com/paritytech/polkadot-sdk/releases/latest), as well as the `trappist-node` from its [release page](https://github.com/paritytech/trappist/releases/latest), and place them in the `../zombienet/bin/` folder. + +You also need to have the latest `zombienet` executable in the `../zombienet/` folder, which you can download from [here](https://github.com/paritytech/zombienet/releases/latest). + +### Launching zombienet + +To launch the zombienet, all you need to do is run the following commands: +```bash +$ yarn build && yarn e2e:build +``` +Then you need to run: +```bash +$ yarn e2e:zombienet +``` +And this will launch the zombienet using the config file located in the `../zombienet/` directory. Once it finished its setup, you can proceed to the following step. + +### Launching the tests + +For testing, we provide 4 options: + +* Testing liquidity tokens transfers with the command `yarn e2e:liquidity-assets`. +* Testing foreign assets transfers with the command `yarn e2e:foreign-assets`. +* Testing local transferss with the command `yarn e2e:local`. +* Testing assets transfers with the command `yarn e2e:assets`. + +Each of these commands will run the appropiate script to setup the basics, located in `../scripts/`, wait for it to finish setting up the testing environment, and then go through the tests indicated in the `./tests/index.ts` file for the chosen option. + +After each testing suite has been completed, it's recommended to restart the zombienet before running another test suite. diff --git a/e2e-tests/balance.ts b/e2e-tests/balance.ts index d27694fc..cd387f47 100644 --- a/e2e-tests/balance.ts +++ b/e2e-tests/balance.ts @@ -8,6 +8,16 @@ export interface IBalance { final: [string, number][]; } +/** + * + * @param api api instance + * @param test name of the test currently being ran + * @param address address of the account whose balance is being queried + * @param assetIds Ids of the assets being queried + * @param balance initial balance for the account queried + * @returns instance of IBalance containing the initial and optionally the final + * balance of the account queried + */ export const balanceTracker = async ( api: ApiPromise, test: string, @@ -72,7 +82,7 @@ export const balanceTracker = async ( if (!balance) { for (const assetId of assetIds) { accountInfo = await api.query.assets.account(assetId, address); - if (accountInfo === null) { + if (accountInfo.isNone) { balances.initial.push([assetId, 0]); } else { balances.initial.push([assetId, accountInfo.unwrap().balance.toBn().toNumber()]); diff --git a/e2e-tests/consts.ts b/e2e-tests/consts.ts index a5b0e510..615f1672 100644 --- a/e2e-tests/consts.ts +++ b/e2e-tests/consts.ts @@ -3,13 +3,8 @@ export const KUSAMA_ASSET_HUB_WS_URL = 'ws://127.0.0.1:9911'; export const ROCOCO_ALICE_WS_URL = 'ws://127.0.0.1:9900'; export const TRAPPIST_WS_URL = 'ws://127.0.0.1:9921'; -export const MOONRIVER_WS_URL = 'ws://127.0.0.1:9931'; export const BOB_ADDR = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty'; export const FERDE_ADDR = '5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL'; -export const ASSET_ID = 1; - -export const MOONRIVER_ADDR = '5Eg2fnt8QeGtg4mcc5ELxPx6qxP2FSEWHbbYXENZ17ormkGP'; -export const TRAPPIST_ADDR = '5Eg2fntDDP4P8TjqRg3Jq89y5boE26JUMM3D7VU3bCAp76nc'; -export const ASSET_HUB_ADDR = '5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV'; +export const EXTRINSIC_VERSION = 4; diff --git a/e2e-tests/executor.ts b/e2e-tests/executor.ts index 32039338..cb3a536f 100644 --- a/e2e-tests/executor.ts +++ b/e2e-tests/executor.ts @@ -7,7 +7,7 @@ import { cryptoWaitReady } from '@polkadot/util-crypto'; import { delay } from '../scripts/util'; import { constructApiPromise } from '../src'; import { balanceTracker, IBalance } from './balance'; -import { KUSAMA_ASSET_HUB_WS_URL, MOONRIVER_WS_URL, ROCOCO_ALICE_WS_URL, TRAPPIST_WS_URL } from './consts'; +import { KUSAMA_ASSET_HUB_WS_URL, ROCOCO_ALICE_WS_URL, TRAPPIST_WS_URL } from './consts'; import { startProgressBar, startTestLogger, terminateProgressBar, testResultLogger, updateProgressBar } from './logger'; import { assetTests, foreignAssetsTests, IndividualTest, liquidPoolsTests, localTests, tests } from './tests'; import { verification } from './verification'; @@ -54,13 +54,6 @@ const executor = async (testCase: string) => { break; } - let originChainId = ''; - let destChainId = ''; - let originAddr = ''; - let destAddr = ''; - let assetIds: string[] = []; - let amounts: string[] = []; - let opts: object = {}; let counter: number = 0; startTestLogger(testCase); @@ -70,13 +63,13 @@ const executor = async (testCase: string) => { const results: [string, string, string, boolean][] = []; for (const t of testData) { - originChainId = t.args[0]; - destChainId = t.args[1]; - originAddr = t.args[2]; - destAddr = t.args[3]; - assetIds = t.args[4].slice(1, -1).split(','); - amounts = t.args[5].slice(1, -1).split(','); - opts = JSON.parse(t.args[6], (key: string, value: string) => { + const originChainId: string = t.args[0]; + const destChainId: string = t.args[1]; + const originAddr: string = t.args[2]; + const destAddr: string = t.args[3]; + const assetIds: string[] = t.args[4].slice(1, -1).split(','); + const amounts: string[] = t.args[5].slice(1, -1).split(','); + const opts: object = JSON.parse(t.args[6], (key: string, value: string) => { return key === 'paysWithFeeOrigin' ? JSON.stringify(value) : value; }) as object; let chainName: string = ''; @@ -94,10 +87,6 @@ const executor = async (testCase: string) => { originWsUrl = TRAPPIST_WS_URL; chainName = 'Trappist'; break; - case '4000': - originWsUrl = MOONRIVER_WS_URL; - chainName = 'Moonriver'; - break; } if (originChainId == destChainId) { destWsUrl = originWsUrl; @@ -115,10 +104,6 @@ const executor = async (testCase: string) => { destWsUrl = TRAPPIST_WS_URL; chainName = 'Trappist'; break; - case '4000': - destWsUrl = MOONRIVER_WS_URL; - chainName = 'Moonriver'; - break; } } @@ -152,9 +137,10 @@ const executor = async (testCase: string) => { destInitialBalance, ); - const correctlyReceived = verification(assetIds, amounts, destFinalBalance); + const verificationAssetIds: string[] = t.verification[0].slice(1, -1).split(','); + const verificationAmounts: string[] = t.verification[1].slice(1, -1).split(','); - await delay(12000); + const correctlyReceived = verification(verificationAssetIds, verificationAmounts, destFinalBalance); await originApi.disconnect(); await destinationApi.disconnect(); diff --git a/e2e-tests/logger.ts b/e2e-tests/logger.ts index 4de70a6d..4076d53d 100644 --- a/e2e-tests/logger.ts +++ b/e2e-tests/logger.ts @@ -4,6 +4,11 @@ import chalk from 'chalk'; import * as cliProgress from 'cli-progress'; import { IndividualTest } from 'tests'; +/** + * + * @param testCase a string containing the test option selected + * @returns a prettified version of the testCase + */ const defineTest = (testCase: string): string => { let test: string = ''; @@ -24,12 +29,26 @@ const defineTest = (testCase: string): string => { return test; }; +/** + * Calls defineTest and prints a message signaling the begining of the tests + * @param testCase a string containing the test option selected + */ export const startTestLogger = (testCase: string) => { const test = defineTest(testCase); console.log(chalk.yellow(`Initializing tests for ${test}\n`)); }; +/** + * This creates and starts an instance of cliProgress containing a SingleBar to + * display the test suite's progress + * + * @param testData an array containing the individual tests for the test suite + * selected + * @param testCase the test suite selected + * @returns an instance of the cliProgress that will be used to track the progress + * of the tests + */ export const startProgressBar = (testData: IndividualTest[], testCase: string): cliProgress.SingleBar => { const test = defineTest(testCase); @@ -48,6 +67,11 @@ export const startProgressBar = (testData: IndividualTest[], testCase: string): return progressBar; }; +/** + * Clears the progress bar in place and prints an updated version + * @param counter current test number + * @param progressBar instance of the cliProgress + */ export const updateProgressBar = (counter: number, progressBar: cliProgress.SingleBar) => { process.stdout.moveCursor(0, -2); @@ -56,6 +80,11 @@ export const updateProgressBar = (counter: number, progressBar: cliProgress.Sing progressBar.increment(counter); }; +/** + * Terminates the cliProgess instance. It's called after the test suite is over + * @param progressBar instance of cliProgress to be terminated + * @param testCase + */ export const terminateProgressBar = (progressBar: cliProgress.SingleBar, testCase: string) => { const test = defineTest(testCase); console.log(chalk.yellow(`Test Suite for ${test} completed.\n`)); @@ -64,6 +93,13 @@ export const terminateProgressBar = (progressBar: cliProgress.SingleBar, testCas console.log('\n'); }; +/** + * + * @param testName current test's name + * @param assetId Id of the asset tested against + * @param chainName Name of the chain against the test ran + * @param passed whether the test passed or failed + */ export const testResultLogger = (testName: string, assetId: string, chainName: string, passed: boolean) => { const tokenId = assetId === '' ? 'native asset' : `asset ${assetId}`; if (passed) { diff --git a/e2e-tests/tests/assets.ts b/e2e-tests/tests/assets.ts index 998f73f9..7a2f3b6d 100644 --- a/e2e-tests/tests/assets.ts +++ b/e2e-tests/tests/assets.ts @@ -1,6 +1,7 @@ // Copyright 2023 Parity Technologies (UK) Ltd. import { ApiPromise } from '@polkadot/api'; import { KeyringPair } from '@polkadot/keyring/types'; +import { EXTRINSIC_VERSION } from 'consts'; import { AssetTransferApi } from '../../src'; import { TxResult } from '../../src/types'; @@ -9,10 +10,10 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe const injectedRegistry = { rococo: { '1836': { - tokens: ['ROC'], + tokens: ['HOP'], assetsInfo: {}, foreignAssetsInfo: {}, - specName: 'asset-hub-rococo', + specName: 'trappist-rococo', poolPairsInfo: {}, }, }, @@ -36,10 +37,17 @@ const createLocalSystemAssetsTransferTransaction = async ( ) => { const assetApi = createAssetApi(api, specName, safeXcmVersion); - let localTransfer: TxResult<'submittable'>; + let localTransferInfo: TxResult<'payload'>; try { - localTransfer = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); - await localTransfer.tx.signAndSend(origin); + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); } catch (e) { console.error(e); throw Error(e as string); @@ -59,15 +67,23 @@ const createPayFeesTransaction = async ( ) => { const assetApi = createAssetApi(api, specName, safeXcmVersion); - let localTransfer: TxResult<'submittable'>; + let localTransferInfo: TxResult<'payload'>; try { - localTransfer = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); - await localTransfer.tx.signAndSend(origin); + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); } catch (e) { console.error(e); throw Error(e as string); } }; + export const assetTests: { [K: string]: Function } = { createLocalSystemAssetsTransferTransaction, createPayFeesTransaction, diff --git a/e2e-tests/tests/foreignAssets.ts b/e2e-tests/tests/foreignAssets.ts index 849bf089..0efdc03e 100644 --- a/e2e-tests/tests/foreignAssets.ts +++ b/e2e-tests/tests/foreignAssets.ts @@ -1,6 +1,7 @@ // Copyright 2023 Parity Technologies (UK) Ltd. import { ApiPromise } from '@polkadot/api'; import { KeyringPair } from '@polkadot/keyring/types'; +import { EXTRINSIC_VERSION } from 'consts'; import { AssetTransferApi } from '../../src'; import { TxResult } from '../../src/types'; @@ -9,10 +10,10 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe const injectedRegistry = { rococo: { '1836': { - tokens: ['ROC'], + tokens: ['HOP'], assetsInfo: {}, foreignAssetsInfo: {}, - specName: 'asset-hub-rococo', + specName: 'trappist-rococo', poolPairsInfo: {}, }, }, @@ -23,7 +24,7 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe return assetApi; }; -const createTransferTransaction = async ( +const createForeignTransferTransaction = async ( origin: KeyringPair, destChainId: string, destAddr: string, @@ -36,13 +37,54 @@ const createTransferTransaction = async ( ) => { const assetApi = createAssetApi(api, specName, safeXcmVersion); - let localTransfer: TxResult<'submittable'>; + let localTransferInfo: TxResult<'payload'>; try { - localTransfer = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); - await localTransfer.tx.signAndSend(origin); + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); } catch (e) { console.error(e); throw Error(e as string); } }; -export const foreignAssetsTests: { [K: string]: Function } = { createTransferTransaction }; + +const createLocalForeignTransferTransaction = async ( + origin: KeyringPair, + destChainId: string, + destAddr: string, + assetIds: string[], + amounts: string[], + opts: object, + api: ApiPromise, + specName: string, + safeXcmVersion: number, +) => { + const assetApi = createAssetApi(api, specName, safeXcmVersion); + + let localTransferInfo: TxResult<'payload'>; + try { + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); + } catch (e) { + console.error(e); + throw Error(e as string); + } +}; + +export const foreignAssetsTests: { [K: string]: Function } = { + createForeignTransferTransaction, + createLocalForeignTransferTransaction, +}; diff --git a/e2e-tests/tests/index.ts b/e2e-tests/tests/index.ts index 2e2eacf1..b1c8cc82 100644 --- a/e2e-tests/tests/index.ts +++ b/e2e-tests/tests/index.ts @@ -22,28 +22,41 @@ export interface TestGroups { export const tests: TestGroups = { foreignAssets: [ { - // This will declare the call to use - test: 'createTransferTransactionCall', - // This will be all the args for the above call + test: 'createForeignTransferTransaction', args: [ - '1836', '1000', + '1836', '//Alice', BOB_ADDR, + '[{ "parents": "1", "interior": { "X2": [{ "Parachain": "1836" }, { "GeneralIndex": "0" }]}}]', + '[200000000]', + '{ "format": "payload", "xcmVersion": 3, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" }', + ], + verification: [ + '[{ "parents": "1", "interior": { "X2": [{ "Parachain": "1836" }, { "GeneralIndex": "0" }]}}]', + '[200000000]', + ], + }, + { + test: 'createLocalForeignTransferTransaction', + args: [ + '1000', + '1000', + '//Alice', + FERDE_ADDR, + '[{ "parents": "1", "interior": { "X2": [{ "Parachain": "1836" }, { "GeneralIndex": "0" }]}}]', + '[200000000000]', + '{ "format": "payload", "xcmVersion": 3, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" }', + ], + verification: [ '[{ "parents": "1", "interior": { "X2": [{ "Parachain": "1836" }, { "GeneralIndex": "0" }]}}]', '[200000000000]', - '{ "format": "submittable", "xcmVersion": 3 }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end - verification: ['', ''], }, ], liquidPools: [ { - // This will declare the call to use test: 'createLocalTransferTransaction', - // This will be all the args for the above call args: [ '1000', '1000', @@ -51,16 +64,12 @@ export const tests: TestGroups = { BOB_ADDR, '[0]', '[20000]', - '{ "format": "submittable", "transferLiquidToken": true }', + '{ "format": "payload", "keepAlive": true, "transferLiquidToken": true, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end - verification: ['[0]', '[2000]'], + verification: ['[0]', '[20000]'], }, { - // This will declare the call to use test: 'createPayFeesTransaction', - // This will be all the args for the above call args: [ '1000', '1000', @@ -68,18 +77,14 @@ export const tests: TestGroups = { FERDE_ADDR, '[0]', '[3000000]', - '{ "format": "payload", "xcmVersion": 3, "transferLiquidToken": true, "paysWithFeeOrigin": { "parents": "0", "interior": { "X2": [{"PalletInstance": "50"}, { "GeneralIndex": "1" }]}}, "sendersAddr": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" }', + '{ "format": "payload", "keepAlive": true, "transferLiquidToken": true, "paysWithFeeOrigin": { "parents": "0", "interior": { "X2": [{"PalletInstance": "50"}, { "GeneralIndex": "1" }]}}, "sendersAddr": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end verification: ['[0]', '[3000000]'], }, ], local: [ { - // This will declare the call to use test: 'createLocalTransferTransaction', - // This will be all the args for the above call args: [ '1000', '1000', @@ -87,16 +92,12 @@ export const tests: TestGroups = { BOB_ADDR, '[]', '[100000000000]', - '{ "format": "submittable", "keepAlive": true }', + '{ "format": "payload", "keepAlive": true, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end - verification: ['[0]', '[10000000000000]'], + verification: ['[]', '[100000000000]'], }, { - // This will declare the call to use - test: 'createLocalTransferTransaction', - // This will be all the args for the above call + test: 'createLocalTransferTransactionWithFees', args: [ '0', '0', @@ -104,18 +105,40 @@ export const tests: TestGroups = { BOB_ADDR, '[]', '[100000000000000000]', - '{ "format": "submittable", "keepAlive": true }', + '{ "format": "payload", "keepAlive": true, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", "paysWithFeeOrigin": { "parents": "0", "interior": { "X2": [{"PalletInstance": "50"}, { "GeneralIndex": "1" }]}} }', + ], + verification: ['[]', '[10000000000000]'], + }, + { + test: 'createLimitedNativeTransferToRelay', + args: [ + '1000', + '0', + '//Alice', + BOB_ADDR, + '[]', + '[1000000000000000]', + '{ "format": "payload", "keepAlive": true, "xcmVersion": 3, "isLimited": true, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", "paysWithFeeOrigin": { "parents": "0", "interior": { "X2": [{"PalletInstance": "50"}, { "GeneralIndex": "1" }]}} }', + ], + verification: ['[]', '[1000000000000000]'], + }, + { + test: 'createLimitedNativeTransferToSystem', + args: [ + '0', + '1000', + '//Bob', + FERDE_ADDR, + '[]', + '[210000000000000]', + '{ "format": "payload", "keepAlive": true, "xcmVersion": 3, "isLimited": true, "weightLimit": {"refTime": "10000" , "proofSize": "3000"}, "sendersAddr": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", "paysWithFeeOrigin": { "parents": "0", "interior": { "X2": [{"PalletInstance": "50"}, { "GeneralIndex": "1" }]}} }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end - verification: ['[0]', '[10000000000000]'], + verification: ['[]', '[210000000000000]'], }, ], assets: [ { - // This will declare the call to use test: 'createLocalSystemAssetsTransferTransaction', - // This will be all the args for the above call args: [ '1000', '1000', @@ -123,16 +146,12 @@ export const tests: TestGroups = { BOB_ADDR, '[1]', '[3000000000000]', - '{ "format": "submittable", "keepAlive": true }', + '{ "format": "payload", "keepAlive": true, "sendersAddr": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end - verification: ['[1]', '[30000]'], + verification: ['[1]', '[3000000000000]'], }, { - // This will declare the call to use test: 'createPayFeesTransaction', - // This will be all the args for the above call args: [ '1000', '1000', @@ -140,11 +159,9 @@ export const tests: TestGroups = { FERDE_ADDR, '[1]', '[200000000000]', - '{ "format": "submittable", "keepAlive": true }', + '{ "format": "payload", "keepAlive": false, "sendersAddr": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", "paysWithFeeOrigin": { "parents": "0", "interior": { "X2": [{"PalletInstance": "50"}, { "GeneralIndex": "1" }]}} }', ], - // This will be a tuple that will allow us to verify if the xcm message - // succesfully went through on the other end - verification: ['[1]', '[2000]'], + verification: ['[1]', '[200000000000]'], }, ], }; diff --git a/e2e-tests/tests/liquidPools.ts b/e2e-tests/tests/liquidPools.ts index 51d7086b..49683064 100644 --- a/e2e-tests/tests/liquidPools.ts +++ b/e2e-tests/tests/liquidPools.ts @@ -4,15 +4,16 @@ import { KeyringPair } from '@polkadot/keyring/types'; import { AssetTransferApi } from '../../src'; import { TxResult } from '../../src/types'; +import { EXTRINSIC_VERSION } from '../consts'; const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: number): AssetTransferApi => { const injectedRegistry = { rococo: { '1836': { - tokens: ['ROC'], + tokens: ['HOP'], assetsInfo: {}, foreignAssetsInfo: {}, - specName: 'asset-hub-rococo', + specName: 'trappist-rococo', poolPairsInfo: {}, }, }, @@ -36,10 +37,17 @@ const createLocalTransferTransaction = async ( ) => { const assetApi = createAssetApi(api, specName, safeXcmVersion); - let localTransferInfo: TxResult<'submittable'>; + let localTransferInfo: TxResult<'payload'>; try { localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); - await localTransferInfo.tx.signAndSend(origin); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); } catch (e) { console.error(e); throw Error(e as string); @@ -59,12 +67,12 @@ const createPayFeesTransaction = async ( ) => { const assetApi = createAssetApi(api, specName, safeXcmVersion); - let transferInfo: TxResult<'payload'>; + let transferWithFeesInfo: TxResult<'payload'>; try { - transferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + transferWithFeesInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); - const payload = api.createType('ExtrinsicPayload', transferInfo.tx, { - version: 4, + const payload = api.createType('ExtrinsicPayload', transferWithFeesInfo.tx, { + version: EXTRINSIC_VERSION, }); const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); diff --git a/e2e-tests/tests/local.ts b/e2e-tests/tests/local.ts index 4ab1cdc7..5cc3aec4 100644 --- a/e2e-tests/tests/local.ts +++ b/e2e-tests/tests/local.ts @@ -2,6 +2,7 @@ import { ApiPromise } from '@polkadot/api'; import { KeyringPair } from '@polkadot/keyring/types'; +import { EXTRINSIC_VERSION } from 'consts'; import { AssetTransferApi } from '../../src'; import { TxResult } from '../../src/types'; @@ -10,10 +11,10 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe const injectedRegistry = { rococo: { '1836': { - tokens: ['ROC'], + tokens: ['HOP'], assetsInfo: {}, foreignAssetsInfo: {}, - specName: 'asset-hub-rococo', + specName: 'trappist-rococo', poolPairsInfo: {}, }, }, @@ -30,17 +31,114 @@ const createLocalTransferTransaction = async ( destAddr: string, assetIds: string[], amounts: string[], - opts: object, + opts: {}, api: ApiPromise, specName: string, safeXcmVersion: number, ) => { const assetApi = createAssetApi(api, specName, safeXcmVersion); - let localTransferInfo: TxResult<'submittable'>; + let localTransferInfo: TxResult<'payload'>; try { localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); - await localTransferInfo.tx.signAndSend(origin); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); + } catch (e) { + console.error(e); + throw Error(e as string); + } +}; + +const createLocalTransferTransactionWithFees = async ( + origin: KeyringPair, + destChainId: string, + destAddr: string, + assetIds: string[], + amounts: string[], + opts: {}, + api: ApiPromise, + specName: string, + safeXcmVersion: number, +) => { + const assetApi = createAssetApi(api, specName, safeXcmVersion); + + let localTransferInfo: TxResult<'payload'>; + try { + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); + } catch (e) { + console.error(e); + throw Error(e as string); + } +}; + +const createLimitedNativeTransferToRelay = async ( + origin: KeyringPair, + destChainId: string, + destAddr: string, + assetIds: string[], + amounts: string[], + opts: {}, + api: ApiPromise, + specName: string, + safeXcmVersion: number, +) => { + const assetApi = createAssetApi(api, specName, safeXcmVersion); + + let localTransferInfo: TxResult<'payload'>; + try { + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); + } catch (e) { + console.error(e); + throw Error(e as string); + } +}; + +const createLimitedNativeTransferToSystem = async ( + origin: KeyringPair, + destChainId: string, + destAddr: string, + assetIds: string[], + amounts: string[], + opts: {}, + api: ApiPromise, + specName: string, + safeXcmVersion: number, +) => { + const assetApi = createAssetApi(api, specName, safeXcmVersion); + + let localTransferInfo: TxResult<'payload'>; + try { + localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts); + + const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, { + version: EXTRINSIC_VERSION, + }); + + const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 }); + + await api.tx(extrinsic).signAndSend(origin); } catch (e) { console.error(e); throw Error(e as string); @@ -49,4 +147,7 @@ const createLocalTransferTransaction = async ( export const localTests: { [K: string]: Function } = { createLocalTransferTransaction, + createLocalTransferTransactionWithFees, + createLimitedNativeTransferToRelay, + createLimitedNativeTransferToSystem, }; diff --git a/e2e-tests/verification.ts b/e2e-tests/verification.ts index 196a9e58..99a88a4e 100644 --- a/e2e-tests/verification.ts +++ b/e2e-tests/verification.ts @@ -1,6 +1,14 @@ // Copyright 2023 Parity Technologies (UK) Ltd. import { IBalance } from './balance'; +/** + * This function verifies whether the test transaction impacted the destination's + * account balance + * @param assetIds assets to be queried + * @param amounts expected final balance + * @param destBalance stored queried balance + * @returns whetere the balance was modified as expected or not + */ export const verification = (assetIds: string[], amounts: string[], destBalance: IBalance) => { const destInitialBalance: [string, number][] = destBalance.initial; const destFinalBalance: [string, number][] = destBalance.final; diff --git a/scripts/consts.ts b/scripts/consts.ts index 721f697b..1a3e85ab 100644 --- a/scripts/consts.ts +++ b/scripts/consts.ts @@ -2,5 +2,5 @@ export const KUSAMA_ASSET_HUB_WS_URL = 'ws://127.0.0.1:9911'; export const ROCOCO_ALICE_WS_URL = 'ws://127.0.0.1:9900'; -export const ROCOCO_ASSET_HUB_WS_URL = 'ws://127.0.0.1:9921'; +export const TRAPPIST_WS_URL = 'ws://127.0.0.1:9921'; export const MOONRIVER_WS_URL = 'ws://127.0.0.1:9931'; diff --git a/scripts/testNetworkForeignAssets.ts b/scripts/testNetworkForeignAssets.ts index 286a89fe..a8ff4d34 100644 --- a/scripts/testNetworkForeignAssets.ts +++ b/scripts/testNetworkForeignAssets.ts @@ -5,11 +5,11 @@ import { Keyring } from '@polkadot/keyring'; import { cryptoWaitReady } from '@polkadot/util-crypto'; import chalk from 'chalk'; -import { KUSAMA_ASSET_HUB_WS_URL, ROCOCO_ALICE_WS_URL, ROCOCO_ASSET_HUB_WS_URL } from './consts'; +import { KUSAMA_ASSET_HUB_WS_URL, ROCOCO_ALICE_WS_URL, TRAPPIST_WS_URL } from './consts'; import { awaitBlockProduction, awaitEpochChange, delay, logWithDate } from './util'; const fAssetSetMetadataCall = (assetHubApi: ApiPromise): `0x${string}` => { - const rockmineMultilocatino = { + const trappistMultilocation = { parents: 1, interior: { X1: { @@ -19,7 +19,7 @@ const fAssetSetMetadataCall = (assetHubApi: ApiPromise): `0x${string}` => { }; const setMetadataTx = assetHubApi.tx.foreignAssets.setMetadata( - rockmineMultilocatino, + trappistMultilocation, 'Asset Hub Rococo Hop', 'Hop', 12, @@ -36,17 +36,17 @@ const fAssetSetMetadataCall = (assetHubApi: ApiPromise): `0x${string}` => { }; const fAssetCreateCall = (assetHubApi: ApiPromise): `0x${string}` => { - const rockmineMultilocatino = { + const trappistMultilocation = { parents: 1, interior: { X1: { - parachain: 3000, + parachain: 1836, }, }, }; const createTx = assetHubApi.tx.foreignAssets.create( - rockmineMultilocatino, + trappistMultilocation, '5Eg2fnsjAAr8RGZfa8Sy5mYFPabA9ZLNGYECCKXPD6xnK6D2', // Sibling 1836 -> ParaId '100000000000', ); @@ -61,13 +61,13 @@ const fAssetCreateCall = (assetHubApi: ApiPromise): `0x${string}` => { return hexCall; }; -const sudoCallWrapper = (rockmineApi: ApiPromise, call: `0x${string}`) => { +const sudoCallWrapper = (trappistApi: ApiPromise, call: `0x${string}`) => { // Double encode the call - const xcmDoubleEncoded = rockmineApi.createType('XcmDoubleEncoded', { + const xcmDoubleEncoded = trappistApi.createType('XcmDoubleEncoded', { encoded: call, }); - const xcmOriginType = rockmineApi.createType('XcmOriginKind', 'Xcm'); + const xcmOriginType = trappistApi.createType('XcmOriginKind', 'Xcm'); const xcmDestMultiLocation = { V3: { parents: 1, @@ -145,8 +145,8 @@ const sudoCallWrapper = (rockmineApi: ApiPromise, call: `0x${string}`) => { }, ], }; - const xcmMsg = rockmineApi.tx.polkadotXcm.send(xcmDestMultiLocation, xcmMessage); - const xcmCall = rockmineApi.createType('Call', { + const xcmMsg = trappistApi.tx.polkadotXcm.send(xcmDestMultiLocation, xcmMessage); + const xcmCall = trappistApi.createType('Call', { callIndex: xcmMsg.callIndex, args: xcmMsg.args, }); @@ -154,14 +154,14 @@ const sudoCallWrapper = (rockmineApi: ApiPromise, call: `0x${string}`) => { return xcmCall; }; -const createForeignAssetViaSudo = (assetHubApi: ApiPromise, rockmineApi: ApiPromise) => { +const createForeignAssetViaSudo = (assetHubApi: ApiPromise, trappistApi: ApiPromise) => { const foreignAssetCreateCall = fAssetCreateCall(assetHubApi); - return sudoCallWrapper(rockmineApi, foreignAssetCreateCall); + return sudoCallWrapper(trappistApi, foreignAssetCreateCall); }; -const setMetadataForeignAssetViaSudo = (assetHubApi: ApiPromise, rockmineApi: ApiPromise) => { +const setMetadataForeignAssetViaSudo = (assetHubApi: ApiPromise, trappistApi: ApiPromise) => { const setMetadataCall = fAssetSetMetadataCall(assetHubApi); - return sudoCallWrapper(rockmineApi, setMetadataCall); + return sudoCallWrapper(trappistApi, setMetadataCall); }; const openHrmpChannels = (api: ApiPromise, sender: number, receiver: number) => { @@ -184,13 +184,13 @@ const main = async () => { await kusamaAssetHubApi.isReady; logWithDate(chalk.green('Created a connection to Kusama AssetHub')); - const rockmineApi = await ApiPromise.create({ - provider: new WsProvider(ROCOCO_ASSET_HUB_WS_URL), + const trappistApi = await ApiPromise.create({ + provider: new WsProvider(TRAPPIST_WS_URL), noInitWarn: true, }); - await rockmineApi.isReady; - logWithDate(chalk.green('Created a connection to Rococo Asset Hub')); + await trappistApi.isReady; + logWithDate(chalk.green('Created a connection to Trappist')); const relayApi = await ApiPromise.create({ provider: new WsProvider(ROCOCO_ALICE_WS_URL), @@ -213,23 +213,23 @@ const main = async () => { await awaitEpochChange(relayApi); logWithDate(chalk.magenta('HRMP channels open')); - logWithDate(chalk.magenta('Sending funds to Rococo Asset Hub Sibling on Kusama AssetHub')); + logWithDate(chalk.magenta('Sending funds to Trappist Sibling on Kusama AssetHub')); await kusamaAssetHubApi.tx.balances .transferKeepAlive('5Eg2fnsjAAr8RGZfa8Sy5mYFPabA9ZLNGYECCKXPD6xnK6D2', 10000000000000) .signAndSend(bob); - const foreignAssetsCreateSudoXcmCall = createForeignAssetViaSudo(kusamaAssetHubApi, rockmineApi); + const foreignAssetsCreateSudoXcmCall = createForeignAssetViaSudo(kusamaAssetHubApi, trappistApi); logWithDate('Sending Sudo XCM message from relay chain to execute create foreign asset call on Kusama AssetHub'); - await rockmineApi.tx.sudo.sudo(foreignAssetsCreateSudoXcmCall).signAndSend(alice); + await trappistApi.tx.sudo.sudo(foreignAssetsCreateSudoXcmCall).signAndSend(alice); await delay(24000); - const foreignAssetsSetMetadataSudoXcmCall = setMetadataForeignAssetViaSudo(kusamaAssetHubApi, rockmineApi); + const foreignAssetsSetMetadataSudoXcmCall = setMetadataForeignAssetViaSudo(kusamaAssetHubApi, trappistApi); logWithDate('Sending Sudo XCM message from relay chain to execute setMetadata call on Kusama AssetHub'); - await rockmineApi.tx.sudo.sudo(foreignAssetsSetMetadataSudoXcmCall).signAndSend(alice); + await trappistApi.tx.sudo.sudo(foreignAssetsSetMetadataSudoXcmCall).signAndSend(alice); await delay(24000); @@ -237,13 +237,13 @@ const main = async () => { logWithDate(chalk.blue('Polkadot-js successfully disconnected from asset-hub')); }); - await rockmineApi.disconnect().then(() => { - logWithDate(chalk.blue('Polkadot-js successfully disconnected from Rococo Asset Hub')); + await trappistApi.disconnect().then(() => { + logWithDate(chalk.blue('Polkadot-js successfully disconnected from Trappist')); }); }; // eslint-disable-next-line @typescript-eslint/no-floating-promises -awaitBlockProduction(ROCOCO_ASSET_HUB_WS_URL).then(async () => { +awaitBlockProduction(TRAPPIST_WS_URL).then(async () => { await main() .catch(console.error) .finally(() => process.exit()); diff --git a/scripts/testNetworkLiquidAssets.ts b/scripts/testNetworkLiquidAssets.ts index 970fc48a..00c2e8cd 100644 --- a/scripts/testNetworkLiquidAssets.ts +++ b/scripts/testNetworkLiquidAssets.ts @@ -81,11 +81,7 @@ const main = async () => { const hrmpChannelCalls = []; hrmpChannelCalls.push(openHrmpChannels(relayApi, Number(1000), Number(1836))); - hrmpChannelCalls.push(openHrmpChannels(relayApi, Number(1000), Number(4000))); hrmpChannelCalls.push(openHrmpChannels(relayApi, Number(1836), Number(1000))); - hrmpChannelCalls.push(openHrmpChannels(relayApi, Number(1836), Number(4000))); - hrmpChannelCalls.push(openHrmpChannels(relayApi, Number(4000), Number(1000))); - hrmpChannelCalls.push(openHrmpChannels(relayApi, Number(4000), Number(1836))); await relayApi.tx.sudo.sudo(relayApi.tx.utility.batchAll(hrmpChannelCalls)).signAndSend(alice); diff --git a/zombienet/medium-network.toml b/zombienet/medium-network.toml index a7cd04ae..ba485038 100644 --- a/zombienet/medium-network.toml +++ b/zombienet/medium-network.toml @@ -60,24 +60,6 @@ chain = "trappist-local" ws_port = 9921 args = ["--log=xcm=trace,pallet-assets=trace"] -[[parachains]] -id = 4000 -add_to_genesis = true -cumulus_based = true -chain = "moonriver-local" - - [[parachains.collators]] - name = "moonriver-collator01" - command = "./zombienet/bin/moonbeam" - ws_port = 9930 - args = ["--log=xcm=trace,pallet-assets=trace"] - - [[parachains.collators]] - name = "moonriver-collator02" - command = "./zombienet/bin/moonbeam" - ws_port = 9931 - args = ["--log=xcm=trace,pallet-assets=trace"] - [types.Header] number = "u64" parent_hash = "Hash"