@moonbeam-network/xcm-builder
Version:
Moonbeam XCM builder
1,970 lines (1,943 loc) • 130 kB
JavaScript
// src/index.ts
import "@polkadot/api-augment";
// src/extrinsic/ExtrinsicBuilder.utils.ts
import { isEthAddress } from "@moonbeam-network/xcm-utils";
import { getTypeDef } from "@polkadot/types";
import { u8aToHex } from "@polkadot/util";
import { decodeAddress } from "@polkadot/util-crypto";
// src/extrinsic/ExtrinsicBuilder.interfaces.ts
var XcmVersion = /* @__PURE__ */ ((XcmVersion2) => {
XcmVersion2["v1"] = "V1";
XcmVersion2["v2"] = "V2";
XcmVersion2["v3"] = "V3";
XcmVersion2["v4"] = "V4";
XcmVersion2["v5"] = "V5";
return XcmVersion2;
})(XcmVersion || {});
// src/extrinsic/ExtrinsicBuilder.utils.ts
function getExtrinsicArgumentVersion(func, index = 0) {
if (!func) return "V1" /* v1 */;
const { type } = func.meta.args[index];
const instance = func.meta.registry.createType(type.toString());
const raw = getTypeDef(instance?.toRawType());
if (!raw.sub) {
return "V1" /* v1 */;
}
const versions = Array.isArray(raw.sub) ? raw.sub.map((x) => x.name) : [raw.sub.name];
if (versions.includes("V5" /* v5 */)) {
return "V5" /* v5 */;
}
if (versions.includes("V4" /* v4 */)) {
return "V4" /* v4 */;
}
if (versions.includes("V3" /* v3 */)) {
return "V3" /* v3 */;
}
if (versions.includes("V2" /* v2 */)) {
return "V2" /* v2 */;
}
if (versions.includes("V1" /* v1 */)) {
return "V1" /* v1 */;
}
throw new Error("Can't find XCM version");
}
function getExtrinsicAccount(address) {
return isEthAddress(address) ? {
AccountKey20: {
key: address
}
} : {
AccountId32: {
id: u8aToHex(decodeAddress(address)),
network: null
}
};
}
function isXcmV4(xcmVersion) {
return xcmVersion >= "V4" /* v4 */;
}
function normalizeX1(xcmVersion, versionedObject) {
if (!isXcmV4(xcmVersion)) return versionedObject;
const normalizedObject = { ...versionedObject };
const interior = normalizedObject.interior;
if ("X1" in interior && interior?.X1 && !Array.isArray(interior.X1)) {
interior.X1 = [interior.X1];
} else if ("x1" in interior && interior?.x1 && !Array.isArray(interior.x1)) {
interior.x1 = [interior.x1];
}
return normalizedObject;
}
function normalizeConcrete(xcmVersion, versionedObject) {
return isXcmV4(xcmVersion) ? versionedObject : applyConcreteWrapper(versionedObject);
}
function applyConcreteWrapper(versionedObject) {
return {
Concrete: { ...versionedObject }
};
}
// src/types/BaseConfig.ts
var BaseConfig = class {
module;
func;
constructor({ module: module5, func }) {
this.module = module5;
this.func = func;
}
};
// src/types/substrate/SubstrateQueryConfig.ts
var SubstrateQueryConfig = class _SubstrateQueryConfig extends BaseConfig {
args;
transform;
static is(obj) {
return obj instanceof _SubstrateQueryConfig;
}
constructor({
args = [],
transform,
...other
}) {
super({ ...other });
this.args = args;
this.transform = transform;
}
};
// src/asset-min/AssetMinBuilder.ts
function AssetMinBuilder() {
return {
assetRegistry,
assets,
foreignAssets
};
}
function assetRegistry() {
const pallet6 = "assetRegistry";
return {
assetMetadatas: () => ({
build: ({ asset }) => new SubstrateQueryConfig({
module: pallet6,
func: "assetMetadatas",
args: [asset],
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
transform: async (response) => response.unwrapOrDefault().minimalBalance.toBigInt()
})
}),
currencyMetadatas: () => ({
build: ({ asset }) => new SubstrateQueryConfig({
module: pallet6,
func: "currencyMetadatas",
args: [asset],
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
transform: async (response) => response.unwrapOrDefault().minimalBalance.toBigInt()
})
}),
metadata: () => ({
build: ({ asset }) => new SubstrateQueryConfig({
module: pallet6,
func: "metadata",
args: [asset],
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
transform: async (response) => response.unwrapOrDefault().existentialDeposit.toBigInt()
})
})
};
}
function assets() {
return {
asset: () => ({
build: ({ asset }) => new SubstrateQueryConfig({
module: "assets",
func: "asset",
args: [asset],
transform: async (response) => response.unwrapOrDefault().minBalance.toBigInt()
})
})
};
}
function foreignAssets() {
return {
asset: () => ({
build: ({ address }) => {
if (!address) {
throw new Error(
"Asset address is missing for foreignAssets.asset min calculation"
);
}
const multilocation = {
parents: 2,
interior: {
X2: [
{
globalconsensus: {
ethereum: {
chainId: 1
}
}
},
getExtrinsicAccount(address)
]
}
};
return new SubstrateQueryConfig({
module: "foreignAssets",
func: "asset",
args: [multilocation],
transform: async (response) => response.unwrapOrDefault().minBalance.toBigInt()
});
}
})
};
}
// src/balance/BalanceBuilder.ts
import { evmToAddress as evmToAddress2 } from "@polkadot/util-crypto";
// src/types/evm/ContractConfig.ts
import { encodeFunctionData } from "viem";
var ContractConfig = class _ContractConfig extends BaseConfig {
address;
abi;
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
args;
static is(obj) {
return obj instanceof _ContractConfig;
}
constructor({
address,
abi,
args,
...other
}) {
super({ ...other });
this.address = address;
this.abi = abi;
this.args = args;
}
encodeFunctionData() {
return encodeFunctionData({
abi: this.abi,
functionName: this.func,
args: this.args
});
}
};
// src/contract/contracts/XcmPrecompile/XcmPrecompile.ts
import { u8aToHex as u8aToHex2 } from "@polkadot/util";
import { decodeAddress as decodeAddress2 } from "@polkadot/util-crypto";
// src/types/evm/EvmQueryConfig.ts
var EvmQueryConfig = class _EvmQueryConfig {
args;
func;
static is(obj) {
return obj instanceof _EvmQueryConfig;
}
constructor({ args, func }) {
this.args = args;
this.func = func;
}
};
// src/types/substrate/ExtrinsicConfig.ts
var ExtrinsicConfig = class _ExtrinsicConfig extends BaseConfig {
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
getArgs;
static is(obj) {
return obj instanceof _ExtrinsicConfig;
}
constructor({ getArgs, ...other }) {
super({ ...other });
this.getArgs = getArgs;
}
};
// src/types/substrate/SubstrateCallConfig.ts
var SubstrateCallConfig = class _SubstrateCallConfig {
api;
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
call;
static is(obj) {
return obj instanceof _SubstrateCallConfig;
}
constructor({ api, call }) {
this.api = api;
this.call = call;
}
};
// src/contract/contracts/XcmPrecompile/XcmPrecompileAbi.ts
var XCM_ABI = [
{
inputs: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "dest",
type: "tuple"
},
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "beneficiary",
type: "tuple"
},
{
components: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "location",
type: "tuple"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetLocationInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "uint32",
name: "feeAssetItem",
type: "uint32"
}
],
name: "transferAssetsLocation",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "uint32",
name: "paraId",
type: "uint32"
},
{
internalType: "address",
name: "beneficiary",
type: "address"
},
{
components: [
{
internalType: "address",
name: "asset",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetAddressInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "uint32",
name: "feeAssetItem",
type: "uint32"
}
],
name: "transferAssetsToPara20",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "uint32",
name: "paraId",
type: "uint32"
},
{
internalType: "bytes32",
name: "beneficiary",
type: "bytes32"
},
{
components: [
{
internalType: "address",
name: "asset",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetAddressInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "uint32",
name: "feeAssetItem",
type: "uint32"
}
],
name: "transferAssetsToPara32",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "bytes32",
name: "beneficiary",
type: "bytes32"
},
{
components: [
{
internalType: "address",
name: "asset",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetAddressInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "uint32",
name: "feeAssetItem",
type: "uint32"
}
],
name: "transferAssetsToRelay",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "dest",
type: "tuple"
},
{
components: [
{
internalType: "address",
name: "asset",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetAddressInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "enum XCM.TransferType",
name: "assetsTransferType",
type: "uint8"
},
{
internalType: "uint8",
name: "remoteFeesIdIndex",
type: "uint8"
},
{
internalType: "enum XCM.TransferType",
name: "feesTransferType",
type: "uint8"
},
{
internalType: "bytes",
name: "customXcmOnDest",
type: "bytes"
}
],
name: "transferAssetsUsingTypeAndThenAddress",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "dest",
type: "tuple"
},
{
components: [
{
internalType: "address",
name: "asset",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetAddressInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "uint8",
name: "remoteFeesIdIndex",
type: "uint8"
},
{
internalType: "bytes",
name: "customXcmOnDest",
type: "bytes"
},
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "remoteReserve",
type: "tuple"
}
],
name: "transferAssetsUsingTypeAndThenAddress",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "dest",
type: "tuple"
},
{
components: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "location",
type: "tuple"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetLocationInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "enum XCM.TransferType",
name: "assetsTransferType",
type: "uint8"
},
{
internalType: "uint8",
name: "remoteFeesIdIndex",
type: "uint8"
},
{
internalType: "enum XCM.TransferType",
name: "feesTransferType",
type: "uint8"
},
{
internalType: "bytes",
name: "customXcmOnDest",
type: "bytes"
}
],
name: "transferAssetsUsingTypeAndThenLocation",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "dest",
type: "tuple"
},
{
components: [
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "location",
type: "tuple"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct XCM.AssetLocationInfo[]",
name: "assets",
type: "tuple[]"
},
{
internalType: "uint8",
name: "remoteFeesIdIndex",
type: "uint8"
},
{
internalType: "bytes",
name: "customXcmOnDest",
type: "bytes"
},
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct XCM.Location",
name: "remoteReserve",
type: "tuple"
}
],
name: "transferAssetsUsingTypeAndThenLocation",
outputs: [],
stateMutability: "nonpayable",
type: "function"
}
];
// src/contract/contracts/XcmPrecompile/XcmPrecompile.ts
var XCM_PRECOMPILE_ADDRESS = "0x000000000000000000000000000000000000081A";
function XcmPrecompile() {
return {
transferAssetsToPara20: () => ({
build: ({ destinationAddress, asset, destination }) => {
return new ContractConfig({
address: XCM_PRECOMPILE_ADDRESS,
abi: XCM_ABI,
args: [
destination.parachainId,
destinationAddress,
[[asset.address, asset.amount]],
0
],
func: "transferAssetsToPara20",
module: "Xcm"
});
}
}),
transferAssetsToPara32: () => ({
build: ({ destinationAddress, asset, destination }) => {
return new ContractConfig({
address: XCM_PRECOMPILE_ADDRESS,
abi: XCM_ABI,
args: [
destination.parachainId,
u8aToHex2(decodeAddress2(destinationAddress)),
[[asset.address, asset.amount]],
0
],
func: "transferAssetsToPara32",
module: "Xcm"
});
}
})
};
}
// src/contract/contracts/Xtokens/Xtokens.ts
import { formatAssetIdToERC20 } from "@moonbeam-network/xcm-utils";
import { u8aToHex as u8aToHex4 } from "@polkadot/util";
import { decodeAddress as decodeAddress4, evmToAddress } from "@polkadot/util-crypto";
// src/builder.utils.ts
import { EvmParachain } from "@moonbeam-network/xcm-types";
import { u8aToHex as u8aToHex3 } from "@polkadot/util";
import { decodeAddress as decodeAddress3 } from "@polkadot/util-crypto";
function getPrecompileDestinationInterior(destination, address) {
if (!address) {
return [`0x0000000${destination.parachainId.toString(16)}`];
}
const accountType = EvmParachain.is(destination) ? "03" : "01";
const acc = `0x${accountType}${u8aToHex3(
decodeAddress3(address),
-1,
false
)}00`;
return destination.parachainId ? [`0x0000000${destination.parachainId.toString(16)}`, acc] : [acc];
}
// src/contract/contracts/Xtokens/XtokensABI.ts
var XTOKENS_ABI = [
{
inputs: [
{
internalType: "address",
name: "currencyAddress",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
},
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct Xtokens.Multilocation",
name: "destination",
type: "tuple"
},
{
internalType: "uint64",
name: "weight",
type: "uint64"
}
],
name: "transfer",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
components: [
{
internalType: "address",
name: "currencyAddress",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
internalType: "struct Xtokens.Currency[]",
name: "currencies",
type: "tuple[]"
},
{
internalType: "uint32",
name: "feeItem",
type: "uint32"
},
{
components: [
{
internalType: "uint8",
name: "parents",
type: "uint8"
},
{
internalType: "bytes[]",
name: "interior",
type: "bytes[]"
}
],
internalType: "struct Xtokens.Multilocation",
name: "destination",
type: "tuple"
},
{
internalType: "uint64",
name: "weight",
type: "uint64"
}
],
name: "transferMultiCurrencies",
outputs: [],
stateMutability: "nonpayable",
type: "function"
}
];
// src/contract/contracts/Xtokens/Xtokens.ts
var U_64_MAX = 18446744073709551615n;
var XTOKENS_CONTRACT_ADDRESS = "0x0000000000000000000000000000000000000804";
function Xtokens() {
return {
transfer: (weight = U_64_MAX) => ({
build: ({ destinationAddress, asset, destination }) => new ContractConfig({
address: XTOKENS_CONTRACT_ADDRESS,
abi: XTOKENS_ABI,
args: [
asset.address ? formatAssetIdToERC20(asset.address) : asset.getAssetId(),
asset.amount,
getDestinationMultilocation(destinationAddress, destination),
weight
],
func: "transfer",
module: "Xtokens"
})
}),
transferMultiCurrencies: (shouldTransferAssetPrecedeFeeAsset = true, weight = U_64_MAX) => ({
build: ({ asset, destination, destinationAddress, fee }) => {
const transferAsset = [
asset.address ? formatAssetIdToERC20(asset.address) : asset.getAssetId(),
asset.amount
];
const feeAsset = [
fee.address ? formatAssetIdToERC20(fee.address) : fee.getAssetId(),
fee.amount
];
const assets3 = shouldTransferAssetPrecedeFeeAsset ? [transferAsset, feeAsset] : [feeAsset, transferAsset];
const feeAssetIndex = shouldTransferAssetPrecedeFeeAsset ? 1 : 0;
return new ContractConfig({
address: XTOKENS_CONTRACT_ADDRESS,
abi: XTOKENS_ABI,
args: [
assets3,
feeAssetIndex,
getDestinationMultilocation(destinationAddress, destination),
weight
],
func: "transferMultiCurrencies",
module: "Xtokens"
});
}
}),
transferWithEvmTo32: (weight = U_64_MAX) => ({
build: ({ destinationAddress, asset, destination }) => {
const multilocation = getDestinationMultilocationForPrecompileDestination(
destinationAddress,
destination
);
return new ContractConfig({
address: XTOKENS_CONTRACT_ADDRESS,
abi: XTOKENS_ABI,
args: [
asset.address ? formatAssetIdToERC20(asset.address) : asset.getAssetId(),
asset.amount,
multilocation,
weight
],
func: "transfer",
module: "Xtokens"
});
}
})
};
}
function getDestinationMultilocationForPrecompileDestination(address, destination) {
const accountType = "01";
const substrateAddress = evmToAddress(address);
const acc = `0x${accountType}${u8aToHex4(
decodeAddress4(substrateAddress),
-1,
false
)}00`;
return [
1,
destination.parachainId ? [`0x0000000${destination.parachainId.toString(16)}`, acc] : [acc]
];
}
function getDestinationMultilocation(address, destination) {
const interior = getPrecompileDestinationInterior(destination, address);
return [1, interior];
}
// src/contract/ContractBuilder.ts
function ContractBuilder() {
return {
Xtokens,
XcmPrecompile
};
}
// src/balance/Erc20Abi.ts
var ERC20_ABI = [
{
constant: true,
inputs: [],
name: "name",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_spender",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "approve",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_from",
type: "address"
},
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transferFrom",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "decimals",
outputs: [
{
name: "",
type: "uint8"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
name: "balance",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [],
name: "symbol",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transfer",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
},
{
name: "_spender",
type: "address"
}
],
name: "allowance",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
payable: true,
stateMutability: "payable",
type: "fallback"
},
{
anonymous: false,
inputs: [
{
indexed: true,
name: "owner",
type: "address"
},
{
indexed: true,
name: "spender",
type: "address"
},
{
indexed: false,
name: "value",
type: "uint256"
}
],
name: "Approval",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
name: "from",
type: "address"
},
{
indexed: true,
name: "to",
type: "address"
},
{
indexed: false,
name: "value",
type: "uint256"
}
],
name: "Transfer",
type: "event"
}
];
// src/balance/BalanceBuilder.ts
function BalanceBuilder() {
return {
evm,
substrate
};
}
function evm() {
return {
erc20,
native
};
}
function erc20() {
return {
build: ({ asset, address }) => {
if (!asset.address) {
throw new Error(`Asset ${asset.key} has no address`);
}
return new ContractConfig({
address: asset.address,
abi: ERC20_ABI,
args: [address],
func: "balanceOf",
module: "Erc20"
});
}
};
}
function native() {
return {
build: ({ address }) => {
return new EvmQueryConfig({
func: "getBalance",
args: [{ address }]
});
}
};
}
function substrate() {
return {
assets: assets2,
foreignAssets: foreignAssets2,
system,
tokens
};
}
function assets2() {
return {
account: () => ({
build: ({ address, asset }) => new SubstrateQueryConfig({
module: "assets",
func: "account",
args: [asset.getBalanceAssetId(), address],
transform: async (response) => response.unwrapOrDefault().balance.toBigInt()
})
})
};
}
function foreignAssets2() {
return {
account: () => ({
build: ({ address, asset }) => {
if (!asset.address) {
throw new Error(
"Asset address is needed to calculate balance with foreignAssets.account function"
);
}
const multilocation = {
parents: 2,
interior: {
X2: [
{ GlobalConsensus: { ethereum: { chainId: 1 } } },
getExtrinsicAccount(asset.address)
]
}
};
return new SubstrateQueryConfig({
module: "foreignAssets",
func: "account",
args: [multilocation, address],
transform: async (response) => response.unwrapOrDefault().balance.toBigInt()
});
}
})
};
}
function system() {
return {
account: () => ({
build: ({ address }) => new SubstrateQueryConfig({
module: "system",
func: "account",
args: [address],
transform: async (response) => calculateSystemAccountBalance(response)
})
}),
accountEquilibrium: () => ({
build: ({ address, asset }) => new SubstrateQueryConfig({
module: "system",
func: "account",
args: [address],
transform: async (response) => {
if (response.data.isEmpty) {
return 0n;
}
const res = response.data.toJSON();
let balances;
if (Array.isArray(res)) {
balances = res;
}
if (Array.isArray(res?.v0?.balance)) {
balances = res.v0.balance;
}
if (!balances) {
throw new Error("Can't get balance from Equilibrium chain");
}
const balance = balances.find(
([assetId]) => assetId === asset.getBalanceAssetId()
);
if (!balance) {
return 0n;
}
return BigInt(balance[1].positive);
}
})
}),
accountEvmTo32: () => ({
build: ({ address }) => {
const substrateAddress = evmToAddress2(address);
return new SubstrateQueryConfig({
module: "system",
func: "account",
args: [substrateAddress],
transform: async (response) => calculateSystemAccountBalance(response)
});
}
})
};
}
function tokens() {
return {
accounts: () => ({
build: ({ address, asset }) => new SubstrateQueryConfig({
module: "tokens",
func: "accounts",
args: [address, asset.getBalanceAssetId()],
transform: async ({
free,
frozen
}) => BigInt(free.sub(frozen).toString())
})
})
};
}
async function calculateSystemAccountBalance(response) {
const balance = response.data;
const free = BigInt(balance.free.toString());
const frozen = balance.miscFrozen ?? balance.frozen;
const frozenMinusReserved = BigInt(frozen.sub(balance.reserved).toString());
const locked = frozenMinusReserved < 0n ? 0n : frozenMinusReserved;
return free - locked;
}
// src/extrinsic/pallets/eqBalances/eqBalances.ts
var pallet = "eqBalances";
function eqBalances() {
return {
xcmTransfer: () => ({
build: ({ destinationAddress, asset, destination }) => new ExtrinsicConfig({
module: pallet,
func: "xcmTransfer",
getArgs: () => [
asset.getAssetId(),
asset.amount,
{
parents: 1,
interior: {
X2: [
{
Parachain: destination.parachainId
},
getExtrinsicAccount(destinationAddress)
]
}
},
"ThisAccWillPay" /* ThisAccWillPay */
]
})
}),
transferXcm: () => ({
build: ({ destinationAddress: address, asset, destination, fee }) => new ExtrinsicConfig({
module: pallet,
func: "transferXcm",
getArgs: () => {
const amountWithoutFee = asset.amount - fee.amount > 0n ? asset.amount - fee.amount : 0n;
return [
[
asset.getAssetId(),
asset.isSame(fee) ? amountWithoutFee : asset.amount
],
[fee.getAssetId(), fee.amount],
{
parents: 1,
interior: {
X2: [
{
Parachain: destination.parachainId
},
getExtrinsicAccount(address)
]
}
}
];
}
})
})
};
}
// src/extrinsic/pallets/polkadotXcm/polkadotXcm.util.ts
function getPolkadotXcmExtrinsicArgs({
asset,
destinationAddress,
destination,
func,
parents = 1,
feeIndex = 0
}) {
const version = getExtrinsicArgumentVersion(func);
return [
{
[version]: normalizeX1(version, {
parents,
interior: {
X1: {
Parachain: destination.parachainId
}
}
})
},
{
[version]: normalizeX1(version, {
parents: 0,
interior: {
X1: getExtrinsicAccount(destinationAddress)
}
})
},
{
[version]: asset
},
feeIndex,
"Unlimited"
];
}
function shouldFeeAssetPrecedeAsset({
asset,
fee
}) {
const assetIdNumber = Number(asset.getAssetId());
const feeAssetIdNumber = Number(fee.getAssetId());
if (Number.isNaN(assetIdNumber) || Number.isNaN(feeAssetIdNumber)) {
return false;
}
return assetIdNumber > feeAssetIdNumber;
}
// src/extrinsic/pallets/polkadotXcm/polkadotXcm.ts
var pallet2 = "polkadotXcm";
function polkadotXcm() {
return {
limitedReserveTransferAssets: () => {
const func = "limitedReserveTransferAssets";
return {
here: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: [
{
id: normalizeConcrete(version, {
parents: 0,
interior: "Here"
}),
fun: {
Fungible: params.asset.amount
}
}
]
});
}
})
}),
X1: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: [
{
id: normalizeConcrete(
version,
normalizeX1(version, {
parents: 0,
interior: {
X1: {
PalletInstance: params.asset.getAssetPalletInstance()
}
}
})
),
fun: {
Fungible: params.asset.amount
}
}
]
});
}
})
}),
X2: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const isAssetDifferent = !params.asset.isSame(params.fee);
const version = getExtrinsicArgumentVersion(extrinsicFunction);
const assets3 = [
{
id: normalizeConcrete(version, {
parents: 0,
interior: {
X2: [
{
PalletInstance: params.asset.getAssetPalletInstance()
},
{
GeneralIndex: params.asset.getAssetId()
}
]
}
}),
fun: {
Fungible: params.asset.amount
}
}
];
const shouldFeeAssetPrecede = shouldFeeAssetPrecedeAsset(params);
if (isAssetDifferent) {
const feeAsset = {
id: normalizeConcrete(version, {
parents: 0,
interior: {
X2: [
{
PalletInstance: params.fee.getAssetPalletInstance()
},
{
GeneralIndex: params.fee.getAssetId()
}
]
}
}),
fun: {
Fungible: params.fee.amount
}
};
if (shouldFeeAssetPrecede) {
assets3.unshift(feeAsset);
} else {
assets3.push(feeAsset);
}
}
return getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: assets3,
feeIndex: isAssetDifferent && !shouldFeeAssetPrecede ? 1 : 0
});
}
})
})
};
},
limitedReserveWithdrawAssets: () => {
const func = "limitedReserveWithdrawAssets";
return {
X2: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: [
{
id: normalizeConcrete(version, {
parents: 1,
interior: {
X2: [
{
Parachain: params.destination.parachainId
},
{
PalletInstance: params.asset.getAssetPalletInstance()
}
]
}
}),
fun: {
Fungible: params.asset.amount
}
}
]
});
}
})
})
};
},
transferAssets: () => {
const func = "transferAssets";
return {
here: (parents = 0) => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: [
{
id: normalizeConcrete(version, {
parents,
interior: "Here"
}),
fun: {
Fungible: params.asset.amount
}
}
]
});
}
})
}),
X2AndFeeHere: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: [
{
id: normalizeConcrete(version, {
parents: 0,
interior: {
X2: [
{
PalletInstance: params.asset.getAssetPalletInstance()
},
{
GeneralIndex: params.asset.getAssetId()
}
]
}
}),
fun: {
Fungible: params.asset.amount
}
},
// Fee Asset
{
id: normalizeConcrete(version, {
parents: 1,
interior: "Here"
}),
fun: {
Fungible: params.fee.amount
}
}
],
feeIndex: 1
});
}
})
})
};
},
transferAssetsUsingTypeAndThen: () => {
const func = "transferAssetsUsingTypeAndThen";
return {
here: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return [
{
[version]: {
parents: 1,
interior: {
X1: [
{
Parachain: params.destination.parachainId
}
]
}
}
},
{
[version]: [
{
id: {
parents: 0,
interior: "Here"
},
fun: {
Fungible: params.asset.amount
}
}
]
},
"LocalReserve",
{
[version]: {
parents: 0,
interior: "Here"
}
},
"LocalReserve",
{
[version]: [
{
DepositAsset: {
assets: {
Wild: { AllCounted: 1 }
},
beneficiary: {
parents: 0,
interior: {
X1: [
getExtrinsicAccount(params.destinationAddress)
]
}
}
}
}
]
},
"Unlimited"
];
}
})
}),
// TODO we could pass a parameter globalConsensus in the chain asset if we need a different one
globalConsensusEthereum: () => ({
build: (params) => new ExtrinsicConfig({
module: pallet2,
func,
getArgs: (extrinsicFunction) => {
if (!params.asset.address) {
throw new Error(
"Asset address is needed for transferAssetsUsingTypeAndThen.globalConsensus function"
);
}
const version = getExtrinsicArgumentVersion(extrinsicFunction);
return [
{
[version]: {
parents: 1,
interior: {
X1: [
{
Parachain: params.destination.parachainId
}
]
}
}
},
{
[version]: [
{
id: normalizeConcrete(version, {
parents: 2,
interior: {
X2: [
{ globalConsensus: { Ethereum: { ChainId: 1 } } },
getExtrinsicAccount(params.asset.address)
]
}
}),
fun: { fungible: params.asset.amount }
}
]
},
"LocalReserve",
{
[version]: normalizeConcrete(version, {
parents: 2,
interior: {
X2: [
{ globalConsensus: { Ethereum: { ChainId: 1 } } },
getExtrinsicAccount(params.asset.address)
]
}
})
},
"LocalReserve",
{
[version]: [
{
DepositAsset: {
assets: {
Wild: { AllCounted: 1 }
},
beneficiary: normalizeX1(version, {
parents: 0,
interior: {
X1: getExtrinsicAccount(
params.destinationAddress
)
}
})
}
}
]
},
"Unlimited"
];
}
})
})
};
}
};
}
// src/extrinsic/pallets/xTokens/xTokens.utils.ts
function getWeight() {
return "Unlimited";
}
function getDestination(version, address, destination) {
return {
[version]: {
parents: 1,
interior: {
X2: [
{
Parachain: destination.parachainId
},
getExtrinsicAccount(address)
]
}
}
};
}
// src/extrinsic/pallets/xTokens/xTokens.ts
var pallet3 = "xTokens";
function xTokens() {
return {
transfer: () => ({
build: ({ destinationAddress, asset, destination }) => new ExtrinsicConfig({
module: pallet3,
func: "transfer",
getArgs: (func) => {
const destIndex = 2;
const version = getExtrinsicArgumentVersion(func, destIndex);
return [
asset.getAssetId(),
asset.amount,
getDestination(version, destinationAddress, destination),
getWeight()
];
}
})
}),
transferMultiAsset: (originParachainId) => {
const funcName = "transferMultiasset";
const destIndex = 1;
return {
here: () => ({
build: ({ destinationAddress: address, asset, destination }) => new ExtrinsicConfig({
module: pallet3,
func: funcName,
getArgs: (func) => {
const version = getExtrinsicArgumentVersion(func, destIndex);
return [
{
[version]: {
id: normalizeConcrete(version, {
parents: 0,
interior: "Here"
}),
fun: {
Fungible: asset.amount
}
}
},
getDestination(version, address, destination),
getWeight()
];
}
})
}),
X1: () => ({
build: ({ destinationAddress: address, asset, destination }) => new ExtrinsicConfig({
module: pallet3,
func: funcName,
getArgs: (func) => {
const version = getExtrinsicArgumentVersion(func, destIndex);
return [
{
[version]: {
id: normalizeConcrete(
version,
normalizeX1(version, {
parents: 1,
interior: {
X1: {
Parachain: originParachainId
}
}