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

Add XCM Dry Run and Location to Account Runtime Calls #1010

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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,25 @@
import { ApiPromise, WsProvider } from '@polkadot/api';

const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });

// Define the multilocation parameter
const multilocation = {
V4: {
parents: 1,
interior: 'Here',
},
};

// Query the locationToAccountApi using convertLocation method
const result =
await api.call.locationToAccountApi.convertLocation(multilocation);
console.log('Conversion result:', result.toHuman());

// Disconnect the API
await api.disconnect();
};

main().catch(console.error);
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Ok: {
executionResult: {
Ok: {
actualWeight: {
refTime: 7,301,734,000
proofSize: 20,928
}
paysFee: Yes
}
}
emittedEvents: [
{
method: Burned
section: balances
index: 0x030b
data: {
who: 0x88bcE0b038eFFa09e58fE6d24fDe4b5Af21aa798
amount: 100,000,000,000,000,000
}
}
{
method: Minted
section: balances
index: 0x030a
data: {
who: 0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0
amount: 100,000,000,000,000,000
}
}
{
method: Attempted
section: polkadotXcm
index: 0x1c00
data: {
outcome: {
Complete: {
used: {
refTime: 7,250,000,000
proofSize: 19,374
}
}
}
}
}
] // Additional events returned here
// Omitted for clarity
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ApiPromise, WsProvider } from '@polkadot/api';
import { hexToU8a } from '@polkadot/util';

const main = async () => {
try {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });

console.log('Connected to the API. Preparing dry run call...');

// Create a test account (you should replace this with an actual account)
const testAccount = api.createType(
'AccountId20',
'0x88bcE0b038eFFa09e58fE6d24fDe4b5Af21aa798'
);

// The call data (replace with your actual call data)
const callData =
'0x1c030408000400010403001300008a5d784563010d010204000103003cd0a705a2dc65e5b1e1205896baa2be8a07c6e007803822b001ba2e0100'; // Your hex-encoded call data

// Convert hex to Uint8Array
const callDataU8a = hexToU8a(callData);

// Perform the dry run call
const result = await api.call.dryRunApi.dryRunCall(
{ system: { Signed: testAccount } }, // origin
callDataU8a // call
);

console.log('Dry run result:', result.toHuman());

// Disconnect the API
await api.disconnect();
console.log('Disconnected from the API.');
} catch (error) {
console.error('An error occurred:', error);
}
};

main().catch(console.error);
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Ok: {
executionResult: {
Complete: {
used: {
refTime: 76,473,048,000
proofSize: 222,483
}
}
}
emittedEvents: [
{
method: Burned
section: assets
index: 0x1d03
data: {
assetId: 42,259,045,809,535,163,221,576,417,993,425,387,648
owner: 0x506172656E740000000000000000000000000000
balance: 1,000,000,000,000
}
}
{
method: NewAccount
section: system
index: 0x0003
data: {
account: 0x1Ccc29B6C837be6A0C03d544b5Aa8580f9fb9489
}
}
{
method: Issued
section: assets
index: 0x1d01
data: {
assetId: 42,259,045,809,535,163,221,576,417,993,425,387,648
owner: 0x1Ccc29B6C837be6A0C03d544b5Aa8580f9fb9489
amount: 959,944,978,002
}
}
{
method: Issued
section: assets
index: 0x1d01
data: {
assetId: 42,259,045,809,535,163,221,576,417,993,425,387,648
owner: 0x6d6F646c70632f74727372790000000000000000
amount: 40,055,021,998
}
}
]
forwardedXcms: [
[
{
V4: {
parents: 1
interior: Here
}
}
[]
] // Additional events returned here
// Omitted for clarity
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { ApiPromise, WsProvider } from '@polkadot/api';

const main = async () => {
try {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
console.log('Connected to the API. Preparing dry run XCM call...');

// Define the origin
const origin = { V4: { parents: 1, interior: 'Here' } };

const assetMultiLocation = {
parents: 0,
interior: { X1: { PalletInstance: 3 } },
}; // The asset's location (adjust PalletInstance as needed)

const amountToSend = 1000000000000; // Adjust this value as needed

const message = {
V4: [
{
WithdrawAsset: [
{
id: { parents: 1, interior: 'Here' },
fun: { Fungible: amountToSend },
},
],
},
{
BuyExecution: {
fees: {
id: { parents: 1, interior: 'Here' },
fun: { Fungible: amountToSend },
},
weightLimit: { Unlimited: null },
},
},
{
ClearOrigin: null,
Copy link
Contributor

Choose a reason for hiding this comment

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

Im curious as to this XCM message that you put here. There is no Deposit Asset so this would actually result in AssetsTrapped right?

},
],
};

// Perform the dry run XCM call
const result = await api.call.dryRunApi.dryRunXcm(origin, message);

// Use JSON.stringify for better output formatting
console.log(
'Dry run XCM result:',
JSON.stringify(result.toJSON(), null, 2)
);

// Disconnect the API
await api.disconnect();
console.log('Disconnected from the API.');
} catch (error) {
console.error('An error occurred:', error);
}
};

main().catch(console.error);
26 changes: 26 additions & 0 deletions builders/interoperability/xcm/core-concepts/multilocations.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,29 @@ To target another parachain (for example, a parachain that has an ID of 1234) fr
},
};
```

### Location to Account API {: #location-to-account-api }

The Location to Account API is an easy way to convert a multilocation into an `AccountID20` address. The Location to Account API can be accessed from the [Runtime Calls](https://polkadot.js.org/apps/#/runtime){target=\_blank} tab of the **Developer** section of Polkadot.js Apps. The `convertLocation` method of the Location to Account API takes a multilocation as a parameter and returns an `AccountID20` address.

```javascript
// Query the locationToAccountApi using convertLocation method
const result =
await api.call.locationToAccountApi.convertLocation(multilocation);
console.log('Conversion result:', result.toHuman());
```

You can view the complete script below.

??? code "View the complete script"

```js
--8<-- 'code/builders/interoperability/xcm/core-concepts/location-to-account.js'
```

The method will return the `AccountID20` address corresponding to the provided multilocation as follows:

```bash
Conversion result: { Ok: '0x506172656E740000000000000000000000000000' }
```

69 changes: 69 additions & 0 deletions builders/interoperability/xcm/send-execute-xcm.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,75 @@ Now that you have the values for each of the parameters, you can write the scrip

Once the transaction is processed, the 0.1 DEV tokens should be withdrawn from Alice's account along with the associated XCM fees, and the destination account should have received 0.1 DEV tokens in their account. A `polkadotXcm.Attempted` event will be emitted with the outcome.


### Test an XCM Message with the XCM Dry Run API {: #test-an-xcm-message-with-the-dry-run-api }

The XCM Dry Run API is an easy and convenient way to test the integrity of your XCM message without incurring any transaction fees. The XCM Dry Run API can be accessed from the [Runtime Calls](https://polkadot.js.org/apps/#/runtime){target=\_blank} tab of the **Developer** section of Polkadot.js Apps.

#### Dry Run Call API Method {: #dry-run-call-api-method }
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this is not XCM-specific tho right? This section works for any call outside of XCM. So maybe moving this to another section is better? Somewhere in the Substrate API for Moonbeam? Maybe even a new section on testing or something.

We should discuss


This method takes as a parameter the origin and the call data and returns an execution result, actual weight, and event data.

```javascript
const testAccount = api.createType(
'AccountId20',
'0x88bcE0b038eFFa09e58fE6d24fDe4b5Af21aa798'
);
const callData =
'0x1c030408000400010403001300008a5d784563010d010204000103003cd0a705a2dc65e5b1e1205896baa2be8a07c6e007803822b001ba2e0100';
const callDataU8a = hexToU8a(callData);

const result = await api.call.dryRunApi.dryRunCall(
{ system: { Signed: testAccount } },
callDataU8a
);
```

??? code "View the complete script"

```js
--8<-- 'code/builders/interoperability/xcm/send-execute-xcm/dry-run/dry-run-call.js'
```

Upon calling the XCM Dry Run API, the method will tell you whether the call would be successful and returns the event data that would be emitted if the XCM were to be actually submitted on chain. You can view the initial output of the `dryRunCall` below.

??? code "View the complete output"

```json
--8<-- 'code/builders/interoperability/xcm/send-execute-xcm/dry-run/dry-run-call-return-data.json'
```

#### Dry Run XCM API Method {: #dry-run-xcm-api-method }
Copy link
Contributor

Choose a reason for hiding this comment

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

This is relevant for this section, but unsure if being under Execute is the right call? Maybe we can rename the section to Send, Execute and Test XCM and add this as a separate ## section?

Wdyt?


The `dryRunXCM` method of the XCM Dry Run API takes a full XCM message as a parameter instead of an encoded call, as well as the origin of the message.

`dryRunXCM` takes as a parameter the origin and the XCM message and returns an execution result, actual weight, and event data.

```javascript
// Define the origin
const origin = { V4: { parents: 1, interior: 'Here' } };

const message = []; // Insert XCM Message Here

// Perform the dry run XCM call
const result = await api.call.dryRunApi.dryRunXcm(origin, message);
```

??? code "View the complete script"

```js
--8<-- 'code/builders/interoperability/xcm/send-execute-xcm/dry-run/dry-run-xcm.js'
```

Upon calling the XCM Dry Run API, the method will tell you whether the call would be successful and returns the event data that would be emitted if the XCM were to be actually submitted on chain. You can view the initial output of the `dryRunXCM` below.

??? code "View the complete output"

```json
--8<-- 'code/builders/interoperability/xcm/send-execute-xcm/dry-run/dry-run-xcm-return-data.json'
```


### Execute an XCM Message with the XCM Utilities Precompile {: #execute-xcm-utils-precompile }

In this section, you'll use the `xcmExecute` function of the [XCM Utilities Precompile](/builders/interoperability/xcm/xcm-utils/){target=\_blank}, which is only supported on Moonbase Alpha, to execute an XCM message locally. The XCM Utilities Precompile is located at the following address:
Expand Down
Loading