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

[Draft] Chopsticks tests with papi and local nodes #6572

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This folder serves as a reference documentation for chopstick tests and the Parity-owned ecosystems.
It provides a working set of configuration files together with the WASM BLOBs, specifically for the Westend ecosystem.
For additional resources and original Acala configuration files, including documentation, refer to the [Acala repository](https://github.com/AcalaNetwork/chopsticks/tree/master/configs) or [Papermoon chopsticks overview](https://papermoonio.github.io/polkadot-ecosystem-docs-draft/dev-tools/chopsticks/overview/#using-a-configuration-file)

Config files, especially `wasm-override:` fields there, assume that there is a `wasms` folder within the same parent directory, and it contains pre-built WASM BLOBs of the
ecosystem under tests.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
endpoint: wss://asset-hub-polkadot-rpc.dwellir.com
mock-signature-host: true
block: ${env.WESTEND_ASSET_HUB_BLOCK_NUMBER}
db: ./db.sqlite
runtime-log-level: 5
wasm-override: wasms/asset_hub_westend_runtime.compact.compressed.wasm

import-storage:
System:
Account:
-
-
- 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY # Alice
- providers: 1
data:
free: 1000000000000000
-
-
- 5Eg2fntQqFi3EvFWAf71G66Ecjjah26bmFzoANAeHFgj9Lia
- providers: 1
data:
free: 1000000000000000
-
-
- 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty # Bob
- providers: 1
data:
free: 1000000000000000
# Assets:
# Account:
# - [[1984, 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY], { balance: 1000000000 }]
# - [[1984, 5Eg2fntQqFi3EvFWAf71G66Ecjjah26bmFzoANAeHFgj9Lia], { balance: 1000000000 }]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
endpoint: wss://bridge-hub-polkadot-rpc.dwellir.com
mock-signature-host: true
block: ${env.WESTEND_BRIDGE_HUB_BLOCK_NUMBER}
db: ./db.sqlite
runtime-log-level: 5
wasm-override: wasms/bridge_hub_westend_runtime.compact.compressed.wasm

import-storage:
System:
Account:
-
-
- 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY # Alice
- providers: 1
data:
free: 1000000000000000
-
-
- 5Eg2fntQqFi3EvFWAf71G66Ecjjah26bmFzoANAeHFgj9Lia
- providers: 1
data:
free: 1000000000000000
-
-
- 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty # Bob
- providers: 1
data:
free: 1000000000000000
# Assets:
# Account:
# - [[1984, 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY], { balance: 1000000000 }]
# - [[1984, 5Eg2fntQqFi3EvFWAf71G66Ecjjah26bmFzoANAeHFgj9Lia], { balance: 1000000000 }]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
endpoint:
- wss://westend-rpc.dwellir.com
mock-signature-host: true
block: ${env.WESTEND_BLOCK_NUMBER}
db: ./db.sqlite
runtime-log-level: 5
wasm-override: wasms/westend_runtime.compact.compressed.wasm

import-storage:
XcmPallet:
SafeXcmVersion: 5
System:
Account:
-
-
- 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
- providers: 1
data:
free: '10000000000000000000'
ParasDisputes:
$removePrefix: ['disputes']
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# v5-sac-test

To install dependencies:

```bash
bun add polkadot-api
# now you need to switch to another terminal window where you executed bunx command, make sure that chains are running and copy Asset Hub's port in the command below (usually the port is 8001).
bun papi add wnd_ah -w ws://localhost:8001
bun add @polkadot-labs/hdkd
```

To run the test:

```bash
bun test ./index.ts
# note: the test may time out during the first run. Single retry usually helps.
```

This project was created using `bun init` in bun v1.1.34. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
import { test, expect } from "bun:test";
import {
wnd_ah,
XcmV3Junctions,
XcmV3Junction,
XcmV3MultiassetFungibility,
XcmV4Instruction,
XcmV3WeightLimit,
XcmV3MultiassetMultiAssetFilter,
XcmV4AssetAssetFilter
} from "@polkadot-api/descriptors";
import { Binary, Enum, createClient } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws-provider/web";
import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
import {
DEV_PHRASE,
entropyToMiniSecret,
mnemonicToEntropy,
} from "@polkadot-labs/hdkd-helpers";
import { getPolkadotSigner } from "polkadot-api/signer";

const WESTEND_NETWORK = Uint8Array.from([225, 67, 242, 56, 3, 172, 80, 232, 246, 248, 230, 38, 149, 209, 206, 158, 78, 29, 104, 170, 54, 193, 205, 44, 253, 21, 52, 2, 19, 243, 66, 62]);
// TODO: find a way to extract keys below from yaml config.
const BOB_KEY = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty";
const ALICE_KEY = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";

// Create and initialize client
const client = createClient(withPolkadotSdkCompat(getWsProvider("ws://localhost:8000")));
const AHApi = client.getTypedApi(wnd_ah);

// Initialize HDKD key pairs and signers
const entropy = mnemonicToEntropy(DEV_PHRASE);
const miniSecret = entropyToMiniSecret(entropy);
const derive = sr25519CreateDerive(miniSecret);

const hdkdKeyPairAlice = derive("//Alice");
const hdkdKeyPairBob = derive("//Bob");

const aliceSigner = getPolkadotSigner(
hdkdKeyPairAlice.publicKey,
"Sr25519",
hdkdKeyPairAlice.sign,
);

const bobSigner = getPolkadotSigner(
hdkdKeyPairBob.publicKey,
"Sr25519",
hdkdKeyPairBob.sign,
);

// Utility function for balance fetching
async function getFreeBalance(api, accountKey) {
const balance = await api.query.System.Account.getValue(accountKey);
return balance.data.free;
}

test("Set Asset Claimer, Trap Assets, Claim Trapped Assets", async () => {
const bobBalanceBefore = await getFreeBalance(AHApi, BOB_KEY);

const alice_msg = Enum("V5", [
Enum("SetAssetClaimer", {
location: {
parents: 0,
interior: XcmV3Junctions.X1(XcmV3Junction.AccountId32({
network: Enum("ByGenesis", Binary.fromBytes(WESTEND_NETWORK)),
id: Binary.fromBytes(hdkdKeyPairBob.publicKey),
}))
},
}),
XcmV4Instruction.WithdrawAsset([{
id: { parents: 1, interior: XcmV3Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000_000n),
}]),
XcmV4Instruction.ClearOrigin(),
]);
const alice_weight = await AHApi.apis.XcmPaymentApi.query_xcm_weight(alice_msg);

// Transaction 1: Alice sets asset claimer to Bob and sends a trap transaction
const trapTx = AHApi.tx.PolkadotXcm.execute({
message: alice_msg,
max_weight: { ref_time: alice_weight.value.ref_time, proof_size: alice_weight.value.proof_size },
});

const trapResult = await trapTx.signAndSubmit(aliceSigner);
expect(trapResult.ok).toBeTruthy();

const bob_msg = Enum("V4", [
XcmV4Instruction.ClaimAsset({
assets: [{
id: { parents: 1, interior: XcmV3Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000_000n),
}],
ticket: { parents: 0, interior: XcmV3Junctions.Here() },
}),
XcmV4Instruction.BuyExecution({
fees: {
id: { parents: 1, interior: XcmV3Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000n),
},
weight_limit: XcmV3WeightLimit.Unlimited(),
}),
XcmV4Instruction.DepositAsset({
assets: XcmV3MultiassetMultiAssetFilter.Definite([{
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000_000n),
id: { parents: 1, interior: XcmV3Junctions.Here() },
}]),
beneficiary: {
parents: 0,
interior: XcmV3Junctions.X1(XcmV3Junction.AccountId32({
network: undefined,
id: Binary.fromBytes(hdkdKeyPairBob.publicKey),
}))
}
}),
]);
const bob_weight = await AHApi.apis.XcmPaymentApi.query_xcm_weight(bob_msg);

// Transaction 2: Bob claims trapped assets.
const bobClaimTx = AHApi.tx.PolkadotXcm.execute({
message: bob_msg,
max_weight: { ref_time: bob_weight.value.ref_time, proof_size: bob_weight.value.proof_size },
});

const claimResult = await bobClaimTx.signAndSubmit(bobSigner);
expect(claimResult.ok).toBeTruthy();


const bobBalanceAfter = await getFreeBalance(AHApi, BOB_KEY);
expect(bobBalanceAfter > bobBalanceBefore).toBeTruthy();
});

test("Initiate Teleport XCM v4", async () => {
const msg = Enum("V4", [
XcmV4Instruction.WithdrawAsset([{
id: { parents: 1, interior: XcmV3Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(7e12),
}]),
XcmV4Instruction.SetFeesMode({
jit_withdraw: true,
}),
XcmV4Instruction.InitiateTeleport({
assets: XcmV4AssetAssetFilter.Wild({type: "All", value: undefined}),
dest: {
parents: 1,
interior: XcmV3Junctions.Here(),
},
xcm: [
XcmV4Instruction.BuyExecution({
fees: {
id: { parents: 0, interior: XcmV3Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(500_000_000_000n),
},
weight_limit: XcmV3WeightLimit.Unlimited(),
}),
],
}),
]);
const weight = await AHApi.apis.XcmPaymentApi.query_xcm_weight(msg);

const ahToWnd = AHApi.tx.PolkadotXcm.execute({
message: msg,
max_weight: { ref_time: weight.value.ref_time, proof_size: weight.value.proof_size },
},
);

const r = await ahToWnd.signAndSubmit(aliceSigner);
expect(r).toBeTruthy();
})

test("Initiate Teleport XCM v5", async () => {
const msg = Enum('V5', [
XcmV4Instruction.WithdrawAsset([
{
id: { parents: 1, interior: XcmV3Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(5_000_000_000_000n),
},

]),
Enum('PayFees', {
asset: {
id: {
parents: 1,
interior: XcmV3Junctions.Here(),
},
fun: XcmV3MultiassetFungibility.Fungible(2_000_000_000_000n),
}
}),
Enum('InitiateTransfer', {
destination: {
parents: 1,
interior: XcmV3Junctions.Here(),
},
// optional field. an example of usage:
// remote_fees: Enum('Teleport', {
// type: 'Wild',
// value: {
// type: 'All',
// value: undefined,
// },
// }),
preserve_origin: false,
assets: [Enum('Teleport', {
type: 'Wild',
value: {
type: 'All',
value: undefined,
},
})],
remote_xcm: [
Enum('PayFees', {
Copy link
Contributor

Choose a reason for hiding this comment

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

If you pass in "remote_fee" it already adds this PayFees in the remote message

asset: {
id: {
parents: 0,
interior: XcmV3Junctions.Here(),
},
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000_000n),
}
}),
XcmV4Instruction.DepositAsset({
assets: XcmV3MultiassetMultiAssetFilter.Definite([{
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000_000n),
id: { parents: 0, interior: XcmV3Junctions.Here() },
}]),
beneficiary: {
parents: 0,
interior: XcmV3Junctions.X1(XcmV3Junction.AccountId32({
network: undefined,
id: Binary.fromBytes(hdkdKeyPairBob.publicKey),
})),
},
}),
],
}),
]);
const weight = await AHApi.apis.XcmPaymentApi.query_xcm_weight(msg);

const ahToWnd = AHApi.tx.PolkadotXcm.execute({
message: msg,
max_weight: { ref_time: weight.value.ref_time, proof_size: weight.value.proof_size },
},
);
Comment on lines +313 to +319
Copy link
Contributor

Choose a reason for hiding this comment

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

Awesome use of the runtime API, I didn't think of it but it's much easier now for clients to call "execute". Did you need to add some extra weight as margin or did this work out of the box?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This worked out of the box. I thought that was the intention 😸

const r = await ahToWnd.signAndSubmit(aliceSigner);
expect(r).toBeTruthy();
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This folder contains WASM BLOBs which are supposed to be used by chopstick tests.
To populate this folder with the required files you need to:
1. BUILD relevant runtimes: usually relay and parachain(s).
- `cargo build --release -p westend-runtime `
- `cargo build --release -p asset-hub-westend-runtime `
2. Copy compressed wasms from target folder into the current one:
- `WBUILD_PATH=../../../../../target/release/wbuild`
- `cp $WBUILD_PATH/asset-hub-westend-runtime/asset_hub_westend_runtime.compact.compressed.wasm .`
- `cp $WBUILD_PATH/westend-runtime/westend_runtime.compact.compressed.wasm .`
Loading