Multilocations¶
Introduction¶
A multilocation defines a specific point in the entire relay chain/parachain ecosystem relative to a given origin. It can be used to target a specific parachain, asset, account, or even a pallet inside a parachain.
Multilocations follow a hierarchical structure, in which some locations are encapsulated within others. For example, a relay chain encapsulates all of the parachains that are connected to it. Similarly, a parachain encapsulates all of the pallets, accounts, and assets that exist within it.
Defining a Multilocation¶
A multilocation contains two parameters:
parents
- refers to how many "hops" up into a parent blockchain you need to take from a given origin. From the perspective of a parachain within the relay chain ecosystem, there can only be one parent, so the value forparents
can only ever be0
to represent the parachain or1
to represent the relay chain. When defining universal locations that consider other consensus systems like Ethereum,parents
can have higher valuesinterior
- refers to how many fields you need to define the target point. From the relay chain, you can drill down to target a specific parachain, or account, asset, or pallet on that parachain. Since this downward movement can be more complex, Junctions are used to represent the steps needed to reach the target location and are defined byXN
, whereN
is the number of Junctions required. If no Junctions are required to define the target point, its value would beHere
as opposed toX1
For example,if you are targeting the relay chain specifically, you'll use Here
since you aren't defining an account on the relay chain, a parachain, or a specific point within a parachain.
On the flip side, if you're targeting an account on the relay chain, or a parachain, or a specific point within a parachain, you'll use one or more Junctions, as needed.
Junctions¶
A Junction can be any of the following:
-
Parachain
- describes a parachain using the parachain's ID{ Parachain: INSERT_PARACHAIN_ID }
-
AccountId32
- describes a 32-byte Substrate-style account. Accepts an optionalnetwork
parameter, which can be one of the following:Any
,Named
,Polkadot
, orKusama
{ AccountId32: { id: INSERT_ADDRESS, network: INSERT_NETWORK } }
-
AccountIndex64
- describes a 64-bit (8-byte) index for an account. Accepts an optionalnetwork
parameter, which can be one of the following:Any
,Named
,Polkadot
, orKusama
{ AccountIndex64: { index: INSERT_ACCOUNT_INDEX, network: INSERT_NETWORK } }
-
AccountKey20
- describes a 20-byte Ethereum-style account, as is used in Moonbeam. Accepts an optionalnetwork
parameter, which can be one of the following:Any
,Named
,Polkadot
, orKusama
{ AccountKey20: { key: INSERT_ADDRESS, network: INSERT_NETWORK } }
-
PalletInstance
- describes the index of a pallet on the target chain{ PalletInstance: INSERT_PALLET_INSTANCE_INDEX }
-
GeneralIndex
- describes a nondescript index that can be used to target data stored in a key-value format{ GeneralIndex: INSERT_GENERAL_INDEX }
-
GeneralKey
- describes a nondescript key that can be used to target more complex data structures. This requires you to specify thedata
and thelength
of the data{ GeneralKey: { length: INSERT_LENGTH_OF_DATA, data: [INSERT_DATA] } }
-
OnlyChild
- describes the child of a location if there is only a one-to-one relation between the parent and child. This is currently not used except as a fallback when deriving context -
Plurality
- describes multiple elements that meet specific conditions or share common characteristics. This requires you to specify the Body ID and the Body Part that the Junction represents{ Plurality: { id: INSERT_BODY_ID, part: INSERT_BODY_PART } }
When using Junctions, you'll use XN
, where N
is the number of Junctions required to reach the target location. For example, if you're targeting an account on Moonbeam from a parachain, parents
needs to be set to 1
, and you'll need to define two Junctions, the Parachain
and the AccountKey20
, so you'll use X2
, which is an array that will contain each Junction:
{
parents: 1,
interior: {
X2: [
{ Parachain: 2004 },
{ AccountKey20: { key: 'INSERT_MOONBEAM_ADDRESS' } },
],
},
};
Example Multilocations¶
Target Moonbeam from Another Parachain¶
To target a Moonbeam-based chain from another parachain, you would use the following multilocation:
{
parents: 1,
interior: {
X1: [{ Parachain: 2004 }],
},
};
{
parents: 1,
interior: {
X1: [{ Parachain: 2023 }],
},
};
{
parents: 1,
interior: {
X1: [{ Parachain: 1000 }],
},
};
Target an Account on Moonbeam from Another Parachain¶
To target a specific account on a Moonbeam-based chain from another parachain, you would use the following multilocation:
{
parents: 1,
interior: {
X2: [
{ Parachain: 2004 },
{ AccountKey20: { key: 'INSERT_MOONBEAM_ADDRESS' } },
],
},
};
{
parents: 1,
interior: {
X2: [
{ Parachain: 2023 },
{ AccountKey20: { key: 'INSERT_MOONBEAM_ADDRESS' } },
],
},
};
{
parents: 1,
interior: {
X2: [
{ Parachain: 1000 },
{ AccountKey20: { key: 'INSERT_MOONBEAM_ADDRESS' } },
],
},
};
Target Moonbeam's Native Asset from Another Parachain¶
To target the native asset of a Moonbeam-based chain from another parachain, you would use the following multilocation:
{
parents: 1,
interior: {
X2: [
{ Parachain: 2004 },
{ PalletInstance: 10 }, // Index of the Balances Pallet on Moonbeam
],
},
};
{
parents: 1,
interior: {
X2: [
{ Parachain: 2023 },
{ PalletInstance: 10 }, // Index of the Balances Pallet on Moonriver
],
},
};
{
parents: 1,
interior: {
X2: [
{ Parachain: 1000 },
{ PalletInstance: 3 }, // Index of the Balances Pallet on Moonbase Alpha
],
},
};
Target Moonbeam from the Relay Chain¶
To target a Moonbeam-based chain from the relay chain, you would use the following multilocation:
{
parents: 0,
interior: {
X1: [{ Parachain: 2004 }],
},
};
{
parents: 0,
interior: {
X1: [{ Parachain: 2023 }],
},
};
{
parents: 0,
interior: {
X1: [{ Parachain: 1000 }],
},
};
Target the Relay Chain from Moonbeam¶
To target the relay chain from a Moonbeam-based chain, you would use the following multilocation:
{
parents: 1,
interior: Here,
};
{
parents: 1,
interior: Here,
};
{
parents: 1,
interior: Here,
};
Target an Account on the Relay Chain from Moonbeam¶
To target a specific account on the relay chain, you would use the following multilocation:
{
parents: 1,
interior: { X1: { AccountId32: { id: INSERT_RELAY_ADDRESS } } },
};
{
parents: 1,
interior: { X1: { AccountId32: { id: INSERT_RELAY_ADDRESS } } },
};
{
parents: 1,
interior: { X1: { AccountId32: { id: INSERT_RELAY_ADDRESS } } },
};
Target Another Parachain from Moonbeam¶
To target another parachain (for example, a parachain that has an ID of 1234) from Moonbeam, you would use the following multilocation:
{
parents: 1,
interior: {
X1: [{ Parachain: 1234 }],
},
};
{
parents: 1,
interior: {
X1: [{ Parachain: 1234 }],
},
};
{
parents: 1,
interior: {
X1: [{ Parachain: 1234 }],
},
};
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 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.
// 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.
View the complete script
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);
The method will return the AccountID20
address corresponding to the provided multilocation as follows:
Conversion result: { Ok: '0x506172656E740000000000000000000000000000' }
| Created: October 28, 2023