Skip to content

Commit e1cdea5

Browse files
raymondkfcheungfranciscoaguirrenhussein11
authored
Add Guide: Replay & Dry Run XCMs with Full Logging Using Chopsticks (#734)
* Update Introduction * Update Prerequisites * Update Steps 1-2 * Remove Enable Full Logging * Update Step 2 * Update Step 3 * Update Additional Resources * Update content * Update content v2 * Update develop/toolkit/parachains/fork-chains/chopsticks/replay-xcm.md Co-authored-by: Francisco Aguirre <[email protected]> * Fix link * Update content * Update content v2 * Update content v3 * Update content v4 * Update content v5 * Update content v6 * Update content v7 * Update content v8 * Update content v9 * Add link to fork * Remove release flag * Update to debug * Update to debug wasm * Add Dry Run the XCM * Proofread * Rename to Replay and Dry Run XCMs * Update setup * Fix debug * Update develop/toolkit/parachains/fork-chains/chopsticks/replay-and-dry-run-xcms.md Co-authored-by: Nicolás Hussein <[email protected]> * Update develop/toolkit/parachains/fork-chains/chopsticks/replay-and-dry-run-xcms.md Co-authored-by: Nicolás Hussein <[email protected]> * Update develop/toolkit/parachains/fork-chains/chopsticks/replay-and-dry-run-xcms.md Co-authored-by: Nicolás Hussein <[email protected]> * Remove all numbers from headers * Remove ~/projects * Update Project Setup * Add {target=\_blank} * Update format * Use code snippet * Use Termynal snippet * Fix Termynal snippet * Add <Your Working Directory> * Fix path * Fix Termynal snippet * Add more Termynal snippet * Update reply-xcm.ts * Remember to add import * Update Copy the Call Data * Explain a Port in Chopsticks Config * Improve "Enable Logging and Wasm Override" Clarity * Enhance "Replay the XCM" Section * Expand "Dry Run the XCM" Explanations * Move Page Location * Fix indentations * Fix format * Use polkadot-labs * Optimise imports * Keep code consistent * Use emoji * Update tutorials/interoperability/replay-and-dry-run-xcms.md Co-authored-by: Francisco Aguirre <[email protected]> * Add papi console * Default to use release --------- Co-authored-by: Francisco Aguirre <[email protected]> Co-authored-by: Nicolás Hussein <[email protected]>
1 parent eea5a67 commit e1cdea5

File tree

9 files changed

+990
-0
lines changed

9 files changed

+990
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Binary, createClient, Enum } from "polkadot-api";
2+
import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
3+
import { getWsProvider } from "polkadot-api/ws-provider/web";
4+
import { assetHub } from "@polkadot-api/descriptors";
5+
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
6+
import { DEV_PHRASE, entropyToMiniSecret, mnemonicToEntropy, ss58Address } from "@polkadot-labs/hdkd-helpers";
7+
8+
const XCM_VERSION = 5;
9+
10+
async function main() {
11+
const provider = withPolkadotSdkCompat(getWsProvider("ws://localhost:8000"));
12+
const client = createClient(provider);
13+
const api = client.getTypedApi(assetHub);
14+
15+
const entropy = mnemonicToEntropy(DEV_PHRASE);
16+
const miniSecret = entropyToMiniSecret(entropy);
17+
const derive = sr25519CreateDerive(miniSecret);
18+
const alice = derive("//Alice");
19+
const aliceAddress = ss58Address(alice.publicKey);
20+
21+
const callData = Binary.fromHex(
22+
"0x1f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000"
23+
);
24+
const tx: any = await api.txFromCallData(callData);
25+
const origin = Enum("system", Enum("Signed", aliceAddress));
26+
const dryRunResult: any = await api.apis.DryRunApi.dry_run_call(origin, tx.decodedCall, XCM_VERSION);
27+
console.dir(dryRunResult.value, { depth: null });
28+
29+
client.destroy();
30+
}
31+
32+
main().catch(console.error);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<div class="termynal" data-termynal>
2+
<span data-ty="input">Dry run result (failure):</span>
3+
<span data-ty="progress"></span>
4+
<span data-ty>execution_result: {</span>
5+
<span data-ty> success: false,</span>
6+
<span data-ty> value: {</span>
7+
<span data-ty> post_info: { ... },</span>
8+
<span data-ty> error: {</span>
9+
<span data-ty> type: 'Module',</span>
10+
<span data-ty> value: {</span>
11+
<span data-ty> type: 'PolkadotXcm',</span>
12+
<span data-ty> value: { type: 'LocalExecutionIncomplete', value: undefined }</span>
13+
<span data-ty> }</span>
14+
<span data-ty> }</span>
15+
<span data-ty> }</span>
16+
<span data-ty>},</span>
17+
<span data-ty>emitted_events: [],</span>
18+
<span data-ty>local_xcm: undefined,</span>
19+
<span data-ty>forwarded_xcms: []</span>
20+
</div>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<div class="termynal" data-termynal>
2+
<span data-ty="input">Dry run result (success):</span>
3+
<span data-ty="progress"></span>
4+
<span data-ty>execution_result: {</span>
5+
<span data-ty> success: true,</span>
6+
<span data-ty> value: { ... }</span>
7+
<span data-ty>},</span>
8+
<span data-ty>emitted_events: [ ... ],</span>
9+
<span data-ty>local_xcm: { ... },</span>
10+
<span data-ty>forwarded_xcms: [ ... ]</span>
11+
</div>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<div class="termynal" data-termynal>
2+
<span data-ty>[09:29:14.988] INFO: Polkadot Asset Hub RPC listening on http://[::]:8000 and ws://[::]:8000</span>
3+
<span data-ty>[09:29:14.988] INFO: Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/acala.yml</span>
4+
<span data-ty>[09:29:15.984] INFO: Acala RPC listening on http://[::]:8001 and ws://[::]:8001</span>
5+
<span data-ty>[09:29:15.990] INFO (xcm): Connected parachains [1000,2000]</span>
6+
<span data-ty>[09:29:15.990] INFO: Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot.yml</span>
7+
<span data-ty>[09:29:16.927] INFO: Polkadot RPC listening on http://[::]:8002 and ws://[::]:8002</span>
8+
<span data-ty>[09:29:16.984] INFO (xcm): Connected relaychain 'Polkadot' with parachain 'Polkadot Asset Hub'</span>
9+
<span data-ty>[09:29:17.028] INFO (xcm): Connected relaychain 'Polkadot' with parachain 'Acala'</span>
10+
</div>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<div class="termynal" data-termynal>
2+
<span data-ty>Executing XCM: {</span>
3+
<span data-ty> "type": "PolkadotXcm",</span>
4+
<span data-ty> "value": {</span>
5+
<span data-ty> "type": "limited_reserve_transfer_assets",</span>
6+
<span data-ty> "value": {</span>
7+
<span data-ty> "dest": { ... },</span>
8+
<span data-ty> "beneficiary": { ... },</span>
9+
<span data-ty> "assets": { ... },</span>
10+
<span data-ty> "fee_asset_item": 0,</span>
11+
<span data-ty> "weight_limit": {</span>
12+
<span data-ty> "type": "Unlimited"</span>
13+
<span data-ty> }</span>
14+
<span data-ty> }</span>
15+
<span data-ty> }</span>
16+
<span data-ty>}</span>
17+
<span data-ty>📦 Included in block #9079592: 0x227a11c64f6051ba2e090a13abd17e5f7581640a80f6c03fc2d43fac66ab7949</span>
18+
<span data-ty>📣 Event: Balances { "type": "Upgraded", "value": { ... } }</span>
19+
<span data-ty>📣 Event: Balances { "type": "Withdraw", "value": { ... } }</span>
20+
<span data-ty>📣 Event: Assets { "type": "Transferred", "value": { ... } }</span>
21+
<span data-ty>📣 Event: PolkadotXcm { "type": "Attempted", "value": { ... } }</span>
22+
<span data-ty>📣 Event: Balances { "type": "Burned", "value": { ... } }</span>
23+
<span data-ty>📣 Event: Balances { "type": "Minted", "value": { ... } }</span>
24+
<span data-ty>📣 Event: PolkadotXcm { "type": "FeesPaid", "value": { ... } }</span>
25+
<span data-ty>📣 Event: XcmpQueue { "type": "XcmpMessageSent", "value": { ... } }</span>
26+
<span data-ty>📣 Event: PolkadotXcm { "type": "Sent", "value": { ... } }</span>
27+
<span data-ty>📣 Event: Balances { "type": "Deposit", "value": { ... } }</span>
28+
<span data-ty>📣 Event: TransactionPayment { "type": "TransactionFeePaid", "value": { ... } }</span>
29+
<span data-ty>📣 Event: System { "type": "ExtrinsicSuccess", "value": { ... } }</span>
30+
<span data-ty>✅ Process completed, exiting...</span>
31+
</div>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Binary, createClient, Transaction } from "polkadot-api";
2+
import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
3+
import { getPolkadotSigner } from "polkadot-api/signer";
4+
import { getWsProvider } from "polkadot-api/ws-provider/web";
5+
import { assetHub } from "@polkadot-api/descriptors";
6+
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
7+
import { DEV_PHRASE, entropyToMiniSecret, mnemonicToEntropy } from "@polkadot-labs/hdkd-helpers";
8+
9+
const toHuman = (_key: any, value: any) => {
10+
if (typeof value === "bigint") {
11+
return Number(value);
12+
}
13+
14+
if (value && typeof value === "object" && typeof value.asHex === "function") {
15+
return value.asHex();
16+
}
17+
18+
return value;
19+
};
20+
21+
function getSigner() {
22+
const entropy = mnemonicToEntropy(DEV_PHRASE);
23+
const miniSecret = entropyToMiniSecret(entropy);
24+
const derive = sr25519CreateDerive(miniSecret);
25+
const alice = derive("//Alice");
26+
27+
return getPolkadotSigner(alice.publicKey, "Sr25519", alice.sign);
28+
}
29+
30+
async function main() {
31+
const provider = withPolkadotSdkCompat(getWsProvider("ws://localhost:8000"));
32+
const client = createClient(provider);
33+
const api = client.getTypedApi(assetHub);
34+
const aliceSigner = getSigner();
35+
36+
const callData = Binary.fromHex(
37+
"0x1f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000"
38+
);
39+
const tx: Transaction<any, string, string, any> = await api.txFromCallData(callData);
40+
console.log("👀 Executing XCM:", JSON.stringify(tx.decodedCall, toHuman, 2));
41+
42+
await new Promise<void>((resolve) => {
43+
const subscription = tx.signSubmitAndWatch(aliceSigner).subscribe((ev) => {
44+
if (ev.type === "finalized" || (ev.type === "txBestBlocksState" && ev.found)) {
45+
console.log(`📦 Included in block #${ev.block.number}: ${ev.block.hash}`);
46+
47+
if (!ev.ok) {
48+
const dispatchError = ev.dispatchError;
49+
if (dispatchError.type === "Module") {
50+
const modErr: any = dispatchError.value;
51+
console.error(`❌ Dispatch error in module: ${modErr.type}${modErr.value?.type}`);
52+
} else {
53+
console.error("❌ Dispatch error:", JSON.stringify(dispatchError, toHuman, 2));
54+
}
55+
}
56+
57+
for (const event of ev.events) {
58+
console.log("📣 Event:", event.type, JSON.stringify(event.value, toHuman, 2));
59+
}
60+
61+
console.log("✅ Process completed, exiting...");
62+
subscription.unsubscribe();
63+
resolve();
64+
}
65+
});
66+
});
67+
68+
client.destroy();
69+
}
70+
71+
main().catch(console.error);

0 commit comments

Comments
 (0)