使用X-Tokens Pallet发送XC-20s¶
概览¶
为同质化资产转移构建XCM信息通道并非一件易事。因此,开发者可以通过利用wrapper函数/pallet在Polkadot/Kusama上使用XCM功能。
此类包装器的一个示例是x-tokens pallet,用于提供通过XCM转移同质化资产的不同方法。
本教程将向您展示如何利用x-tokens pallet在生态系统(中继链/平行链)中从基于Moonbeam的网络发送XC-20至其他链。此外,您还将学习到如何使用x-tokens预编译通过以太坊API执行同样的操作。
开发者须知若发送不正确的XCM信息可能会导致资金丢失。因此,XCM功能需先在测试网上进行测试后才可移至生产环境。
相关XCM定义¶
- XCM — 代表跨共识信息,是共识系统相互通信的信息格式
- VMP — 代表垂直消息传递,它允许平行链与中继链交换消息。UMP(向上消息传递)允许平行链将消息发送到它们的中继链,而 DMP(向下消息传递)允许中继链将消息向下传递到它们的平行链之一
- XCMP — 代表跨共识消息传递,它允许平行链与同一中继链上的其他平行链交换消息
- HRMP — 代表平行中继路由消息传递,是启动完整XCMP实现前的过度实现方式。与XCMP具有相同的接口,但消息存储在中继链上
- 主权账户 — 生态系统中每条链预设的账户,用于中继链和其他平行链。它的地址为特定单词和平行链ID连接的
blake2
哈希(中继链中的主权账户为blake2(para+ParachainID)
,其他中的主权账户为blake2(sibl+ParachainID)
平行链),将哈希截断为正确的长度。该帐户归root所支配,只能通过SUDO(如果有)或民主(技术委员会或公民投票)使用。主权账户通常在其它链上签署 XCM 消息 - Multilocation — 一种指定整个中继链或平行链生态系统中来源点(相对或绝对来源)的方式;例如,它可用于指定特定的平行链、资产、账户,甚至是一个Pallet。一般而言,multilocation定义包含为
parents
和interior
。parents
是指需要从来源点“跳跃”多少次可以进入parent
区块链。interior
,是指定义目标点需要多少个字段。例如,要从另一个平行链中定位ID为1000
的平行链,multilocation将是{ "parents": 1, "interior": { "X1": [{ "Parachain": 1000 }]}}
X-tokens Pallet接口¶
Extrinsics¶
X-tokens pallet提供以下extrinsics(函数):
- transfer(currencyId, amount, dest, destWeight) — 转移一个币种,根据原生Token(自身储备)或是资产ID定义
- transferMultiasset(asset, dest, destWeight) — 转移一种可替代资产,根据其multilocation定义
- transferMultiassetWithFee(asset, fee, dest, destWeight) — 转移一种可替代资产,但其能够让资产的发送者使用另外一种资产支付转移费用。两者皆根据其multilocation定义
- transferMultiassets(assets, feeItem, dest, destWeight) — 转移多种可替代资产,并定义其中哪种资产将会被用于支付转移费用。所有资产皆由其multilocation定义
- transferMulticurrencies(currencies, feeItem, dest, destWeight) — 转移多个币种,并定义其中哪种币种将会被用于支付转移费用。所有币种都将通过原生Token(自身储备)或是资产ID定义
- transferWithFee(currencyId, amount, fee, dest, destWeight) — 转移一个币种,但允许资产发送者使用不同的资产支付转移费用。两者皆由其multilocation定义
其中需要提供信息输入的函数定义如下:
- currencyId/currencies — 将通过XCM转移的币种ID。不同runtime有不同的方法定义ID。以基于Moonbeam的网络为例子,
SelfReserve
代表原生Token,ForeignAsset
代表其XC-20资产ID(而不是其XC-20地址) - amount — 将通过XCM转移的Token数量
- dest — 一个multilocation,用于定义将通过XCM转移Token的目标地址。其支持不同地址格式,如20或32字节的地址(以太坊或是Substrate格式)
- destWeight — 一个枚举类型(enum),表示您提供给目标链希望其执行XCM信息的最大执行时间。
Unlimited
选项允许将所有用于gas的资产用于支付权重(weight)。Limited
选项将gas的使用量限制为特定值。如果您提供的信息不足,XCM将会执行失败,且资金将会被锁定在主权账户或是特定的pallet中。设置目标权重非常重要,这将避免XCM失败 - asset/assets — 一个用于定义将通过XCM转移资产的multilocation。每条平行链将会有不同定义资产的方式。举例而言,基于Moonbeam的网络将会经由其原生Token的pallet余额索引定义
- fee — 一个用于定义支付XCM在目标链上执行的multilocation
- feeItem — 一个用于定义多样资产发送地点的索引,将用于支付XCM在目标链上的执行。举例而言,如果仅有一种资产被发送,
feeItem
将会是0
存储方法¶
X-tokens pallet包括以下只读存储方式:
- palletVersion() - 提供正在使用的x-tokens pallet的版本
Pallet常量¶
X-tokens pallet包括以下用于获取pallet常量的只读函数:
- baseXcmWeight() - 返回执行所需的基本XCM重量
- selfLocation() - 返回本地的multilocation
使用x-tokens Pallet构建XCM信息¶
此教程将会包含使用x-tokens pallet构建XCM信息的过程,更详细来说为使用transfer
和transferMultiasset
函数。然而,这两种情况仍然可以外推至其他函数,特别是当您熟悉了多重地点的使用之后。
注意事项
每条平行链皆能够通过pallet允许/禁止特定函数。因此,开发者需要确认使用的函数是被平行链允许的。相反来说,如果使用了被禁止的函数,交易将会如同system.CallFiltered
显示一般失败。
本教程将以转移xcUNIT
token为例。xcUNIT
是Alphanet中继链Token UNIT
的XC-20形式,也是外部XC-20。本教程也同样适用于其他外部XC-20或可铸造XC-20。
查看先决条件¶
要在Polikadot.js Apps上发送extrinsics,您需要准备以下内容:
- 一个已添加至Polkadot.js的账户,且该账户拥有一些DEV tokens
- 您要转移资产的资产ID:
- 对于外部XC-20,您可以从Polkadot.js Apps的资产ID列表中获取
- 对于可铸造XC-20,请查阅获取可铸造XC-20资产的列表部分
- 您要转移资产的位数:
- 对于外部XC-20,请查阅获取外部XC-20资产的元数据部分
- 对于可铸造XC-20,请查阅获取可铸造XC-20资产的元数据部分
- 一些
xcUNIT
tokens。您可以在Moonbeam-Swap上将DEV
tokens兑换成xcUNIT
,Moonbeam-Swap是Moonbase Alpha上的Uniswap-V2版本的示范协议。
要查看您的xcUNIT
余额,您可以使用以下地址将XC-20添加至MetaMask:
0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080
您可以通过以下教程查看如何计算预编译地址:
X-Tokens转移函数¶
在本示例中,您将会构建一个XCM信息,通过x-tokens pallet的transfer
函数将xcUNIT
从Moonbase Alpha转移回其中继链上。
导航至Polkadot.js Apps的extrinsic页面,并设定以下选项(也可以适用于可铸造XC-20s):
- 选取您希望转移XCM的账户
- 选择xTokens pallet
- 选择transfer extrinsic
- 将外部XC-20的币种ID设置为ForeignAsset或将可铸造XC-20的币种ID设置为LocalAssetReserve。因为
xcUNIT
是外部XC-20,所以您需要选择ForeignAsset - 输入资产ID。在本示例中,
xcUNIT
的资产ID为42259045809535163221576417993425387648
- 设置需要转移的Token数量。在本示例中,您将转移1个
xcUNIT
,但您需要注意xcUNIT
后有12位小数位 -
定义XCM目标multilocation,您需要将Moonbase Alpha的中继链中的一个账户作为初始点。因此,您需要设置以下参数:
参数 数值 Version V1 Parents 1 Interior X1 X1 AccountId32 Network Any Id Target Account -
将目标权重设置为
Limited
,并将其值设置为1000000000
。请注意,在Moonbase Alpha上,每个XCM操作需要大概100000000
权重单位。一个transfer
包含4个XCM操作,因此目标权重应当设置为400000000
左右 -
点击Submit Transaction按钮并签署交易
注意事项
以上extrinsic配置的编码调用数据为0x1e00018080778c30c20fa2ebc0ed18d2cbca1f0010a5d4e800000000000000000000000101010100c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a0630102286bee
,这同样包含一个您需要改变的接收者函数。
当交易正在处理中,TargetAccount将会获取设定的转移数量并扣除用于在目标链上执行XCM的小额费用。在Polkadot.js Apps,您可以查看Moonbase Alpha以及中继链的相关extrinsics和事件。
X-Tokens转移多种资产函数¶
在本示例中,您将会构建一个XCM信息,通过x-tokens pallet的transferMultiasset
函数将xcUNIT
从Moonbase Alpha转移回其中继链上。
导航至Polkadot.js Apps的extrinsic页面,并设定以下选项:
-
选取您希望转移XCM的账户
-
选择xTokens pallet
-
选择transferMultiasset extrinsic
-
定义XCM资产multilocation,您需要将Moonbase Alpha的中继链中的
UNIT
作为初始点。每条链皆有不同的定义方法。因此,您需要为各个目标设置不同的资产multilocation。在此例而言,中继链Token将会通过以下函数定义:参数 数值 Version V1 Parents 1 Interior Here 如果您要将本教程修改成适应可铸造XC-20资产,您需要指定创建资产和资产ID的pallet。因此,您需要设置以下参数:
参数 数值 Version V1 Parents 1 Interior X2 PalletInstance 36 GeneralIndex Asset ID -
将资产类别设置为Fungible
-
设置需要转移的Token数量。在本示例中,您将转移1个
xcUNIT
,但您需要注意xcUNIT
后有12位小数位 -
定义XCM目标multilocation,您需要将Moonbase Alpha的中继链中的一个账户作为初始点。因此,您需要设置以下参数:
参数 数值 Version V1 Parents 1 Interior X1 X1 AccountId32 Network Any Id Target Account -
将目标权重设置为
1000000000
。请注意,在Moonbase Alpha上,每个XCM操作需要大概100000000
权重单位。一个transferMultiasset
包含4个XCM操作,因此目标权重应当设置为400000000
左右 -
点击Submit Transaction按钮并签署交易
注意事项
以上extrinsic配置的编码调用数据为0x1e010100010000070010a5d4e80101010100c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a0630102286bee
,这同样包含一个您需要改变的接收者函数。
当交易正在处理中,TargetAccount将会获取设定的转移数量并扣取用于在目标链上执行XCM的小额费用。在Polkadot.js Apps,您可以查看Moonbase Alpha以及中继链的相关extrinsics和事件。
X-Tokens预编译¶
X-tokens预编译合约将会允许开发者通过基于Moonbeam网络的以太坊API访问XCM Token转移功能。如同其他预编译合约,x-tokens预编译位于以下地址:
0x0000000000000000000000000000000000000804
0x0000000000000000000000000000000000000804
0x0000000000000000000000000000000000000804
注意事项
在Moonbeam使用预编译合约时,可能会出现一些意想不到的后果。 请参阅安全注意事项 页面了解更多信息。
X-Tokens Solidity接口¶
Xtokens.sol是一个开发者能够使用以太坊API与x-tokens pallet交互的接口。
此接口包含以下函数:
-
transfer(address currencyAddress, uint256 amount, Multilocation memory destination, uint64 weight) —— 用于表示先前示例中提及的
transfer
函数。然而,在使用币种ID之外,您需要为currencyAddress
提供资产预编译地址:- 对于外部XC-20,您可以提供XC-20预编译地址
- 对于可铸造XC-20,您可以遵循计算预编译地址的操作说明
- 对于原生Token(如GLMR、MOVR和DEV),您可以提供ERC-20预编译地址,即
0x0000000000000000000000000000000000000802
destination
multilocation将会以一种特殊形式构建(我们将在下一部分提及) -
transferMultiasset(Multilocation memory asset, uint256 amount, Multilocation memory destination, uint64 weight) —— 用于表示先前示例中提及的
transferMultiasset
函数。两种multilocation将会以一种特殊形式构建(我们将在下一部分提及)
构建预编译Multilocation¶
在x-tokens预编译接口中,Multilocation
架构根据下列函数定义:
struct Multilocation {
uint8 parents;
bytes[] interior;
}
请注意每个multilocation皆有parents
元素,请使用uint8
和一组字节定义。Parents代表有多少“hops”在通过中继链中您需要执行的传递向上方向。作为uint8
,您将会看到以下数值:
Origin | Destination | Parents Value |
---|---|---|
Parachain A | Parachain A | 0 |
Parachain A | Relay Chain | 1 |
Parachain A | Parachain B | 1 |
字节阵列(bytes[]
)定义了内部参数以及其在multilocation的内容。阵列的大小则根据以下定义interior
数值:
Array | Size | Interior Value |
---|---|---|
[] | 0 | Here |
[XYZ] | 1 | X1 |
[XYZ, ABC] | 2 | X2 |
[XYZ, ... N] | N | XN |
注意事项
内部值Here
通常用于中继链(作为目标链或以中继链资产为目标)。
假设所有字节阵列包含数据。所有元素的首个字节(2个十六进制数值)与XN
部分的选择器相关,举例来说:
Byte Value | Selector | Data Type |
---|---|---|
0x00 | Parachain | bytes4 |
0x01 | AccountId32 | bytes32 |
0x02 | AccountIndex64 | u64 |
0x03 | AccountKey20 | bytes20 |
0x04 | PalletInstance | byte |
0x05 | GeneralIndex | u128 |
0x06 | GeneralKey | bytes[] |
接着,根据选择器及其数据类型,以下字节对应于提供的实际数据。请注意在Polkadot.js Apps示例中出现的AccountId32
,AccountIndex64
和AccountKey20
,network
将会在最后添加。如下所示:
Selector | Data Value | Represents |
---|---|---|
Parachain | "0x00+000007E7" | Parachain ID 2023 |
AccountId32 | "0x01+AccountId32+00" | AccountId32, Network Any |
AccountKey20 | "0x03+AccountKey20+00" | AccountKey20, Network Any |
PalletInstance | "0x04+03" | Pallet Instance 3 |
注意事项
interior
数据通常需要使用引号包含。如果您未遵循此规则,您将会获得invalid tuple value
错误。
以下代码片段包含Multilocation
架构的部分示例,因为其将会在x-tokens预编译函数中使用:
// Multilocation targeting the relay chain or its asset from a parachain
{
1, // parents = 1
[] // interior = here
}
// Multilocation targeting Moonbase Alpha DEV token from another parachain
{
1, // parents = 1
// Size of array is 2, meaning is an X2 interior
[
"0x00000003E8", // Selector Parachain, ID = 1000 (Moonbase Alpha)
"0x0403" // Pallet Instance = 3
]
}
// Multilocation targeting Alice's account on the Relay Chain from Moonbase Alpha
{
1, // parents = 0
// Size of array is 1, meaning is an X1 interior
[
"0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"
// AccountKey32 Selector + Address in hex + Network = Any
]
}
使用库与X-Token交互¶
当使用库与Ethereum API交互时,Multilocation结构可以像任何其他结构一样格式化。以下代码片段包括前面的x-tokens 传输函数、x-tokens 多资产传输函数和示例Multilocation结构示例。您可以在Github上找到x-tokens的合约ABI。
import abi from './xtokensABI.js'; // Import the x-tokens ABI
import { ethers } from 'ethers'; // Import Ethers library
const PRIVATE_KEY = 'YOUR_PRIVATE_KEY_HERE';
// Create Ethers wallet & contract instance
const provider = new ethers.providers.JsonRpcProvider('https://rpc.api.moonbase.moonbeam.network');
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
const xTokens = new ethers.Contract(
'0x0000000000000000000000000000000000000804',
abi,
signer
);
// xcUNIT address in Moonbase Alpha
const xcUNIT_ADDRESS = '0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080';
// Multilocation targeting Alice's account on the relay chain from Moonbase Alpha
const ALICE_RELAY_ACC = [1, ['0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300']];
// Sends 1 xcUNIT to the relay chain using the transfer function
async function transferToAlice() {
// Creates, signs, and sends the transfer transaction
const transaction = await xTokens.transfer(
xcUNIT_ADDRESS, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);
// Waits for the transaction to be included in a block
await transaction.wait();
console.log(transaction);
}
// Multilocation targeting the relay chain or its asset from a parachain
const RELAY_CHAIN_ASSET = [1, []];
// Sends 1 xcUNIT to the relay chain using the transferMultiasset function
async function transferMultiassetToAlice() {
const transaction = await xTokens.transferMultiasset(
RELAY_CHAIN_ASSET, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);
await transaction.wait();
console.log(transaction);}
transferToAlice();
transferMultiassetToAlice();
// Here are some additional multilocations for the Asset multilocation:
const LOCAL_ASSET = [0, ["0x0424", "0x05FD9D0BF45A2947A519A741C4B9E99EB6"]]; // Note that 0x0424 indicates the x-tokens pallet
const DEV_FROM_OTHER_PARACHAIN = [1, ["0x00000003E8", "0x0403"]]; // Use if you were targeting DEV from a non-Moonbeam network
// Here are some additional multilocations for the Destination multilocation:
const ADDRESS32_OF_PARACHAIN = [1, ["0x00000007EF", "0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"]];
const ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [1, ["0x00000003E8", "0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00"]];
import abi from './xtokensABI.js'; // Import the x-tokens ABI
import Web3 from 'web3'; // Import Web3 library
const PRIVATE_KEY = 'YOUR_PRIVATE_KEY_HERE';
// Create Web3 wallet & contract instance
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network'); // Change to network of choice
const xTokens = new web3.eth.Contract(
abi,
'0x0000000000000000000000000000000000000804',
{ from: web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY).address } // 'from' is necessary for gas estimation
);
// xcUNIT address in Moonbase Alpha
const xcUNIT_ADDRESS = '0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080';
// Multilocation targeting Alice's account on the relay chain from Moonbase Alpha
const ALICE_RELAY_ACC = [1, ['0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300']];
// Sends 1 xcUNIT to the relay chain using the transfer function
async function transferToAlice() {
// Create transaction
const transferTx = xTokens.methods.transfer(
xcUNIT_ADDRESS, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);
// Sign transaction
const signedTx = await web3.eth.accounts.signTransaction(
{
to: '0x0000000000000000000000000000000000000804',
data: transferTx.encodeABI(),
gas: await transferTx.estimateGas()
},
PRIVATE_KEY
);
// Send signed transaction
const sendTx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log(sendTx);
}
// Multilocation targeting the relay chain or its asset from a parachain
const RELAY_CHAIN_ASSET = [1, []];
// Sends 1 xcUNIT to the relay chain using the transferMultiasset function
async function transferMultiassetToAlice() {
const transferTx = xTokens.methods.transferMultiasset(
RELAY_CHAIN_ASSET, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);
const signedTx = await web3.eth.accounts.signTransaction(
{
to: '0x0000000000000000000000000000000000000804',
data: transferTx.encodeABI(),
gas: await transferTx.estimateGas()
},
PRIVATE_KEY
);
const sendTx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log(sendTx);
}
transferToAlice();
transferMultiassetToAlice();
// Here are some additional multilocations for the Asset multilocation:
const LOCAL_ASSET = [0, ["0x0424", "0x05FD9D0BF45A2947A519A741C4B9E99EB6"]]; // Note that 0x0424 indicates the x-tokens pallet
const DEV_FROM_OTHER_PARACHAIN = [1, ["0x00000003E8", "0x0403"]]; // Use if you were targeting DEV from a non-Moonbeam network
// Here are some additional multilocations for the Destination multilocation:
const ADDRESS32_OF_PARACHAIN = [1, ["0x00000007EF", "0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"]];
const ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [1, ["0x00000003E8", "0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00"]];
from web3 import Web3
abi = 'XTOKENS_ABI_HERE' # Paste or import the x-tokens ABI
privateKey = 'YOUR_PRIVATE_KEY_HERE' # This is for demo purposes, never store your private key in plain text
address = 'YOUR_ADDRESS_HERE' # The wallet address that corresponds to your private key
# Create Web3 wallet & contract instance
web3 = Web3(Web3.HTTPProvider('https://rpc.api.moonbase.moonbeam.network'))
xTokens = web3.eth.contract(
address='0x0000000000000000000000000000000000000804',
abi=abi
)
# xcUNIT address in Moonbase Alpha
xcUNIT_ADDRESS = '0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080'
# Multilocation targeting Alice's account on the relay chain from Moonbase Alpha
ALICE_RELAY_ACC = [1, ['0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300']]
# Sends 1 xcUNIT to the relay chain using the transfer function
def transferToAlice():
# Create transaction
transferTx = xTokens.functions.transfer(
xcUNIT_ADDRESS, # Asset
1000000000000, # Amount
ALICE_RELAY_ACC, # Destination
1000000000 # Weight
).buildTransaction(
{
'from': address,
'nonce': web3.eth.get_transaction_count(address),
}
)
# Sign transaction
signedTx = web3.eth.account.sign_transaction(transferTx, privateKey)
# 7. Send tx and wait for receipt
hash = web3.eth.send_raw_transaction(signedTx.rawTransaction)
receipt = web3.eth.wait_for_transaction_receipt(hash)
print(f'Tx successful with hash: { receipt.transactionHash.hex() }')
# Multilocation targeting the relay chain or its asset from a parachain
RELAY_CHAIN_ASSET = [1, []];
# Sends 1 xcUNIT to the relay chain using the transferMultiasset function
def transferMultiassetToAlice():
transferTx = xTokens.functions.transferMultiasset(
RELAY_CHAIN_ASSET, # Asset
1000000000000, # Amount
ALICE_RELAY_ACC, # Destination
1000000000 # Weight
).buildTransaction(
{
'from': address,
'nonce': web3.eth.get_transaction_count(address),
}
)
signedTx = web3.eth.account.sign_transaction(transferTx, privateKey)
hash = web3.eth.send_raw_transaction(signedTx.rawTransaction)
receipt = web3.eth.wait_for_transaction_receipt(hash)
print(f'Tx successful with hash: { receipt.transactionHash.hex() }')
transferToAlice()
transferMultiassetToAlice()
# Here are some additional multilocations for the Asset multilocation:
LOCAL_ASSET = [0, ["0x0424", "0x05FD9D0BF45A2947A519A741C4B9E99EB6"]] # Note that 0x0424 indicates the x-tokens pallet
DEV_FROM_OTHER_PARACHAIN = [1, ["0x00000003E8", "0x0403"]] # Use if you were targeting DEV from a non-Moonbeam network
# Here are some additional multilocations for the Destination multilocation:
ADDRESS32_OF_PARACHAIN = [1, ["0x00000007EF", "0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"]]
ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [1, ["0x00000003E8", "0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00"]]
注意事项
在Moonbeam 或 Moonriver上测试上述示例时,您可以将RPC URL替换为您自己的私有端点和API密钥。
| Created: April 29, 2022