diff --git a/__tests__/teleport.test.ts b/__tests__/teleport.test.ts index 4edfac7..62ae7a0 100644 --- a/__tests__/teleport.test.ts +++ b/__tests__/teleport.test.ts @@ -72,14 +72,15 @@ describe("TransactionRouter Cross-chain teleport", () => { provider: assetHubProvider, }); - const receiverBalanceBefore = await getBalance(rococoApi, bob.address); - const senderBalanceBefore = await getBalance(assetHubApi, alice.address); + const senderBalanceBefore = await getBalance(rococoApi, alice.address); + const receiverBalanceBefore = await getBalance(assetHubApi, bob.address); - const amount = 4000000000000; + const amount = 4 * Math.pow(10, 12); // 4 KSM const assetReserveChainId = 0; const asset: Fungible = { multiAsset: { + parents: 0, interior: "Here" }, amount @@ -92,7 +93,21 @@ describe("TransactionRouter Cross-chain teleport", () => { assetReserveChainId, asset ); - }); + + // Delay a bit just to be safe. + await delay(5000); + + const senderBalanceAfter = await getBalance(rococoApi, alice.address); + const receiverBalanceAfter = await getBalance(assetHubApi, bob.address); + + // Expect the balance to be possibly lower than `senderBalanceBefore - amount` since + // the fees also need to be paid. + expect(Number(senderBalanceAfter)).toBeLessThanOrEqual(senderBalanceBefore - amount); + + // Tolerance for fee payment on the receiver side. + const tolerance = 50000000; + expect(Number(receiverBalanceAfter)).toBeGreaterThanOrEqual((receiverBalanceBefore + amount) - tolerance); + }, 120000); }); const addNetwork = async ( @@ -106,9 +121,11 @@ const addNetwork = async ( }; const getBalance = async (api: ApiPromise, who: string): Promise => { - const maybeBalance: any = (await api.query.system.account(who)).toJSON(); + const maybeBalance: any = (await api.query.system.account(who)).toPrimitive(); if (maybeBalance && maybeBalance.data) { return maybeBalance.data.free; } return 0; -} \ No newline at end of file +} + +const delay = (ms: number) => new Promise(res => setTimeout(res, ms)); diff --git a/src/utils/index.ts b/src/utils/index.ts index fe746e7..5bf97e3 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -27,6 +27,6 @@ export const getParaId = async (api: ApiPromise): Promise => { const response = (await api.query.parachainInfo.parachainId()).toJSON(); return Number(response); } else { - return -1; + return 0; } } diff --git a/src/utils/transactionRouter/index.ts b/src/utils/transactionRouter/index.ts index 9ada579..f4be613 100644 --- a/src/utils/transactionRouter/index.ts +++ b/src/utils/transactionRouter/index.ts @@ -6,7 +6,7 @@ import TransferAsset from "./transferAsset"; import { Fungible, Receiver, Sender } from "./types"; import IdentityContract from "../../../types/contracts/identity"; import { AccountType } from "../../../types/types-arguments/identity"; -import { TeleportableRoute, teleportableRoutes } from "../../../teleportableRoutes"; +import { TeleportableRoute, teleportableRoutes } from "./teleportableRoutes"; import { getParaId } from ".."; // Responsible for handling all the transfer logic. @@ -64,14 +64,18 @@ class TransactionRouter { const originParaId = await getParaId(originApi); const destParaId = await getParaId(destApi); - const teleportableRoute: TeleportableRoute = { - relayChain: process.env.RELAY_CHAIN ? process.env.RELAY_CHAIN : "", - destParaId: destParaId, + const maybeTeleportableRoute: TeleportableRoute = { + relayChain: process.env.RELAY_CHAIN ? process.env.RELAY_CHAIN : "rococo", originParaId: originParaId, - xcAsset: asset.multiAsset + destParaId: destParaId, + multiAsset: asset.multiAsset }; - // if (TeleportableRoutes.indexOf()) + if (teleportableRoutes.some(route => JSON.stringify(route) === JSON.stringify(maybeTeleportableRoute))) { + // The asset is allowed to be teleported between the origin and the destination. + await TeleportTransfer.send(originApi, destApi, sender.keypair, receiver, asset); + return; + } // The sender chain is the reserve chain of the asset. This will simply use the existing // `limitedReserveTransferAssets` extrinsic diff --git a/src/utils/transactionRouter/reserveTransfer.test.ts b/src/utils/transactionRouter/reserveTransfer.test.ts index 8b0b345..4db39b4 100644 --- a/src/utils/transactionRouter/reserveTransfer.test.ts +++ b/src/utils/transactionRouter/reserveTransfer.test.ts @@ -601,7 +601,7 @@ describe("TransactionRouter unit tests", () => { it("Works from parachain to relaychain", () => { const bob = ecdsaKeyring.addFromUri("//Bob"); - const destParaId = -1; + const destParaId = 0; const beneficiary: Receiver = { addressRaw: bob.addressRaw, network: 1, @@ -961,7 +961,7 @@ describe("TransactionRouter unit tests", () => { it("Works with relaychain being the reserve chain", () => { const bob = ecdsaKeyring.addFromUri("//Bob"); - const reserveParaId = -1; + const reserveParaId = 0; const destParaId = 2002; const beneficiary: Receiver = { addressRaw: bob.addressRaw, diff --git a/src/utils/transactionRouter/reserveTransfer.ts b/src/utils/transactionRouter/reserveTransfer.ts index 9073a3c..1d875ec 100644 --- a/src/utils/transactionRouter/reserveTransfer.ts +++ b/src/utils/transactionRouter/reserveTransfer.ts @@ -19,7 +19,7 @@ class ReserveTransfer { // eslint-disable-next-line no-prototype-builtins const isOriginPara = originApi.query.hasOwnProperty("parachainInfo"); - const destination = getDestination(isOriginPara, destParaId, destParaId >= 0); + const destination = getDestination(isOriginPara, destParaId, destParaId > 0); const beneficiary = getTransferBeneficiary(receiver); const multiAsset = getMultiAsset(asset); @@ -195,7 +195,7 @@ class ReserveTransfer { // NOTE: we use parse and stringify to make a hard copy of the asset. const assetFromReservePerspective = JSON.parse(JSON.stringify(asset.multiAsset)); - if (destParaId >= 0) { + if (destParaId > 0) { // The location of the asset will always start with the parachain if the reserve is a parachain. this.assetFromReservePerspective(assetFromReservePerspective); } else { diff --git a/src/utils/transactionRouter/teleportTransfer.ts b/src/utils/transactionRouter/teleportTransfer.ts index 4890b79..fbc0d9c 100644 --- a/src/utils/transactionRouter/teleportTransfer.ts +++ b/src/utils/transactionRouter/teleportTransfer.ts @@ -7,7 +7,7 @@ import { getDestination, getMultiAsset, getTransferBeneficiary } from "."; class TeleportTransfer { public static async send( originApi: ApiPromise, - destinationApi: ApiPromise, + destApi: ApiPromise, sender: KeyringPair, receiver: Receiver, asset: Fungible @@ -21,9 +21,9 @@ class TeleportTransfer { // eslint-disable-next-line no-prototype-builtins const isOriginPara = originApi.query.hasOwnProperty("parachainInfo"); - const destParaId = await getParaId(destinationApi); + const destParaId = await getParaId(destApi); - const destination = getDestination(isOriginPara, destParaId, destParaId >= 0); + const destination = getDestination(isOriginPara, destParaId, destParaId > 0); const beneficiary = getTransferBeneficiary(receiver); const multiAsset = getMultiAsset(asset); diff --git a/teleportableRoutes.ts b/src/utils/transactionRouter/teleportableRoutes.ts similarity index 52% rename from teleportableRoutes.ts rename to src/utils/transactionRouter/teleportableRoutes.ts index 12f9c42..55e2625 100644 --- a/teleportableRoutes.ts +++ b/src/utils/transactionRouter/teleportableRoutes.ts @@ -1,11 +1,13 @@ // File containing all the possible assets on all possible routes that support asset // teleportation. +import AssetRegistry from "../assetRegistry"; + export type TeleportableRoute = { relayChain: string, originParaId: number, destParaId: number, - xcAsset: string + multiAsset: any }; export const teleportableRoutes: TeleportableRoute[] = [ @@ -13,18 +15,27 @@ export const teleportableRoutes: TeleportableRoute[] = [ relayChain: "polkadot", originParaId: 0, destParaId: 1000, - xcAsset: "[{\"network\":\"polkadot\"},\"here\"]" + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse('[{"network":"polkadot"},"here"]'), + false, + ), }, { relayChain: "kusama", originParaId: 0, destParaId: 1000, - xcAsset: "[{\"network\":\"kusama\"},\"here\"]" + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse('[{"network":"kusama"},"here"]'), + false, + ), }, { relayChain: "rococo", originParaId: 0, destParaId: 1000, - xcAsset: "[{\"network\":\"kusama\"},\"here\"]" - } + multiAsset: AssetRegistry.xcmInteriorToMultiAsset( + JSON.parse('[{"network":"rocooc"},"here"]'), + false, + ), + }, ];