Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: chopsticks #650

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
8 changes: 6 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,20 @@ integration-tests:
image: paritytech/ci-unified:bullseye-1.70.0
stage: test
variables:
CI: "true"
SPIRITNET_BLOCK_NUMBER: 6390611
Copy link
Member

@ntn-x2 ntn-x2 Sep 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move these to the relevant part of our new GH workflow (when merging conflicts with develop).

HYDRADX_BLOCK_NUMBER: 5235787
POLKADOT_BLOCK_NUMBER: 21010819
SPIRITNET_WASM_OVERRIDE: "../../target/debug/wbuild/spiritnet-runtime/spiritnet_runtime.compact.compressed.wasm"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No compact WASM is generated anymore, so this should refer to the regular, uncompressed, uncompacted one.

script:
- cd ./integration-tests/chopsticks
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
- export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" --no-use
- eval "[ -f .nvmrc ] && nvm install" && nvm use
- yarn --immutable
- cargo build -p spiritnet-runtime
- yarn ts-check
- yarn lint
- yarn test:CI
- yarn test

# TODO: The try-runtime-cli executable could be built as part of the Docker image directly, saving some time.
test-try-runtime:
Expand Down
16 changes: 10 additions & 6 deletions integration-tests/chopsticks/.env-example
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
HYDRADX_WS=
HYDRADX_PORT=
POLKADOT_WS=
POLKADOT_PORT=
SPIRITNET_WS=
SPIRITNET_PORT=
# Those env variables are mandatory for the tests to work.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Those env variables are mandatory for the tests to work.
# These env variables are mandatory for the tests to work.


# The Spiritnet block number to be used in the tests
SPIRITNET_BLOCK_NUMBER=
# The HydraDx block number to be used in the tests
HYDRADX_BLOCK_NUMBER=
# The Polkadot block number to be used in the tests
POLKADOT_BLOCK_NUMBER=
# Directory path to the new WASM blob
SPIRITNET_WASM_OVERRIDE=
74 changes: 74 additions & 0 deletions integration-tests/chopsticks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# e2e Chopsticks tests

This project is a set of end-to-end tests for the KILT protocol against other parachains.
Other functionalities such as a creation of DID can be easy inserted.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Other functionalities such as a creation of DID can be easy inserted.
Other functionalities such as a creation of DID can be easily added.


## Getting Started

These instructions will allow you to run the tests on your local machine for development and testing purposes.

### Prerequisites

- Node.js v20.11.0 (as specified in the [`.nvmrc`](https://github.com/nvm-sh/nvm)). With `nvm use` the right node version will be installed.
- npm (comes with Node.js)


### Installing

To install the node modules call:

```sh
yarn
```

### Running the tests

In the package.json a script is provided.

By calling the command below, the test will be executed:

```sh
yarn test
```

Please make sure an appropriate env is set.

### Env

The project uses environment variables for configuration. You can find an example in the `.env-example` file. Copy this file to
.env and fill in the appropriate values. Explanation for the values are in the `.env-example` file provided.


## Built With

[TypeScript](https://www.typescriptlang.org/)
[Chopsticks](https://github.com/AcalaNetwork/chopsticks)
[Polkadot API](https://github.com/polkadot-js/api)

## Code Style

This project uses Prettier and ESLint for code formatting and linting. The configuration for these tools can be found in the `.prettierrc` and `.eslintrc.json` files respectively.

To check your code for style issues, run:

```sh
yarn lint
```

To automatically fix style issues, run:

```sh
yarn lint:fix
```

## Adding a new test case

To add a new test case, you need to insert a new object into the list of test cases. For example, if you want to add a new instance of `LimitedReserveTestConfiguration`, you would insert it into the `testPairsLimitedReserveTransfers` list. Here's a step-by-step guide:


- Create a new instance of LimitedReserveTestConfiguration. Make sure to fill in all the necessary parameters for the test.
- Insert this new instance into the testPairsLimitedReserveTransfers list.

The tests are configuration-driven, meaning they can be easily customized for different scenarios. The test framework doesn't make assumptions about which parachain is sending which coin to which destination over which relay chain. Fundamental events such as the moving of coins or the creation of a new account should be emitted during the test.

The test cases live in the tests folder and use mocks from the network directory. The network directory contains helper functions to set the blockchain state and provides an abstraction over the chopsticks functionalities, such as creating a network.
11 changes: 5 additions & 6 deletions integration-tests/chopsticks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"author": "[\"KILT <[email protected]>\"]",
"license": "MIT",
"devDependencies": {
"@acala-network/chopsticks": "0.10.0",
"@acala-network/chopsticks-testing": "0.10.1",
"@acala-network/chopsticks": "0.11.0",
"@acala-network/chopsticks-testing": "0.11.0",
"@polkadot/api": "^10.11.2",
"@types/node": "^20.11.30",
"@typescript-eslint/eslint-plugin": "^7.7.0",
Expand All @@ -19,22 +19,21 @@
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard-with-typescript": "^43.0.1",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.0.0",
"prettier": "^3.2.5",
"ts-node": "^10.9.2",
"tsx": "^4.7.1",
"typescript": "*",
"vitest": "^1.4.0",
"eslint-plugin-jsx-a11y": "^6.8.0"
"vitest": "^1.4.0"
},
"scripts": {
"ts-check": "tsc --noEmit",
"lint": "eslint src && prettier --check src",
"lint:fix": "eslint --fix src && prettier --write src",
"clean": "rm -rf ./db",
"test": "LOG_LEVEL=error vitest",
"test:CI": "vitest --bail 0 --no-file-parallelism"
"test": "LOG_LEVEL=error vitest"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely lower priority, but we should investigate how to make the tests run faster without them throw errors. Our new GH pipeline currently takes almost 1h, but I have no idea if this refactoring will make tests go faster or slower.

}
}
176 changes: 176 additions & 0 deletions integration-tests/chopsticks/src/helper/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ApiPromise } from '@polkadot/api'

/**
* All possible ways to submit an XCM message for the xtokens pallet.
* different structs for the xcm versions are provided
*/
export const xtokens = {
parachainV2: (paraId: number) => (acc: any) => ({
V1: {
parents: 1,
interior: {
X2: [
{ Parachain: paraId },
{
AccountId32: {
network: 'Any',
id: acc,
},
},
],
},
},
}),
parachainV3: (paraId: number) => (acc: any) => ({
V3: {
parents: 1,
interior: {
X2: [
{ Parachain: paraId },
{
AccountId32: {
id: acc,
},
},
],
},
},
}),
transfer:
(token: any, dest: (dest: any) => any, weight: any = 'Unlimited') =>
({ api }: { api: ApiPromise }, acc: any, amount: any) =>
api.tx.xTokens.transfer(token, amount, dest(acc), weight),
}

/**
* All possible ways to submit an XCM message for the xcmPallet.
* different structs for the xcm versions are provided
*/
export const xcmPallet = {
parachainV2: (parents: number, paraId: number) => ({
V2: {
parents,
interior: {
X1: { Parachain: paraId },
},
},
}),
parachainV3: (parents: number, paraId: any) => ({
V3: {
parents,
interior: {
X1: { Parachain: paraId },
},
},
}),
limitedTeleportAssets:
(token: any, amount: any, dest: any) =>
({ api }: { api: ApiPromise }, acc: any) =>
(api.tx.xcmPallet || api.tx.polkadotXcm).limitedTeleportAssets(
dest,
{
V3: {
parents: 0,
interior: {
X1: {
AccountId32: {
// network: 'Any',
id: acc,
},
},
},
},
},
{
V3: [
{
id: token,
fun: { Fungible: amount },
},
],
},
0,
'Unlimited'
),
limitedReserveTransferAssetsV2:
(token: any, dest: any) =>
({ api }: { api: ApiPromise }, acc: any, amount: any) =>
(api.tx.xcmPallet || api.tx.polkadotXcm).limitedReserveTransferAssets(
dest,
{
V2: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: 'Any',
id: acc,
},
},
},
},
},
{
V2: [
{
id: token,
fun: { Fungible: amount },
},
],
},
0,
'Unlimited'
),
limitedReserveTransferAssetsV3:
(token: any, dest: any) =>
({ api }: { api: ApiPromise }, acc: any, amount: any) =>
(api.tx.xcmPallet || api.tx.polkadotXcm).limitedReserveTransferAssets(
dest,
{
V3: {
parents: 0,
interior: {
X1: {
AccountId32: {
id: acc,
},
},
},
},
},
{
V3: [
{
id: token,
fun: { Fungible: amount },
},
],
},
0,
'Unlimited'
),
}

/**
* Different pallets to submit xcm messages.
*/
export const tx = {
xtokens,
xcmPallet,
}

/**
* Query functions for different chains.
* Native tokens are fetched via the system pallet, while other tokens are fetched via the tokens pallet.
*
*/

export const query = {
balances: async ({ api }: { api: ApiPromise }, address: string) =>
BigInt(((await api.query.system.account(address)) as any).data.free),
tokens:
(token: any) =>
async ({ api }: { api: ApiPromise }, address: string) =>
BigInt(((await api.query.tokens.accounts(address, token)) as any).free),
}
Loading