From d427b17df5b82360c69390287c463068a04fecec Mon Sep 17 00:00:00 2001 From: Sergej Sakac Date: Mon, 28 Aug 2023 22:26:34 +0200 Subject: [PATCH] bydirectional teleport --- src/pages/transfer.tsx | 50 ++++++++++------ src/utils/transactionRouter/index.ts | 17 ++++-- .../transactionRouter/teleportableRoutes.ts | 60 +++++++++++++++++++ 3 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/pages/transfer.tsx b/src/pages/transfer.tsx index cc23165..c7c3163 100644 --- a/src/pages/transfer.tsx +++ b/src/pages/transfer.tsx @@ -18,7 +18,7 @@ import { AccountType } from 'types/types-arguments/identity'; import AssetRegistry, { Asset } from '@/utils/assetRegistry'; import IdentityKey from '@/utils/identityKey'; import KeyStore from '@/utils/keyStore'; -import TransactionRouter from '@/utils/transactionRouter'; +import TransactionRouter, { isTeleport } from '@/utils/transactionRouter'; import { chainsSupportingXcmExecute, RELAY_CHAIN } from '@/consts'; import { useRelayApi } from '@/contexts/RelayApi'; @@ -26,6 +26,7 @@ import { useToast } from '@/contexts/Toast'; import { useIdentity } from '@/contracts'; import { useAddressBook } from '@/contracts/addressbook/context'; import { getTeleportableAssets } from '@/utils/transactionRouter/teleportableRoutes'; +import { Fungible } from '@/utils/transactionRouter/types'; const TransferPage = () => { const { @@ -190,19 +191,30 @@ const TransferPage = () => { }, [recipientId]); // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars - const isTransferSupported = ( - originParaId: number, - reserveParaId: number - ): boolean => { + const isTransferSupported = (): boolean => { + if ( + sourceChainId === undefined || + destChainId === undefined || + selectedAssetXcmInterior === undefined + ) { + return false; + } + const reserveParaId = getParaIdFromXcmInterior(selectedAssetXcmInterior); // If the origin is the reserve chain that means that we can use the existing // `limitedReserveTransferAssets` or `limitedTeleportAssets` extrinsics which are // supported on all chains that have the xcm pallet. - if (originParaId == reserveParaId) { + if (sourceChainId == reserveParaId) { + return true; + } + + const isSourceParachain = sourceChainId > 0; + + if (isTeleport(sourceChainId, destChainId, getFungible(selectedAssetXcmInterior, isSourceParachain, 0))) { return true; } const isOriginSupportingLocalXCM = chainsSupportingXcmExecute.findIndex( - (chain) => chain.paraId == originParaId && chain.relayChain == RELAY_CHAIN + (chain) => chain.paraId == sourceChainId && chain.relayChain == RELAY_CHAIN ); // We only need the origin chain to support XCM for any other type of transfer to @@ -259,14 +271,7 @@ const TransferPage = () => { : AccountType.accountKey20, }, reserveChainId, - { - multiAsset: AssetRegistry.xcmInteriorToMultiAsset( - JSON.parse(selectedAssetXcmInterior.toString()), - isSourceParachain, - sourceChainId - ), - amount, - }, + getFungible(selectedAssetXcmInterior, isSourceParachain, amount), { originApi: await getApi(chains[sourceChainId].rpcUrls[rpcIndex]), destApi: await getApi(chains[destChainId].rpcUrls[rpcIndex]), @@ -276,7 +281,7 @@ const TransferPage = () => { ); }; - const getParaIdFromXcmInterior = (xcmInterior: any[]): number => { + const getParaIdFromXcmInterior = (xcmInterior: any): number => { if (xcmInterior.length > 1 && Object.hasOwn(xcmInterior[1], 'parachain')) { return xcmInterior[1].parachain; } else { @@ -290,10 +295,21 @@ const TransferPage = () => { return api; }; + const getFungible = (xcmInterior: any, isSourceParachain: boolean, amount: number): Fungible => { + return { + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse(xcmInterior.toString()), + isSourceParachain, + sourceChainId + ), + amount, + }; + } + const canTransfer = assetSelected && recipientId !== undefined && - isTransferSupported(sourceChainId, destChainId); + isTransferSupported(); return ( diff --git a/src/utils/transactionRouter/index.ts b/src/utils/transactionRouter/index.ts index 098c7f5..ce4ce7a 100644 --- a/src/utils/transactionRouter/index.ts +++ b/src/utils/transactionRouter/index.ts @@ -60,12 +60,7 @@ class TransactionRouter { const originParaId = sender.chain; const destParaId = receiver.chain; - if (teleportableRoutes.some(route => { - return process.env.RELAY_CHAIN ? process.env.RELAY_CHAIN : "rococo" === route.relayChain && - originParaId === route.originParaId && - destParaId === route.destParaId && - JSON.stringify(asset.multiAsset) === JSON.stringify(route.multiAsset) - })) { + if (isTeleport(originParaId, destParaId, asset)) { // The asset is allowed to be teleported between the origin and the destination. await TeleportTransfer.send( transferRpcApis.originApi, @@ -207,3 +202,13 @@ const ensureContainsXcmPallet = (api: ApiPromise) => { throw new Error("The blockchain does not support XCM"); } } + +// Returns whether the transfer is a teleport. +export const isTeleport = (originParaId: number, destParaId: number, asset: Fungible): boolean => { + return teleportableRoutes.some(route => { + return process.env.RELAY_CHAIN ? process.env.RELAY_CHAIN : "rococo" === route.relayChain && + originParaId === route.originParaId && + destParaId === route.destParaId && + JSON.stringify(asset.multiAsset) === JSON.stringify(route.multiAsset) + }); +} diff --git a/src/utils/transactionRouter/teleportableRoutes.ts b/src/utils/transactionRouter/teleportableRoutes.ts index 70f2917..4220559 100644 --- a/src/utils/transactionRouter/teleportableRoutes.ts +++ b/src/utils/transactionRouter/teleportableRoutes.ts @@ -33,6 +33,26 @@ export const teleportableRoutes: TeleportableRoute[] = [ false ) }, + { + relayChain: "polkadot", + originParaId: 1000, + destParaId: 0, + asset: { + asset: { + Token: "DOT" + }, + name: "DOT", + symbol: "DOT", + decimals: 10, + xcmInteriorKey: '[{"network":"polkadot"},"here"]', + inferred: true, + confidence: 0 + }, + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse('[{"network":"polkadot"},"here"]'), + false + ) + }, { relayChain: "kusama", originParaId: 0, @@ -53,6 +73,26 @@ export const teleportableRoutes: TeleportableRoute[] = [ false ) }, + { + relayChain: "kusama", + originParaId: 1000, + destParaId: 0, + asset: { + asset: { + Token: "KSM" + }, + name: "KSM", + symbol: "KSM", + decimals: 12, + xcmInteriorKey: '[{"network":"kusama"},"here"]', + inferred: true, + confidence: 0 + }, + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse('[{"network":"kusama"},"here"]'), + false + ) + }, { relayChain: "rococo", originParaId: 0, @@ -73,6 +113,26 @@ export const teleportableRoutes: TeleportableRoute[] = [ false ) }, + { + relayChain: "rococo", + originParaId: 1000, + destParaId: 0, + asset: { + asset: { + Token: "ROC" + }, + name: "ROC", + symbol: "ROC", + decimals: 12, + xcmInteriorKey: '[{"network":"rococo"},"here"]', + inferred: true, + confidence: 0 + }, + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse('[{"network":"rococo"},"here"]'), + false + ) + } ]; export const getTeleportableAssets = (originChainId: number, destChainId: number): Asset[] => {