Skip to content

Commit

Permalink
feat: support construction of teleports for parachains' primary nativ…
Browse files Browse the repository at this point in the history
…e assets to AssetHub (#267)
  • Loading branch information
marshacb authored Aug 30, 2023
1 parent 41574f7 commit f1c2970
Show file tree
Hide file tree
Showing 14 changed files with 529 additions and 91 deletions.
58 changes: 58 additions & 0 deletions examples/paraToSystemParachainPrimaryNative.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* When importing from @substrate/asset-transfer-api it would look like the following
*
* import { AssetsTransferApi, constructApiPromise } from '@substrate/asset-transfer-api'
*/
import { AssetsTransferApi, constructApiPromise } from '../src';
import { TxResult } from '../src/types';
import { GREEN, PURPLE, RESET } from './colors';

/**
* In this example we are creating a call to send MOVR from a Moonriver (Parachain) account
* to a Kusama Asset Hub (System Parachain) account, where the `xcmVersion` is set to 3, and `isLimited` is false declaring that
* it will allow `unlimited` weight for the tx.
*
* NOTE: When `isLimited` is true it will expect for refTime and proofSize to be provided as additional arguments.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise(
'wss://moonriver.api.onfinality.io/public-ws'
);
const assetApi = new AssetsTransferApi(api, specName, safeXcmVersion);
let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
'1000',
'0xc4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a063',
['movr'], // Note: since it is the primary asset of Moonriver that is being sent to AssetHub, it will be a `teleportAssets` call
['1000000000000'],
{
format: 'call',
isLimited: false,
xcmVersion: 3,
}
);

console.log(
`${PURPLE}The following call data that is returned:\n${GREEN}${JSON.stringify(
callInfo,
null,
4
)}`
);
} catch (e) {
console.error(e);
throw Error(e as string);
}

const decoded = assetApi.decodeExtrinsic(callInfo.tx, 'call');
console.log(
`\n${PURPLE}The following decoded tx:\n${GREEN} ${JSON.stringify(
JSON.parse(decoded),
null,
4
)}${RESET}`
);
};

main().finally(() => process.exit());
25 changes: 25 additions & 0 deletions src/AssetsTransferApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ describe('AssetTransferAPI', () => {
Direction.RelayToSystem,
AssetType.Native,
false,
false,
relayAssetsApi.registry
);

Expand All @@ -217,6 +218,7 @@ describe('AssetTransferAPI', () => {
Direction.RelayToPara,
AssetType.Native,
false,
false,
relayAssetsApi.registry
);

Expand All @@ -232,6 +234,7 @@ describe('AssetTransferAPI', () => {
Direction.SystemToRelay,
AssetType.Native,
false,
false,
systemAssetsApi.registry
);

Expand All @@ -247,6 +250,7 @@ describe('AssetTransferAPI', () => {
Direction.SystemToSystem,
AssetType.Native,
false,
false,
systemAssetsApi.registry
);

Expand All @@ -261,6 +265,7 @@ describe('AssetTransferAPI', () => {
Direction.SystemToSystem,
AssetType.Foreign,
true,
false,
systemAssetsApi.registry
);

Expand All @@ -278,6 +283,7 @@ describe('AssetTransferAPI', () => {
Direction.SystemToPara,
AssetType.Foreign,
true,
false,
systemAssetsApi.registry
);

Expand All @@ -293,6 +299,7 @@ describe('AssetTransferAPI', () => {
Direction.SystemToPara,
AssetType.Foreign,
true,
false,
systemAssetsApi.registry
);

Expand All @@ -308,6 +315,7 @@ describe('AssetTransferAPI', () => {
Direction.ParaToRelay,
AssetType.Foreign,
false,
false,
moonriverAssetsApi.registry
);

Expand All @@ -323,6 +331,21 @@ describe('AssetTransferAPI', () => {
Direction.ParaToSystem,
AssetType.Foreign,
true,
false,
moonriverAssetsApi.registry
);

expect(assetCallType).toEqual('Teleport');
});
it('Should correctly return Teleport when sending the parachains native asset', () => {
const assetCallType = moonriverAssetsApi['fetchCallType'](
'2023',
'1000',
['movr'],
Direction.ParaToSystem,
AssetType.Foreign,
true,
true,
moonriverAssetsApi.registry
);

Expand All @@ -336,6 +359,7 @@ describe('AssetTransferAPI', () => {
Direction.ParaToSystem,
AssetType.Foreign,
true,
false,
moonriverAssetsApi.registry
);

Expand All @@ -351,6 +375,7 @@ describe('AssetTransferAPI', () => {
Direction.ParaToPara,
AssetType.Foreign,
true,
false,
moonriverAssetsApi.registry
);

Expand Down
20 changes: 16 additions & 4 deletions src/AssetsTransferApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
import { assetIdsContainRelayAsset } from './createXcmTypes/util/assetIdsContainsRelayAsset';
import { getAssetId } from './createXcmTypes/util/getAssetId';
import { getChainIdBySpecName } from './createXcmTypes/util/getChainIdBySpecName';
import { isParachainPrimaryNativeAsset } from './createXcmTypes/util/isParachainPrimaryNativeAsset';
import { isSystemChain } from './createXcmTypes/util/isSystemChain';
import { multiLocationAssetIsParachainsNativeAsset } from './createXcmTypes/util/multiLocationAssetIsParachainsNativeAsset';
import {
Expand Down Expand Up @@ -165,10 +166,17 @@ export class AssetsTransferApi {
);
const isForeignAssetsTransfer: boolean =
this.checkIsForeignAssetTransfer(assetIds);
const isPrimaryParachainNativeAsset = isParachainPrimaryNativeAsset(
registry,
_specName,
xcmDirection,
assetIds[0]
);
const xcmPallet = establishXcmPallet(
_api,
xcmDirection,
isForeignAssetsTransfer
isForeignAssetsTransfer,
isPrimaryParachainNativeAsset
);

/**
Expand Down Expand Up @@ -307,6 +315,7 @@ export class AssetsTransferApi {
registry,
isForeignAssetsTransfer,
isLiquidTokenTransfer,
isPrimaryParachainNativeAsset,
{
xcmVersion,
paysWithFeeDest,
Expand All @@ -326,6 +335,7 @@ export class AssetsTransferApi {
xcmDirection,
assetType,
isForeignAssetsTransfer,
isPrimaryParachainNativeAsset,
registry
);

Expand Down Expand Up @@ -715,6 +725,7 @@ export class AssetsTransferApi {
xcmDirection: Direction,
assetType: AssetType,
isForeignAssetsTransfer: boolean,
isParachainPrimaryNativeAsset: boolean,
registry: Registry
): AssetCallType {
// relay to system -> teleport
Expand Down Expand Up @@ -808,9 +819,10 @@ export class AssetsTransferApi {

// para to system only when the assets are native to origin -> teleport
if (
xcmDirection === Direction.ParaToSystem &&
!assetIdsContainRelayAsset(assetIds, registry) &&
originIsMultiLocationsNativeChain
(xcmDirection === Direction.ParaToSystem &&
!assetIdsContainRelayAsset(assetIds, registry) &&
originIsMultiLocationsNativeChain) ||
isParachainPrimaryNativeAsset
) {
return AssetCallType.Teleport;
}
Expand Down
11 changes: 7 additions & 4 deletions src/createXcmCalls/util/establishXcmPallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export enum XcmPalletName {
export const establishXcmPallet = (
api: ApiPromise,
direction?: Direction,
isForeignAssetsTransfer?: boolean
isForeignAssetsTransfer?: boolean,
isParachainPrimaryNativeAsset?: boolean
): XcmPalletName => {
// checks for the existence of the xTokens pallet
// for direction ParaToSystem, if it exists and the tx is
Expand All @@ -30,7 +31,8 @@ export const establishXcmPallet = (
isXTokensParaToSystemNonForeignAssetsPalletTx(
api,
direction,
isForeignAssetsTransfer
isForeignAssetsTransfer,
isParachainPrimaryNativeAsset
)
) {
return XcmPalletName.xTokens;
Expand All @@ -56,11 +58,12 @@ export const establishXcmPallet = (
const isXTokensParaToSystemNonForeignAssetsPalletTx = (
api: ApiPromise,
direction?: Direction,
isForeignAssetsTransfer?: boolean
isForeignAssetsTransfer?: boolean,
isParachainPrimaryNativeAsset?: boolean
): boolean => {
if (
isForeignAssetsTransfer != undefined &&
!isForeignAssetsTransfer &&
!isParachainPrimaryNativeAsset &&
direction &&
direction === Direction.ParaToSystem &&
api.tx.xTokens
Expand Down
Loading

0 comments on commit f1c2970

Please sign in to comment.