diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c211bc0..6e22134 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,7 @@ jobs: node-version: ${{ matrix.node-version }} - run: yarn install - run: 'CI=false yarn build' - - run: yarn test -- src/utils/transactionRouter/reserveTransfer.test.ts + - run: yarn test -- src/utils/xcmTransfer/reserveTransfer.test.ts transfer-asset-test: runs-on: ubuntu-latest strategy: @@ -76,7 +76,7 @@ jobs: node-version: ${{ matrix.node-version }} - run: yarn install - run: 'CI=false yarn build' - - run: yarn test -- src/utils/transactionRouter/transferAsset.test.ts + - run: yarn test -- src/utils/xcmTransfer/transferAsset.test.ts all: needs: [build] diff --git a/__tests__/crossChainRouter.test.ts b/__tests__/crossChainRouter.test.ts index e9671e7..9e5bc11 100644 --- a/__tests__/crossChainRouter.test.ts +++ b/__tests__/crossChainRouter.test.ts @@ -2,8 +2,8 @@ import { ApiPromise, Keyring, WsProvider } from "@polkadot/api"; import { KeyringPair } from "@polkadot/keyring/types"; import { u8aToHex } from '@polkadot/util'; -import TransactionRouter from "../src/utils/transactionRouter"; -import { Fungible, Receiver, Sender } from "../src/utils/transactionRouter/types"; +import TransactionRouter from "../src/utils/xcmTransfer"; +import { Fungible, Receiver, Sender } from "../src/utils/xcmTransfer/types"; import IdentityContractFactory from "../types/constructors/identity"; import IdentityContract from "../types/contracts/identity"; import { AccountType, ChainInfo } from "../types/types-arguments/identity"; diff --git a/__tests__/teleport.test.ts b/__tests__/teleport.test.ts index d73f5e0..9f8cc79 100644 --- a/__tests__/teleport.test.ts +++ b/__tests__/teleport.test.ts @@ -1,8 +1,8 @@ import { ApiPromise, Keyring, WsProvider } from "@polkadot/api"; import { KeyringPair } from "@polkadot/keyring/types"; -import TransactionRouter from "../src/utils/transactionRouter"; -import { Fungible, Receiver, Sender } from "../src/utils/transactionRouter/types"; +import TransactionRouter from "../src/utils/xcmTransfer"; +import { Fungible, Receiver, Sender } from "../src/utils/xcmTransfer/types"; import IdentityContractFactory from "../types/constructors/identity"; import IdentityContract from "../types/contracts/identity"; diff --git a/__tests__/transferAsset.test.ts b/__tests__/transferAsset.test.ts index 8476935..3037434 100644 --- a/__tests__/transferAsset.test.ts +++ b/__tests__/transferAsset.test.ts @@ -1,9 +1,9 @@ import { ApiPromise, Keyring, WsProvider } from "@polkadot/api"; import { KeyringPair } from "@polkadot/keyring/types"; -import { Fungible, Receiver, Sender } from "@/utils/transactionRouter/types"; +import { Fungible, Receiver, Sender } from "@/utils/xcmTransfer/types"; -import TransactionRouter from "../src/utils/transactionRouter"; +import TransactionRouter from "../src/utils/xcmTransfer"; import IdentityContractFactory from "../types/constructors/identity"; import IdentityContract from "../types/contracts/identity"; import { AccountType, ChainInfo } from "../types/types-arguments/identity"; diff --git a/chaindata/index.ts b/chaindata/index.ts new file mode 100644 index 0000000..8d50e3e --- /dev/null +++ b/chaindata/index.ts @@ -0,0 +1,39 @@ +import { gql, request } from 'graphql-request'; + +const graphqlUrl = 'https://squid.subsquid.io/chaindata/v/v4/graphql'; + +/// NOTE: this file is copied from the talisman chaindata. + +const chainsQuery = gql` + query chains { + chains(orderBy: sortIndex_ASC) { + id + name + paraId + relay { + id + } + rpcs { + url + } + } + } +`; + +const tokensQuery = gql` + query tokens { + tokens(orderBy: id_ASC) { + data + } + } +`; + +export const getChains = async (): Promise> => { + const result: any = await request(graphqlUrl, chainsQuery); + return result.chains; +}; + +export const getTokens = async (): Promise> => { + const result: any = await request(graphqlUrl, tokensQuery); + return result.tokens; +}; diff --git a/chaindata/ss58registry.ts b/chaindata/ss58registry.ts new file mode 100644 index 0000000..792eab8 --- /dev/null +++ b/chaindata/ss58registry.ts @@ -0,0 +1,15 @@ +import axios from 'axios'; + +const ss58registry = async (chainName: string): Promise => { + const ss58Registry = (await axios.get('https://raw.githubusercontent.com/paritytech/ss58-registry/main/ss58-registry.json')).data.registry; + + const result: any = ss58Registry.find((chain: any) => chain.network === chainName); + + if (!result) { + return null + } + + return result.prefix; +} + +export default ss58registry; \ No newline at end of file diff --git a/package.json b/package.json index 4f77381..76adfb1 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "aes-js": "^3.1.2", "axios": "^1.4.0", "clsx": "^1.1.1", + "graphql": "^16.8.0", + "graphql-request": "^6.1.0", "material-ui-confirm": "^3.0.9", "next": "^13.3.1", "react": "^18.2.0", diff --git a/src/contracts/identity/context.tsx b/src/contracts/identity/context.tsx index 238a914..02aba88 100644 --- a/src/contracts/identity/context.tsx +++ b/src/contracts/identity/context.tsx @@ -7,6 +7,8 @@ import { useContract, useInkathon, } from '@scio-labs/use-inkathon'; +import { getChains } from 'chaindata'; +import ss58registry from 'chaindata/ss58registry'; import { createContext, useCallback, @@ -15,17 +17,12 @@ import { useState, } from 'react'; +import { RELAY_CHAIN } from '@/consts'; import { useToast } from '@/contexts/Toast'; import { IdentityMetadata } from '.'; import { CONTRACT_IDENTITY } from '..'; -import { - Address, - ChainConsts, - ChainId, - Chains, - IdentityNo, -} from '../types'; +import { Address, ChainConsts, ChainId, Chains, IdentityNo } from '../types'; interface IdentityContract { identityNo: number | null; @@ -109,23 +106,34 @@ const IdentityContractProvider = ({ children }: Props) => { const count = rpcUrls.length; const rpcIndex = Math.min(Math.floor(Math.random() * count), count - 1); const rpc = rpcUrls[rpcIndex]; + try { - const provider = new WsProvider(rpc); - const api = new ApiPromise({ provider, rpc: jsonrpc }); + const chainData = (await getChains()).find((chain) => + chain.paraId + ? chain.paraId === chainId && chain.relay.id === RELAY_CHAIN + : chainId === 0 && chain.id === RELAY_CHAIN + ); + + if (!chainData) { + return null; + } - await api.isReady; + const ss58Result = await ss58registry(chainData.id); - const ss58Prefix: number = - api.consts.system.ss58Prefix.toPrimitive() as number; - const name = (await api.rpc.system.chain()).toString(); - const paraId = chainId; + const rpcCount = chainData.rpcs.length; + const rpcIndex = Math.min( + Math.floor(Math.random() * rpcCount), + rpcCount - 1 + ); - await api.disconnect(); + const ss58Prefix = ss58Result + ? ss58Result + : await fetchSs58Prefix(chainData.rpcs[rpcIndex].url); return { - name, - ss58Prefix, - paraId, + name: chainData.name, + ss58Prefix: ss58Prefix, + paraId: chainId, }; } catch (e) { toastError && toastError(`Failed to get chain info for ${rpc}`); @@ -133,6 +141,20 @@ const IdentityContractProvider = ({ children }: Props) => { } }; + const fetchSs58Prefix = async (rpc: string): Promise => { + const provider = new WsProvider(rpc); + const api = new ApiPromise({ provider, rpc: jsonrpc }); + + await api.isReady; + + const ss58Prefix: number = + api.consts.system.ss58Prefix.toPrimitive() as number; + + await api.disconnect(); + + return ss58Prefix; + }; + setLoadingChains(true); try { const result = await contractQuery( @@ -152,7 +174,7 @@ const IdentityContractProvider = ({ children }: Props) => { const _chains: Chains = {}; for await (const item of output) { - const chainId = parseInt(item[0].replace(/,/g, "")); + const chainId = parseInt(item[0].replace(/,/g, '')); const { accountType, rpcUrls } = item[1]; const info = await getChainInfo(rpcUrls, chainId); if (info) @@ -185,7 +207,7 @@ const IdentityContractProvider = ({ children }: Props) => { const _addresses: Array
= []; for (let idx = 0; idx < records.length; ++idx) { const record = records[idx]; - const chainId: ChainId = parseInt(record[0].replace(/,/g, "")); + const chainId: ChainId = parseInt(record[0].replace(/,/g, '')); const address = record[1]; // FIXME: Decode address here _addresses.push({ chainId, diff --git a/src/pages/transfer.tsx b/src/pages/transfer.tsx index 3cb850c..cc9633a 100644 --- a/src/pages/transfer.tsx +++ b/src/pages/transfer.tsx @@ -13,15 +13,17 @@ import { import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; import { useInkathon } from '@scio-labs/use-inkathon'; import styles from '@styles/pages/transfer.module.scss'; +import { getChains, getTokens } from 'chaindata'; import { useCallback, useEffect, useState } from 'react'; 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, { isTeleport } from '@/utils/transactionRouter'; -import { getTeleportableAssets } from '@/utils/transactionRouter/teleportableRoutes'; -import { Fungible } from '@/utils/transactionRouter/types'; +import NativeTransfer from '@/utils/nativeTransfer'; +import TransactionRouter, { isTeleport } from '@/utils/xcmTransfer'; +import { getTeleportableAssets } from '@/utils/xcmTransfer/teleportableRoutes'; +import { Fungible } from '@/utils/xcmTransfer/types'; import { chainsSupportingXcmExecute, RELAY_CHAIN } from '@/consts'; import { useRelayApi } from '@/contexts/RelayApi'; @@ -93,11 +95,37 @@ const TransferPage = () => { setAssets(_assets); } } else { - const _assets = await AssetRegistry.getAssetsOnBlockchain( - RELAY_CHAIN, - chains[sourceChainId].paraId + const chainData = (await getChains()).find( + (chain) => chain.paraId ? + chain.paraId === sourceChainId && chain.relay.id === RELAY_CHAIN + : + sourceChainId === 0 && chain.id === RELAY_CHAIN ); - _assets.push(...getTeleportableAssets(sourceChainId, destChainId)); + + const _assets = []; + if (chainData) { + const tokens = (await getTokens()).filter((token) => { + const prefix = `${chainData.id}-${token.data.type}`; + const isPartOfSourceChain = token.data.id.startsWith(prefix); + return isPartOfSourceChain; + }); + const assets: Asset[] = tokens.map(t => { + const asset: Asset = { + asset: "", + assetId: t.data?.assetId, + onChainId: t.data?.onChainId, + name: t.data.symbol, + symbol: t.data.symbol, + decimals: t.data.decimals, + type: t.data.type, + confidence: 0, + inferred: false + }; + return asset; + }); + _assets.push(...assets); + } + setSelectedAsset([]); setAssets(_assets); } @@ -143,10 +171,16 @@ const TransferPage = () => { // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars const isTransferSupported = (): boolean => { + // We support simple transfers. + if (sourceChainId === destChainId) { + return true; + } + if ( sourceChainId === undefined || destChainId === undefined || - selectedAsset === undefined + selectedAsset === undefined || + selectedAsset.xcmInteriorKey === undefined ) { return false; } @@ -200,6 +234,39 @@ const TransferPage = () => { return; } + if (sourceChainId === destChainId) { + // Just do a simple token transfer. + const count = chains[sourceChainId].rpcUrls.length; + const rpcIndex = Math.min(Math.floor(Math.random() * count), count - 1); + + const api = await getApi(chains[sourceChainId].rpcUrls[rpcIndex]); + + const keypair = new Keyring(); + keypair.addFromAddress(activeAccount.address); + + const receiverKeypair = new Keyring(); + receiverKeypair.addFromAddress(recipientAddress); + + setTransferring(true); + + try { + await NativeTransfer.transfer( + api, + keypair.pairs[0], + selectedAsset, + receiverKeypair.pairs[0].publicKey, + amount * Math.pow(10, selectedAsset.decimals), + activeSigner + ); + } catch (e: any) { + toastError(`Transfer failed. Error: ${e.toString()}`); + } finally { + setTransferring(false); + } + + return; + } + const reserveChainId = getParaIdFromXcmInterior( selectedAsset.xcmInteriorKey ); @@ -225,7 +292,7 @@ const TransferPage = () => { try { await TransactionRouter.sendTokens( { - keypair: keypair.pairs[0], // How to convert active account into a keypair? + keypair: keypair.pairs[0], chain: sourceChainId, }, { @@ -238,7 +305,7 @@ const TransferPage = () => { }, reserveChainId, getFungible( - selectedAsset.xcmInteriorKey, + JSON.parse(JSON.stringify(selectedAsset.xcmInteriorKey)), // Make a hard copy. isSourceParachain, amount * Math.pow(10, selectedAsset.decimals) ), diff --git a/src/utils/assetRegistry.ts b/src/utils/assetRegistry.ts index 810b6c2..2b79e42 100644 --- a/src/utils/assetRegistry.ts +++ b/src/utils/assetRegistry.ts @@ -10,6 +10,9 @@ export type Asset = { symbol: string; decimals: number; xcmInteriorKey?: any; + type?: string; + assetId?: any; + onChainId?: any; inferred: boolean; confidence: number; }; diff --git a/src/utils/nativeTransfer/assets.ts b/src/utils/nativeTransfer/assets.ts new file mode 100644 index 0000000..4d344f2 --- /dev/null +++ b/src/utils/nativeTransfer/assets.ts @@ -0,0 +1,42 @@ +import { ApiPromise } from "@polkadot/api"; +import { Signer } from "@polkadot/api/types"; +import { KeyringPair } from "@polkadot/keyring/types"; + +import { AccountIdRaw } from "../xcmTransfer/types"; + +class SubstrateAssets { + public static async transfer( + api: ApiPromise, + sender: KeyringPair, + token: any, + to: AccountIdRaw, + amount: number, + signer?: Signer + ): Promise { + if (token.type !== "substrate-assets") + throw new Error(`This module doesn't handle tokens of type ${token.type}`) + + const id = token.assetId; + + const transferCall = api.tx.assets.transfer(id, { Id: to }, amount); + + if (signer) api.setSigner(signer); + + const account = signer ? sender.address : sender; + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + const unsub = await transferCall.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } + }); + } +} + +export default SubstrateAssets; diff --git a/src/utils/nativeTransfer/index.ts b/src/utils/nativeTransfer/index.ts new file mode 100644 index 0000000..201ff38 --- /dev/null +++ b/src/utils/nativeTransfer/index.ts @@ -0,0 +1,38 @@ +import { ApiPromise } from "@polkadot/api"; +import { Signer } from "@polkadot/api/types"; +import { KeyringPair } from "@polkadot/keyring/types"; + +import SubstrateAssets from "./assets"; +import SubstrateNative from "./native"; +import SubstrateOrml from "./orml"; +import SubstrateTokens from "./tokens"; +import { AccountIdRaw } from "../xcmTransfer/types"; + +class NativeTransfer { + public static async transfer( + api: ApiPromise, + sender: KeyringPair, + token: any, + to: AccountIdRaw, + amount: number, + signer?: Signer + ): Promise { + + switch (token.type) { + case "substrate-native": + await SubstrateNative.transfer(api, sender, token, to, amount, signer); + break; + case "substrate-assets": + await SubstrateAssets.transfer(api, sender, token, to, amount, signer); + break; + case "substrate-tokens": + await SubstrateTokens.transfer(api, sender, token, to, amount, signer); + break; + case "substrate-orml": + await SubstrateOrml.transfer(api, sender, token, to, amount, signer); + break; + } + } +} + +export default NativeTransfer; diff --git a/src/utils/nativeTransfer/native.ts b/src/utils/nativeTransfer/native.ts new file mode 100644 index 0000000..36c5370 --- /dev/null +++ b/src/utils/nativeTransfer/native.ts @@ -0,0 +1,40 @@ +import { ApiPromise } from "@polkadot/api"; +import { Signer } from "@polkadot/api/types"; +import { KeyringPair } from "@polkadot/keyring/types"; + +import { AccountIdRaw } from "../xcmTransfer/types"; + +class SubstrateNative { + public static async transfer( + api: ApiPromise, + sender: KeyringPair, + token: any, + to: AccountIdRaw, + amount: number, + signer?: Signer + ): Promise { + if (token.type !== "substrate-native") + throw new Error(`This module doesn't handle tokens of type ${token.type}`) + + const transferCall = api.tx.balances.transfer(to, amount); + + if (signer) api.setSigner(signer); + + const account = signer ? sender.address : sender; + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + const unsub = await transferCall.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }); + } catch (e) { + reject(e); + } + }); + } +} + +export default SubstrateNative; diff --git a/src/utils/nativeTransfer/orml.ts b/src/utils/nativeTransfer/orml.ts new file mode 100644 index 0000000..dd7ffee --- /dev/null +++ b/src/utils/nativeTransfer/orml.ts @@ -0,0 +1,45 @@ +import { ApiPromise } from "@polkadot/api"; +import { Signer } from "@polkadot/api/types"; +import { KeyringPair } from "@polkadot/keyring/types"; + +import { AccountIdRaw } from "../xcmTransfer/types"; + +class SubstrateOrml { + public static async transfer( + api: ApiPromise, + sender: KeyringPair, + token: any, + to: AccountIdRaw, + amount: number, + signer?: Signer + ): Promise { + if (token.type !== "substrate-orml") + throw new Error(`This module doesn't handle tokens of type ${token.type}`) + + const currencyId = { Token: token.symbol.toUpperCase() } + + const transferCall = api.tx.tokens ? + api.tx.tokens.transfer(to, currencyId, amount) + : + api.tx.currencies.transfer(to, currencyId, amount); + + if (signer) api.setSigner(signer); + + const account = signer ? sender.address : sender; + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + const unsub = await transferCall.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } + }); + } +} + +export default SubstrateOrml; diff --git a/src/utils/nativeTransfer/tokens.ts b/src/utils/nativeTransfer/tokens.ts new file mode 100644 index 0000000..4f7df57 --- /dev/null +++ b/src/utils/nativeTransfer/tokens.ts @@ -0,0 +1,52 @@ +import { ApiPromise } from "@polkadot/api"; +import { Signer } from "@polkadot/api/types"; +import { KeyringPair } from "@polkadot/keyring/types"; + +import { AccountIdRaw } from "../xcmTransfer/types"; + +class SubstrateTokens { + public static async transfer( + api: ApiPromise, + sender: KeyringPair, + token: any, + to: AccountIdRaw, + amount: number, + signer?: Signer + ): Promise { + if (token.type !== "substrate-tokens") + throw new Error(`This module doesn't handle tokens of type ${token.type}`) + + const currencyId = (() => { + try { + // `as string` doesn't matter here because we catch it if it throws + return JSON.parse(token.onChainId as string) + } catch (error) { + return token.onChainId + } + })(); + + const transferCall = api.tx.tokens ? + api.tx.tokens.transfer(to, currencyId, amount) + : + api.tx.currencies.transfer(to, currencyId, amount); + + if (signer) api.setSigner(signer); + + const account = signer ? sender.address : sender; + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + const unsub = await transferCall.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } + }); + } +} + +export default SubstrateTokens; diff --git a/src/utils/transactionRouter/index.ts b/src/utils/xcmTransfer/index.ts similarity index 100% rename from src/utils/transactionRouter/index.ts rename to src/utils/xcmTransfer/index.ts diff --git a/src/utils/transactionRouter/reserveTransfer.test.ts b/src/utils/xcmTransfer/reserveTransfer.test.ts similarity index 100% rename from src/utils/transactionRouter/reserveTransfer.test.ts rename to src/utils/xcmTransfer/reserveTransfer.test.ts diff --git a/src/utils/transactionRouter/reserveTransfer.ts b/src/utils/xcmTransfer/reserveTransfer.ts similarity index 91% rename from src/utils/transactionRouter/reserveTransfer.ts rename to src/utils/xcmTransfer/reserveTransfer.ts index 3b1b787..366c973 100644 --- a/src/utils/transactionRouter/reserveTransfer.ts +++ b/src/utils/xcmTransfer/reserveTransfer.ts @@ -41,13 +41,17 @@ class ReserveTransfer { const account = signer ? sender.keypair.address : sender.keypair; // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve) => { - const unsub = await reserveTransfer.signAndSend(account, (result: any) => { - if (result.status.isFinalized) { - unsub(); - resolve(); - } - }) + return new Promise(async (resolve, reject) => { + try { + const unsub = await reserveTransfer.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } }); } @@ -80,13 +84,17 @@ class ReserveTransfer { const account = signer ? sender.keypair.address : sender.keypair; // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve) => { - const unsub = await reserveTransfer.signAndSend(account, (result: any) => { - if (result.status.isFinalized) { - unsub(); - resolve(); - } - }) + return new Promise(async (resolve, reject) => { + try { + const unsub = await reserveTransfer.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } }); } @@ -119,13 +127,17 @@ class ReserveTransfer { const account = signer ? sender.keypair.address : sender.keypair; // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve) => { - const unsub = await reserveTransfer.signAndSend(account, (result: any) => { - if (result.status.isFinalized) { - unsub(); - resolve(); - } - }) + return new Promise(async (resolve, reject) => { + try { + const unsub = await reserveTransfer.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } }); } diff --git a/src/utils/transactionRouter/teleportTransfer.ts b/src/utils/xcmTransfer/teleportTransfer.ts similarity index 83% rename from src/utils/transactionRouter/teleportTransfer.ts rename to src/utils/xcmTransfer/teleportTransfer.ts index a70cb45..e976cd7 100644 --- a/src/utils/transactionRouter/teleportTransfer.ts +++ b/src/utils/xcmTransfer/teleportTransfer.ts @@ -46,13 +46,17 @@ class TeleportTransfer { const account = signer ? sender.address : sender; // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve) => { - const unsub = await teleport.signAndSend(account, (result: any) => { - if (result.status.isFinalized) { - unsub(); - resolve(); - } - }) + return new Promise(async (resolve, reject) => { + try { + const unsub = await teleport.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }); + } catch (e) { + reject(e); + } }); } } diff --git a/src/utils/transactionRouter/teleportableRoutes.ts b/src/utils/xcmTransfer/teleportableRoutes.ts similarity index 100% rename from src/utils/transactionRouter/teleportableRoutes.ts rename to src/utils/xcmTransfer/teleportableRoutes.ts diff --git a/src/utils/transactionRouter/transferAsset.test.ts b/src/utils/xcmTransfer/transferAsset.test.ts similarity index 100% rename from src/utils/transactionRouter/transferAsset.test.ts rename to src/utils/xcmTransfer/transferAsset.test.ts diff --git a/src/utils/transactionRouter/transferAsset.ts b/src/utils/xcmTransfer/transferAsset.ts similarity index 89% rename from src/utils/transactionRouter/transferAsset.ts rename to src/utils/xcmTransfer/transferAsset.ts index 1c26474..a40dac7 100644 --- a/src/utils/transactionRouter/transferAsset.ts +++ b/src/utils/xcmTransfer/transferAsset.ts @@ -40,13 +40,17 @@ class TransferAsset { const account = signer ? sender.address : sender; // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve) => { - const unsub = await xcmExecute.signAndSend(account, (result: any) => { - if (result.status.isFinalized) { - unsub(); - resolve(); - } - }) + return new Promise(async (resolve, reject) => { + try { + const unsub = await xcmExecute.signAndSend(account, (result: any) => { + if (result.status.isFinalized) { + unsub(); + resolve(); + } + }) + } catch (e) { + reject(e); + } }); } diff --git a/src/utils/transactionRouter/types.ts b/src/utils/xcmTransfer/types.ts similarity index 100% rename from src/utils/transactionRouter/types.ts rename to src/utils/xcmTransfer/types.ts