-
Notifications
You must be signed in to change notification settings - Fork 707
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
base: master
Are you sure you want to change the base?
Changes from 7 commits
4c2d063
33c3a09
eed6aaf
799d65c
d663799
5e677de
443fc85
274debb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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', { | ||
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 .` |
There was a problem hiding this comment.
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