发送和执行XCM消息¶
概览¶
XCM消息由一系列的指令组成,由跨共识虚拟机(XCVM)执行。这些指令的组合会执行预定的操作,例如跨链Token转移。您可以通过组合各种XCM指令创建自定义XCM消息。
X-Tokens和XCM Transactor等Pallet提供带有一组预定义的XCM指令的函数,用于发送XC-20s或通过XCM在其他链上远程执行。然而,要更好地了解组合不同XCM指令的结果,您可以在Moonbeam上本地构建和执行自定义XCM消息。你也可以发送自定义XCM消息至其他链(这将以DescendOrigin
指令开始)。但是,要成功执行XCM消息,目标链需要理解这些指令。
要执行或发送自定义XCM消息,你可以直接使用Polkadot XCM Pallet或者尝试通过带有XCM-Utilities预编译的以太坊API。在本教程中,您将学习如何使用这两种方式在Moonbase Alpha上本地执行和发送自定义的XCM消息。
本教程假设您已熟悉XCM基本概念,例如基本的XCM专业术语和XCM指令。您可以访问XCM概览文档获取更多信息。
Polkadot XCM Pallet接口¶
Extrinsics¶
Polkadot XCM Pallet包含以下相关extrinsics(函数):
- execute(message, maxWeight) - 仅支持Moonbase Alpha - 给定SCALE编码的XCM版本化的XCM消息和要消耗的最大权重,执行自定义XCM消息
- send(dest, message) - 仅支持Moonbase Alpha - 给定要发送消息的目标链的multilocation和要发送的SCALE编码的XCM版本化的XCM消息,发送自定义消息。要成功执行XCM消息,目标链需要理解消息中的指令
存储函数¶
Polkadot XCM Pallet包含以下相关只读存储函数:
- assetTraps(Option
) - 给定 MultiAssets
对的Blake2-256哈希,返回中断资产的现有次数。如果哈希出现omitted的错误,则返回所有中断资产 - palletVersion() - 提供正在使用的Polkadot XCM Pallet的版本
查看先决条件¶
开始操作本教程之前,请先准备以下内容:
- 您的账户必须拥有一些DEV Token 您可以每24小时一次从Moonbase Alpha水龙头上获取DEV代币以在Moonbase Alpha上进行测试
本地执行XCM消息¶
这一部分涵盖了通过两种不同的方法来构建要在本地(即在Moonbeam中)执行的自定义XCM消息:Polkadot XCM Pallet的execute
函数和XCM-Utilities预编译的xcmExecute
函数。此功能为您提供了试验不同的XCM指令并直接查看这些试验结果的平台。这也有助于确定与Moonbeam上给定XCM消息相关联的费用。
在以下示例中,您将在Moonbase Alpha上从一个账户转移DEV Token至另一个账户。为此,您需要构建一个XCM消息以包含以下XCM指令,这些指令将在本地执行(在本示例中为Moonbase Alpha):
WithdrawAsset
- 移除资产并将其放入暂存处DepositAsset
- 将资产从暂存处取出并存入等值资产至接收方账户中
注意事项
通常情况下,当您发送XCM消息跨链至目标链时,需要用到BuyExecution
指令用于支付远程执行。但是,对于本地执行,此指令非必要,因为您已通过extrinsic调用支付费用。
使用Polkadot.js API执行XCM消息¶
在本示例中,您将使用Polkadot.js API在Moonbase Alpha上本地执行自定义XCM消息,以直接与Polkadot XCM Pallet交互。
Polkadot XCM Pallet的execute
函数接受两个参数:message
和maxWeight
。您可以执行以下步骤组装这些参数:
-
构建
WithdrawAsset
指令,其将要求您定义:- Moonbase Alpha上DEV token的multilocation
- 要转移的DEV token数量
const instr1 = { WithdrawAsset: [ { id: { Concrete: { parents: 0, interior: { X1: { PalletInstance: 3 } } } }, fun: { Fungible: 100000000000000000n }, // 0.1 DEV }, ], };
-
构建
DepositAsset
指令,其将要求您定义:- DEV token的多资产标识符。您可以使用允许通配符匹配的
WildMultiAsset
format来识别资产 - Moonbase Alpha上接收账户的multilocation
const instr2 = { DepositAsset: { assets: { Wild: { AllCounted: 1 } }, beneficiary: { parents: 0, interior: { X1: { AccountKey20: { key: moonbeamAccount, }, }, }, }, }, };
- DEV token的多资产标识符。您可以使用允许通配符匹配的
-
将XCM指令合并至版本化的XCM消息中:
const message = { V3: [instr1, instr2] };
-
指定
maxWeight
,其中包括您需要定义的refTime
和proofSize
值refTime
是可用于执行的计算时间量。在本示例中,您可以设置为400000000n
proofSize
是可使用的存储量(以字节为单位)。在本示例中,您可以设置为14484n
const maxWeight = { refTime: 400000000n, proofSize: 14484n } ;
现在,您已经有了每个参数的值,您可以为交易编写脚本了。为此,您需要执行以下步骤:
-
提供调用的输入数据,这包含:
- 用于创建提供商的Moonbase Alpha端点URL
execute
函数的每个参数的值
-
创建一个用于发送交易的Keyring实例
- 创建Polkadot.js API提供商
- 使用
message
和maxWeight
值制作polkadotXcm.execute
extrinsic - 使用
signAndSend
extrinsic和在第二个步骤创建的Keyring实例发送交易
请记住
本教程的操作仅用于演示目的,请勿将您的私钥存储至JavaScript文档中。
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; // Version 9.13.6
// 1. Provide input data
const providerWsURL = 'wss://wss.api.moonbase.moonbeam.network';
const privateKey = 'INSERT_PRIVATE_KEY';
const moonbeamAccount = 'INSERT_ADDRESS';
const instr1 = {
WithdrawAsset: [
{
id: { Concrete: { parents: 0, interior: { X1: { PalletInstance: 3 } } } },
fun: { Fungible: 100000000000000000n },
},
],
};
const instr2 = {
DepositAsset: {
assets: { Wild: { AllCounted: 1 } },
beneficiary: {
parents: 0,
interior: {
X1: {
AccountKey20: {
key: moonbeamAccount,
},
},
},
},
},
};
const message = { V3: [instr1, instr2] };
const maxWeight = { refTime: 400000000n, proofSize: 14484n };
// 2. Create Keyring instance
const keyring = new Keyring({ type: 'ethereum' });
const alice = keyring.addFromUri(privateKey);
const executeXcmMessage = async () => {
// 3. Create Substrate API provider
const substrateProvider = new WsProvider(providerWsURL);
const api = await ApiPromise.create({ provider: substrateProvider });
// 4. Craft the extrinsic
const tx = api.tx.polkadotXcm.execute(message, maxWeight);
// 5. Send the transaction
const txHash = await tx.signAndSend(alice);
console.log(`Submitted with hash ${txHash}`);
api.disconnect();
};
executeXcmMessage();
注意事项
您可以使用以下编码的调用数据在Polkadot.js Apps上查看上述脚本的示例,该脚本将1个DEV发送给Moonbeam上Bob的账户:0x1c03030800040000010403001300008a5d784563010d010204000103003cd0a705a2dc65e5b1e1205896baa2be8a07c6e002105e5f51e2
。
交易处理后,0.1 DEV Token和相关联的XCM费用从Alice的账户提取,Bob将在其账户收到0.1 DEV Token。polkadotXcm.Attempted
事件将与结果一同发出。
使用XCM Utilities预编译执行XCM交易¶
在这一部分,您将使用XCM Utilities预编译的xcmExecute
函数(该函数仅支持Moonbase Alpha)以本地执行XCM消息。XCM Utilities预编译位于以下地址:
0x000000000000000000000000000000000000080C
在Hood下,XCM Utilities预编译的xcmExecute
函数调用Polkadot XCM Pallet的execute
函数,即用Rust编码的Substrate pallet。使用XCM Utilities预编译调用xcmExecute
的好处是您可以通过以太坊API完成此操作并使用Ethers.js等以太坊库。
xcmExecute
函数接受两个参数:要执行SCALE编码的版本化XCM消息和要消耗的最大权重。
首先,您将了解如何生成编码的调用数据,然后您将了解如何使用编码的调用数据与 XCM Utilities预编译交互。
生成XCM消息的编码调用数据¶
要获取XCM消息的编码调用数据,您可以创建一个类似于在使用Polkadot.js API执行XCM消息部分创建的脚本。您将构建消息来获取编码的调用数据,而不是构建消息并发送交易。为此,您需要执行以下步骤:
-
提供调用的输入数据,这包含:
- 用于创建提供商的Moonbase Alpha端点URL
- 使用Polkadot.js API执行XCM消息部分定义的
execute
函数的每个参数的值
-
创建Polkadot.js API提供商
- 使用
message
和maxWeight
值制作polkadotXcm.execute
extrinsic - 使用交易获取编码的调用数据
整个脚本如下所示:
import { ApiPromise, WsProvider } from '@polkadot/api'; // Version 9.13.6
// 1. Provide input data
const moonbeamAccount = 'INSERT_ADDRESS'
const providerWsURL = 'wss://wss.api.moonbase.moonbeam.network';
const instr1 = {
WithdrawAsset: [
{
id: { Concrete: { parents: 0, interior: { X1: { PalletInstance: 3 } } } },
fun: { Fungible: 100000000000000000n },
},
],
};
const instr2 = {
DepositAsset: {
assets: { Wild: { AllCounted: 1 } },
beneficiary: {
parents: 0,
interior: {
X1: {
AccountKey20: {
key: moonbeamAccount,
},
},
},
},
},
};
const message = { V3: [instr1, instr2] };
const maxWeight = { refTime: 400000000n, proofSize: 14484n };
const getEncodedXcmMessage = async () => {
// 2. Create Substrate API provider
const substrateProvider = new WsProvider(providerWsURL);
const api = await ApiPromise.create({ provider: substrateProvider });
// 3. Craft the extrinsic
const tx = api.tx.polkadotXcm.execute(message, maxWeight);
// 4. Get the encoded XCM message
// By using index 0, you'll get just the encoded XCM message.
// If you wanted to get the maxWeight, you could use index 1
const encodedXcmMessage = tx.args[0].toHex()
console.log(`Encoded Calldata for XCM Message: ${encodedXcmMessage}`);
api.disconnect();
}
getEncodedXcmMessage();
执行XCM消息¶
现在,您已拥有SCALE编码的XCM消息,您可以使用以下代码片段通过您选择的以太坊库以编程方式调用XCM-Utilities预编译的xcmExecute
函数:
- 创建提供商和签署者
- 创建用于交互的XCM Utilities Precompile的实例
- 定义
xcmExecute
函数所需的参数,这些参数将是XCM消息的编码调用数据以及用于执行消息的最大权重。您可以将maxWeight
设置为400000000n
,它对应于refTime
。proofSize
将自动设置为默认值,即64KB - 执行XCM消息
请记住
请勿将您的私钥存储至JavaScript或Python文件中。
import ABI from './xcmUtilsABI.js'; // Import the XCM Utilities Precompile ABI
import { ethers } from 'ethers'; // Import Ethers library
const privateKey = 'INSERT_YOUR_PRIVATE_KEY';
const xcmUtilsAddress = '0x000000000000000000000000000000000000080C';
/* Create Ethers provider and signer */
const provider = new ethers.JsonRpcProvider(
'https://rpc.api.moonbase.moonbeam.network'
);
const signer = new ethers.Wallet(privateKey, provider);
/* Create contract instance of the XCM Utilities Precompile */
const xcmUtils = new ethers.Contract(
xcmUtilsAddress,
ABI,
signer
);
const executeXcmMessageLocally = async () => {
/* Define parameters required for the xcmExecute function */
const encodedCalldata = 'INSERT_ENCODED_CALLDATA';
const maxWeight = '400000000';
/* Execute the custom XCM message */
const tx = await xcmUtils.xcmExecute(encodedCalldata, maxWeight);
await tx.wait();
console.log(`Transaction receipt: ${tx.hash}`);
};
executeXcmMessageLocally();
import ABI from './xcmUtilsABI.js'; // Import the XCM Utilities Precompile ABI
import { Web3 } from 'web3'; // Import Web3 library
const privateKey = 'INSERT_PRIVATE_KEY';
const accountFrom = web3.eth.accounts.privateKeyToAccount(privateKey).address;
const xcmUtilsAddress = '0x000000000000000000000000000000000000080C';
/* Create Web3 provider */
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network'); // Change to network of choice
/* Create contract instance of the XCM Utilities Precompile */
const xcmUtils = new web3.eth.Contract(
ABI,
xcmUtilsAddress,
{ from: accountFrom } // 'from' is necessary for gas estimation
);
const executeXcmMessageLocally = async () => {
/* Define parameters required for the xcmExecute function */
const encodedCalldata = 'INSERT_ENCODED_CALLDATA';
const maxWeight = '400000000';
/* Send the custom XCM message */
// Craft the extrinsic
const tx = await xcmUtils.methods.xcmExecute(encodedCalldata, maxWeight);
// Sign transaction
const signedTx = await web3.eth.accounts.signTransaction(
{
to: xcmUtilsAddress,
data: tx.encodeABI(),
gas: await tx.estimateGas(),
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(accountFrom),
},
privateKey
);
// Send the signed transaction
const sendTx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log(`Transaction receipt: ${sendTx.transactionHash}`);
};
executeXcmMessageLocally();
from web3 import Web3
abi = "INSERT_XCM_UTILS_ABI" # Paste or import the XCM Utils ABI
# This is for demo purposes, never store your private key in plain text
private_key = "INSERT_PRIVATE_KEY"
# The wallet address that corresponds to your private key
address = "INSERT_ADDRESS"
xcm_utils_address = "0x000000000000000000000000000000000000080C"
## Create Web3 provider ##
web3 = Web3(Web3.HTTPProvider("https://rpc.api.moonbase.moonbeam.network"))
## Create contract instance of the XCM Utilities Precompile ##
xcm_utils = web3.eth.contract(
# XCM Utilities Precompile address
address=xcm_utils_address,
abi=abi,
)
def execute_xcm_message_locally():
## Define parameters required for the xcmExecute function ##
encoded_calldata = "INSERT_ENCODED_CALLDATA"
max_weight = 400000000
## Execute the custom XCM message ##
# Craft the extrinsic
tx = xcm_utils.functions.xcmExecute(encoded_calldata, max_weight).build_transaction(
{
"from": address,
"nonce": web3.eth.get_transaction_count(address),
}
)
# Sign transaction
signedTx = web3.eth.account.sign_transaction(tx, private_key)
# Send tx
hash = web3.eth.send_raw_transaction(signedTx.rawTransaction)
receipt = web3.eth.wait_for_transaction_receipt(hash)
print(f"Transaction receipt: { receipt.transactionHash.hex() }")
execute_xcm_message_locally()
跨链发送XCM消息¶
这一部分涵盖了通过两种不同的方法来跨链发送自定义XCM消息(即从Moonbeam到目标链,如中继链):Polkadot XCM Pallet的send
函数和XCM-Utilities预编译的xcmSend
函数。
要成功执行XCM消息,目标链需要理解消息中的指令。相反,您将在目标链上看到Barrier
过滤器。为保证安全,XCM消息前会加上DecendOrigin
指令以防止XCM代表源链的主权账户执行操作。如上所述,此部分的示例仅用于演示目的。
在以下示例中,您将构建一个包含以下XCM指令的XCM消息,这些指令将在Alphanet中继链中执行:
WithdrawAsset
- 移除资产并将其放入暂存处BuyExecution
- 从暂存处获取资产以支付执行费用。支付的费用由目标链决定DepositAsset
- 将资产从暂存处取出并存入等值资产至接收方账户中
这些指令的目的是将中继链的原生资产(即Alphanet中继链的UNIT)从Moonbase Alpha转移到中继链上的一个账户。此示例仅用于演示目的,以演示如何跨链发送自定义XCM消息。 请记住,目标链需要理解消息中的指令才可执行。
使用Polkadot.js API发送XCM消息¶
在本示例中,您将使用Polkadot.js API在Moonbase Alpha上本地执行自定义XCM消息,以直接与Polkadot XCM Pallet交互。
Polkadot XCM Pallet的send
函数接受两个参数:dest
和message
。您可以执行以下步骤开始组装这些参数:
-
为
dest
构建中继链Token UNIT的multilocation:const dest = { V3: { parents: 1, interior: null } };
-
构建
WithdrawAsset
指令,这将要求您定义:- 中继链上UNIT token的multilocation
- 要提现的UNIT token数量
const instr1 = { WithdrawAsset: [ { id: { Concrete: { parents: 1, interior: null } }, fun: { Fungible: 1000000000000n }, // 1 UNIT }, ], };
-
构建
BuyExecution
指令,这将要求您定义:- 中继链上UNIT token的multilocation
- 用于执行的UNIT token数量
- 权重限制
const instr2 = { BuyExecution: [ { id: { Concrete: { parents: 1, interior: null } }, fun: { Fungible: 1000000000000n }, // 1 UNIT }, { Unlimited: null } ], };
-
构建
DepositAsset
指令,这将要求您定义:- UNIT token的多资产标识符。您可以使用允许通配符匹配的
WildMultiAsset
format来识别资产 - 中继链上接收账户的multilocation
const instr3 = { DepositAsset: { assets: { Wild: 'All' }, beneficiary: { parents: 1, interior: { X1: { AccountId32: { id: relayAccount, }, }, }, }, }, };
- UNIT token的多资产标识符。您可以使用允许通配符匹配的
-
将XCM指令合并至版本化的XCM消息中:
const message = { V3: [instr1, instr2, instr3] };
现在,您已经有了每个参数的值,您可以为交易编写脚本了。为此,您需要执行以下步骤:
-
提供调用的输入数据,这包含:
- 用于创建提供商的Moonbase Alpha端点URL
send
函数的每个参数的值
-
创建用于发送交易的Keyring实例
- 创建Polkadot.js API提供商
- 使用
dest
和message
值制作polkadotXcm.execute
extrinsic - 使用
signAndSend
extrinsic和在第二个步骤创建的Keyring实例发送交易
请记住
本教程的操作仅用于演示目的,请勿将您的私钥存储至JavaScript文档中。
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; // Version 9.13.6
import { decodeAddress } from '@polkadot/util-crypto';
// 1. Input data
const providerWsURL = 'wss://wss.api.moonbase.moonbeam.network';
// You can use the decodeAddress function to ensure that your address is properly
// decoded. If it isn't decoded, it will decode it and if it is, it will ignore it
const privateKey = 'INSERT_PRIVATE_KEY';
const relayAccount = decodeAddress('INSERT_ADDRESS');
const dest = { V3: { parents: 1, interior: null } };
const instr1 = {
WithdrawAsset: [
{
id: { Concrete: { parents: 1, interior: null } },
fun: { Fungible: 1000000000000n }, // 1 UNIT
},
],
};
const instr2 = {
BuyExecution: [
{
id: { Concrete: { parents: 1, interior: null } },
fun: { Fungible: 1000000000000n }, // 1 UNIT
},
{ Unlimited: null }
],
};
const instr3 = {
DepositAsset: {
assets: { Wild: 'All' },
beneficiary: {
parents: 1,
interior: {
X1: {
AccountId32: {
id: relayAccount,
},
},
},
},
},
};
const message = { V3: [instr1, instr2, instr3] };
// 2. Create Keyring instance
const keyring = new Keyring({ type: 'ethereum' });
const alice = keyring.addFromUri(privateKey);
const sendXcmMessage = async () => {
// 3. Create Substrate API Provider
const substrateProvider = new WsProvider(providerWsURL);
const api = await ApiPromise.create({ provider: substrateProvider });
// 4. Create the extrinsic
const tx = api.tx.polkadotXcm.send(dest, message);
// 5. Send the transaction
const txHash = await tx.signAndSend(alice);
console.log(`Submitted with hash ${txHash}`);
api.disconnect();
};
sendXcmMessage();
注意事项
您可以使用以下编码的调用数据在Polkadot.js Apps上查看上述脚本的示例,该脚本将1个UNIT发送给中继链上Bob的账户:0x1c00030100030c000400010000070010a5d4e81300010000070010a5d4e8000d0100010101000c36e9ba26fa63c60ec728fe75fe57b86a450d94e7fee7f9f9eddd0d3f400d67
。
交易处理后,polkadotXcm.sent
事件将与发送的XCM消息详情一同发出。
使用XCM Utilities预编译发送XCM交易¶
在这一部分,您将使用XCM Utilities预编译的xcmSend
函数(该函数仅支持Moonbase Alpha)以跨链发送XCM消息。XCM-Utilities预编译位于以下地址:
0x000000000000000000000000000000000000080C
在Hood下,XCM-Utilities预编译的xcmSend
函数调用Polkadot XCM Pallet的send
函数,即用Rust编码的Substrate pallet。使用XCM-Utilities预编译调用send
的好处是您可以通过以太坊API完成此操作并使用Ethers.js等以太坊库。要成功执行XCM消息,目标链需要了解消息中的指令。
xcmSend
函数接受两个参数:目标链的multilocation和要发送的SCALE编码的版本化XCM消息。
首先,您将了解如何生成用于XCM消息的编码调用数据,然后您将了解如何使用编码的调用数据与 XCM Utilities预编译交互。
生成XCM消息的编码调用数据¶
要获取XCM消息的编码调用数据,您可以创建一个类似于在使用Polkadot.js API执行XCM消息部分创建的脚本。您将构建消息来获取编码的调用数据,而不是构建消息并发送交易。为此,您需要执行以下步骤:
-
提供调用的输入数据,这包含:
- 用于创建提供商的Moonbase Alpha端点URL
- 使用Polkadot.js API执行XCM消息部分定义的
send
函数的每个参数的值
-
创建Polkadot.js API提供商
- 使用
message
和maxWeight
值制作polkadotXcm.execute
extrinsic - 使用交易获取编码的调用数据
完整脚本如下所示:
import { ApiPromise, WsProvider } from '@polkadot/api'; // Version 9.13.6
import { decodeAddress } from '@polkadot/util-crypto';
// 1. Input data
const providerWsURL = 'wss://wss.api.moonbase.moonbeam.network';
// You can use the decodeAddress function to ensure that your address is properly
// decoded. If it isn't decoded, it will decode it and if it is, it will ignore it
const relayAccount = decodeAddress('INSERT_ADDRESS');
const dest = { V3: { parents: 1, interior: null } };
const instr1 = {
WithdrawAsset: [
{
id: { Concrete: { parents: 1, interior: null } },
fun: { Fungible: 1000000000000n }, // 1 UNIT
},
],
};
const instr2 = {
BuyExecution: [
{
id: { Concrete: { parents: 1, interior: null } },
fun: { Fungible: 1000000000000n }, // 1 UNIT
},
{ Unlimited: null }
],
};
const instr3 = {
DepositAsset: {
assets: { Wild: 'All' },
beneficiary: {
parents: 1,
interior: {
X1: {
AccountId32: {
id: relayAccount,
},
},
},
},
},
};
const message = { V3: [instr1, instr2, instr3] };
const generateEncodedXcmMessage = async () => {
// 2. Create Substrate API Provider
const substrateProvider = new WsProvider(providerWsURL);
const api = await ApiPromise.create({ provider: substrateProvider });
// 3. Create the extrinsic
const tx = api.tx.polkadotXcm.send(dest, message);
// 4. Get the encoded XCM message
// By using index 1, you'll get just the encoded XCM message.
// If you wanted to get the dest, you could use index 0
const encodedXcmMessage = tx.args[1].toHex()
console.log(`Encoded Calldata for XCM Message: ${encodedXcmMessage}`);
api.disconnect();
};
generateEncodedXcmMessage();
发送XCM消息¶
在发送XCM消息前,您需要构建目标的multilocation。在本示例中,您将以Moonbase Alpha作为源链的中继链:
const dest = [
1, // Parents: 1
[] // Interior: Here
];
现在,你已拥有SCALE编码的XCM消息和目标multilocation,您可以使用以下代码片段选择以太坊库以编程方式调用XCM Utilities预编译的xcmSend
函数。通常,您需要执行以下步骤:
- 创建提供商和签署者
- 创建用于交互的XCM Utilities Precompile的实例
- 定义
xcmSend
函数所需的参数,该参数将是XCM消息的目标链和编码的调用数据 - 发送XCM消息
请记住
以下代码片段仅用于演示目的,请勿将您的私钥存储至JavaScript或Python文件中。
import ABI from './xcmUtilsABI.js'; // Import the XCM Utilities Precompile ABI
import { ethers } from 'ethers'; // Import Ethers library
const privateKey = 'INSERT_PRIVATE_KEY';
const xcmUtilsAddress = '0x000000000000000000000000000000000000080C';
/* Create Ethers provider and signer */
const provider = new ethers.JsonRpcProvider(
'https://rpc.api.moonbase.moonbeam.network'
);
const signer = new ethers.Wallet(privateKey, provider);
/* Create contract instance of the XCM Utilities Precompile */
const xcmUtils = new ethers.Contract(
xcmUtilsAddress,
ABI,
signer
);
const sendXcm = async () => {
/* Define parameters required for the xcmSend function */
const encodedCalldata = 'INSERT_ENCODED_CALLDATA';
const dest = [
1, // Parents: 1
[] // Interior: Here
];
/* Send the custom XCM message */
const tx = await xcmUtils.xcmSend(dest, encodedCalldata);
await tx.wait();
console.log(`Transaction receipt: ${tx.hash}`);
};
sendXcm();
import ABI from './xcmUtilsABI.js'; // Import the XCM Utilities Precompile ABI
import { Web3 } from 'web3'; // Import Web3 library
const privateKey = 'INSERT_PRIVATE_KEY';
const accountFrom = web3.eth.accounts.privateKeyToAccount(privateKey).address;
const xcmUtilsAddress = '0x000000000000000000000000000000000000080C';
/* Create Web3 provider */
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network'); // Change to network of choice
/* Create contract instance of the XCM Utilities Precompile */
const xcmUtils = new web3.eth.Contract(
ABI,
xcmUtilsAddress,
{ from: accountFrom } // 'from' is necessary for gas estimation
);
const sendXcm = async () => {
/* Define parameters required for the xcmSend function */
const encodedCalldata = 'INSERT_ENCODED_CALLDATA';
const dest = [
1, // Parents: 1
[], // Interior: Here
];
/* Send the custom XCM message */
// Craft the extrinsic
const tx = await xcmUtils.methods.xcmSend(dest, encodedCalldata);
// Sign transaction
const signedTx = await web3.eth.accounts.signTransaction(
{
to: xcmUtilsAddress,
data: tx.encodeABI(),
gas: await tx.estimateGas(),
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(accountFrom),
},
privateKey
);
// Send the signed transaction
const sendTx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log(`Transaction receipt: ${sendTx.transactionHash}`);
};
sendXcm();
from web3 import Web3
abi = "INSERT_XCM_UTILS_ABI" # Paste or import the XCM Utils ABI
# This is for demo purposes, never store your private key in plain text
private_key = "INSERT_PRIVATE_KEY"
# The wallet address that corresponds to your private key
address = "INSERT_ADDRESS"
xcm_utils_address = "0x000000000000000000000000000000000000080C"
## Create Web3 provider ##
web3 = Web3(Web3.HTTPProvider("https://rpc.api.moonbase.moonbeam.network"))
## Create contract instance of the XCM Utilities Precompile ##
xcm_utils = web3.eth.contract(
# XCM Utilities Precompile address
address=xcm_utils_address,
abi=abi,
)
def send_xcm():
## Define parameters required for the xcmSend function ##
encoded_calldata = "INSERT_ENCODED_CALLDATA"
xcm_dest = [1, []] # Parents: 1 # Interior: Here
## Send the custom XCM message ##
# Craft the extrinsic
tx = xcm_utils.functions.xcmSend(xcm_dest, encoded_calldata).build_transaction(
{
"from": address,
"nonce": web3.eth.get_transaction_count(address),
}
)
# Sign transaction
signed_tx = web3.eth.account.sign_transaction(tx, private_key)
# Send tx
hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction)
receipt = web3.eth.wait_for_transaction_receipt(hash)
print(f"Transaction receipt: { receipt.transactionHash.hex() }")
send_xcm()
这样就可以了!您已成功使用Polkadot XCM Pallet和XCM-Utilities预编译从Moonbase Alpha上发送消息至另一条链。
| Created: April 14, 2023