diff --git a/src/components/accountButton.tsx b/src/components/accountButton.tsx index 9ee2820..56c9b08 100644 --- a/src/components/accountButton.tsx +++ b/src/components/accountButton.tsx @@ -64,7 +64,7 @@ export default function AccountButton({ setSwitchWallet }: { setSwitchWallet: (x setActiveSenderWallet(undefined); setActiveSenderAccount(undefined); disconnect(); - }, [setSender, setActiveSenderWallet, setActiveSenderAccount]); + }, [setSender, setActiveSenderWallet, setActiveSenderAccount, disconnect]); useEffect(() => { if (needSwitchNetwork) { @@ -78,7 +78,15 @@ export default function AccountButton({ setSwitchWallet }: { setSwitchWallet: (x setSwitchWallet(true); }); } - }, [sourceChain, chain, switchNetworkAsync]); + }, [ + sourceChain, + chain, + switchNetworkAsync, + handleDisconnect, + setSwitchWallet, + activeSenderWallet, + needSwitchNetwork, + ]); useEffect(() => { window.addEventListener("click", () => { diff --git a/src/components/appBox.tsx b/src/components/appBox.tsx index bd2c560..ed6391a 100644 --- a/src/components/appBox.tsx +++ b/src/components/appBox.tsx @@ -1,29 +1,34 @@ "use client"; -import { ChangeEventHandler, useCallback, useEffect, useMemo, useRef, useState } from "react"; -import data from "../data/data.json"; +import { ChangeEventHandler, useCallback, useMemo, useRef, useState } from "react"; import Image from "next/image"; -import ChainSelectInput, { chainType } from "./chainSelectInput"; +import ChainSelectInput from "./chainSelectInput"; import SuccessModal from "./successModal"; import PendingModal from "./pendingModal"; -import { formatBalance, getAssetIconSrc, isExceedingCrossChainLimit, isValidAddress, parseCross } from "@/utils"; +import { + formatBalance, + getAssetIconSrc, + getAvailableSourceAsset, + getAvailableSourceChain, + getAvailableSourceChainOptions, + getAvailableTargetAsset, + getAvailableTargetChain, + getAvailableTargetChainOptions, + isExceedingCrossChainLimit, + isValidAddress, +} from "@/utils"; import { useTransfer } from "@/hooks"; import { BN, BN_ZERO, bnToBn } from "@polkadot/util"; import { formatUnits, parseUnits } from "viem"; import { WalletID } from "@/types"; import { useAccount, useNetwork, useSwitchNetwork } from "wagmi"; import notification from "@/ui/notification"; -import { supportedTokenList } from "@/config/tokens"; import { useTrail, animated, useSpring } from "@react-spring/web"; import WalletSelectionModal from "./walletSelectionModal"; +import { assetCategories } from "@/config/asset-categories"; export default function AppBox() { const [connectModal, setConnectModal] = useState(false); - - const { defaultSourceChainOptions, defaultSourceAssetOptions } = parseCross(); - const [selectedAsset, setSelectedAsset] = useState(supportedTokenList[0]); - const [allowedChain, setAllowedChain] = useState<any>([]); - // const [sourceAssetOptions, setSourceAssetOptions] = useState(defaultSourceAssetOptions); const [successModal, setSuccessModal] = useState<boolean>(false); const [receipt, setReceipt] = useState<boolean | null>(false); @@ -58,7 +63,10 @@ export default function AppBox() { activeSenderAccount, feeBalanceOnSourceChain, sourceNativeBalance, + assetCategory, + setAssetCategory, } = useTransfer(); + const handleCloseSuccessModal = useCallback(() => { setSuccessModal(false); setReceipt(null); @@ -69,7 +77,15 @@ export default function AppBox() { updateSourceNativeBalance(); updateTargetNativeBalance(); updateFeeBalanceOnSourceChain(); - }, []); + }, [ + setTransferAmount, + updateFeeBalanceOnSourceChain, + updateSourceAssetBalance, + updateSourceNativeBalance, + updateTargetAssetBalance, + updateTargetAssetSupply, + updateTargetNativeBalance, + ]); const sourceChainRef = useRef(sourceChain); const targetChainRef = useRef(targetChain); @@ -158,8 +174,6 @@ export default function AppBox() { return null; }, [bridgeInstance, feeBalanceOnSourceChain]); - // console.log("fee alert", feeAlert); - const existentialAlertOnSourceChain = useMemo(() => { if ( sourceChain.existential && @@ -219,26 +233,12 @@ export default function AppBox() { !!existentialAlertOnSourceChain || !!existentialAlertOnTargetChain; - // console.log( - // "check this now", - // sender?.address, - // sender?.valid, - // recipient?.address, - // recipient?.valid, - // transferAmount.input, - // transferAmount.valid, - // feeAlert, - // existentialAlertOnSourceChain, - // existentialAlertOnTargetChain, - // ); - const handleSend = useCallback(async () => { if (needSwitchNetwork) { switchNetwork?.(sourceChain.id); } else if (bridgeInstance && recipient) { const callback = { successCb: (receipt: any) => { - console.log("receipt", receipt); setReceipt(receipt); setBusy(false); setSuccessModal(true); @@ -266,69 +266,14 @@ export default function AppBox() { needSwitchNetwork, recipient, sender?.address, - setTransferAmount, sourceChain.id, switchNetwork, transfer, transferAmount.amount, transferAmount.input, - updateFeeBalanceOnSourceChain, - updateSourceAssetBalance, - updateTargetAssetBalance, updateTargetAssetSupply, - updateSourceNativeBalance, - updateTargetNativeBalance, ]); - useEffect(() => { - console.log("defaultSourceAssetOptions", sourceChain.assets); - let sourceChainOptions: any = []; - for (const item of selectedAsset.allowedSource) { - for (const chain of defaultSourceChainOptions) { - if (chain.name === item) { - sourceChainOptions.push(chain); - } - } - } - let selectedSourceAsset; - for (const item of sourceChainOptions[0].assets) { - if (selectedAsset.icon === item.icon) { - selectedSourceAsset = item; - } - } - setAllowedChain([...sourceChainOptions]); - setSourceChain(sourceChainOptions[0]); - setSourceAsset(selectedSourceAsset); - setTargetChain(sourceChainOptions[1]); - }, [selectedAsset]); - - useEffect(() => { - console.log(allowedChain); - if (allowedChain.length > 0) { - if (sourceChain.name === allowedChain[0].name && targetChain.name === allowedChain[0].name) { - setTargetChain(allowedChain[1]); - } else if (sourceChain.name === allowedChain[1].name && targetChain.name === allowedChain[1].name) { - setTargetChain(allowedChain[0]); - } - } - for (const asset of sourceChain.assets) { - if (selectedAsset.name === asset.name) setSourceAsset(asset); - } - }, [sourceChain]); - - useEffect(() => { - if (allowedChain.length > 0) { - if (targetChain.name === allowedChain[0].name && sourceChain.name == allowedChain[0].name) { - setSourceChain(allowedChain[1]); - } else if (targetChain.name === allowedChain[1].name && sourceChain.name === allowedChain[1].name) { - setSourceChain(allowedChain[0]); - } - } - for (const asset of targetChain.assets) { - if (selectedAsset.name === asset.name) setTargetAsset(asset); - } - }, [targetChain]); - const trails = useTrail(5, { from: { transform: "translateX(-100%)", opacity: 0 }, to: { opacity: 1, transform: "translateX(0)" }, @@ -339,8 +284,6 @@ export default function AppBox() { to: { opacity: 1, transform: "translateY(0)" }, }); - // console.log("check this.................", sender, needSwitchNetwork, disabledSend); - return ( <> <animated.section @@ -355,16 +298,24 @@ export default function AppBox() { <p className="text-[12px] leading-[15.22px] text-[#12161980]">Token</p> </div> <div className="flex items-center gap-[10px]"> - {supportedTokenList.map((item: any) => ( + {assetCategories.map((item) => ( <div className="flex items-center gap-[10px] duration-500" key={item.name} style={{ - maxWidth: selectedAsset.name === item.name ? "100px" : "30px", - transitionDelay: selectedAsset.name === item.name ? "0.4s" : "0s", + maxWidth: assetCategory === item.category ? "100px" : "30px", + transitionDelay: assetCategory === item.category ? "0.4s" : "0s", }} onClick={() => { - setSelectedAsset(item); + setAssetCategory(item.category); + const _sourceChain = getAvailableSourceChain(getAvailableSourceChainOptions(item.category)); + const _sourceAsset = getAvailableSourceAsset(_sourceChain, item.category); + const _targetChain = getAvailableTargetChain(getAvailableTargetChainOptions(_sourceAsset)); + const _targetAsset = getAvailableTargetAsset(_targetChain, item.category); + setSourceChain(_sourceChain); + setSourceAsset(_sourceAsset); + setTargetChain(_targetChain); + setTargetAsset(_targetAsset); }} > <Image @@ -385,7 +336,19 @@ export default function AppBox() { > <div className="flex h-[30px] items-center justify-between"> <p className="text-[12px] leading-[15.22px] text-[#12161980]">Sender</p> - <ChainSelectInput options={allowedChain} who="sender" /> + <ChainSelectInput + value={sourceChain} + options={getAvailableSourceChainOptions(assetCategory)} + onSelect={(chain) => { + setSourceChain(chain); + const _sourceAsset = getAvailableSourceAsset(chain, assetCategory); + const _targetChain = getAvailableTargetChain(getAvailableTargetChainOptions(_sourceAsset)); + const _targetAsset = getAvailableTargetAsset(_targetChain, assetCategory); + setSourceAsset(_sourceAsset); + setTargetChain(_targetChain); + setTargetAsset(_targetAsset); + }} + /> </div> {sender ? ( <input @@ -413,7 +376,15 @@ export default function AppBox() { > <div className="flex h-[30px] items-center justify-between"> <p className="text-[12px] leading-[15.22px] text-[#12161980]">Recipient</p> - <ChainSelectInput options={allowedChain} who="target" /> + <ChainSelectInput + value={targetChain} + options={getAvailableTargetChainOptions(sourceAsset)} + onSelect={(chain) => { + setTargetChain(chain); + const _targetAsset = getAvailableTargetAsset(chain, assetCategory); + setTargetAsset(_targetAsset); + }} + /> </div> <input type="text" diff --git a/src/components/chainSelectInput.tsx b/src/components/chainSelectInput.tsx index 0aa953f..442c632 100644 --- a/src/components/chainSelectInput.tsx +++ b/src/components/chainSelectInput.tsx @@ -1,87 +1,31 @@ "use clients"; import Image from "next/image"; -import data from "../data/data.json"; -import { useCallback, useEffect, useRef, useState } from "react"; -import { useTransfer } from "@/hooks"; -import { getChainLogoSrc, parseCross } from "@/utils"; -import { Asset, ChainConfig } from "@/types"; - -export interface chainType { - name: string; - logo: string; -} - -export default function ChainSelectInput({ who, options }: { who: string; options: [any] }) { - const { sourceChain, setSourceChain, sourceAsset, setTargetChain, setSourceAsset, targetChain } = useTransfer(); - const { - defaultSourceChainOptions, - defaultTargetChainOptions, - availableTargetChainOptions, - availableSourceAssetOptions, - defaultSourceAssetOptions, - } = parseCross(); - const [sourceChainOptions, _setSourceChainOptions] = useState(defaultSourceChainOptions); - const [sourceAssetOptions, setSourceAssetOptions] = useState(defaultSourceAssetOptions); - const [targetChainOptions, setTargetChainOptions] = useState(defaultTargetChainOptions); - - const targetChainRef = useRef(targetChain); - const sourceAssetRef = useRef(sourceAsset); - const sourceChainRef = useRef(sourceChain); - - const _setTargetChain = useCallback( - (chain: ChainConfig | undefined) => { - setTargetChain((prev) => chain ?? prev); - targetChainRef.current = chain ?? targetChainRef.current; - }, - [setTargetChain], - ); - - // useEffect(() => { - // const options = availableTargetChainOptions[sourceChain.network]?.[sourceAsset.symbol] || []; - // setTargetChainOptions(options); - // _setTargetChain(options.at(0)); - // }, [sourceChain, sourceAsset, _setTargetChain]); - - const _setSourceChain = useCallback( - (chain: ChainConfig | undefined) => { - setSourceChain((prev) => chain ?? prev); - sourceChainRef.current = chain ?? sourceChainRef.current; - }, - [setSourceChain], - ); - - // const _setSourceAsset = useCallback( - // (asset: Asset | undefined) => { - // setSourceAsset((prev) => asset ?? prev); - // sourceAssetRef.current = asset ?? sourceAssetRef.current; - // }, - // [setSourceAsset], - // ); - - // useEffect(() => { - // const options = availableSourceAssetOptions[sourceChain.network] || []; - // setSourceAssetOptions(options); - // _setSourceAsset(options.at(0)); - // }, [sourceChain, _setSourceAsset]); +import { useState } from "react"; +import { getChainLogoSrc } from "@/utils"; +import { ChainConfig } from "@/types"; + +export default function ChainSelectInput({ + value, + options, + onSelect, +}: { + value: ChainConfig; + options: ChainConfig[]; + onSelect: (chain: ChainConfig) => void; +}) { const [open, setOpen] = useState<boolean>(false); - const name = "Polkadot AssetHub"; return ( <div className="relative cursor-pointer" onClick={() => { - setOpen(!open); + setOpen((prev) => !prev); }} > <div className="flex items-center justify-center gap-[5px]"> - <Image - src={getChainLogoSrc(who === "sender" ? sourceChain.logo : targetChain.logo)} - width={20} - height={20} - alt={who === "sender" ? sourceChain.name : targetChain.name} - /> - <p className="text-[12px] leading-[15px]">{who === "sender" ? sourceChain.name : targetChain.name}</p> + <Image src={getChainLogoSrc(value.logo)} width={20} height={20} alt={value.name} /> + <p className="text-[12px] leading-[15px]">{value.name}</p> <span className="block h-[16px] w-[16px] bg-[url('/images/icons/downarrow-icon.svg')] bg-contain bg-center bg-no-repeat" /> </div> <div @@ -90,12 +34,8 @@ export default function ChainSelectInput({ who, options }: { who: string; option > <div className="relative flex h-fit w-full flex-col gap-[10px] rounded-[10px] p-[10px]"> {options.map((item) => ( - <div - key={item.name} - className="flex w-full items-center gap-[5px]" - onClick={who === "sender" ? () => _setSourceChain(item) : () => _setTargetChain(item)} - > - <Image src={getChainLogoSrc(item.logo)} width={20} height={20} alt={item.name} /> + <div key={item.name} className="flex w-full items-center gap-[5px]" onClick={() => onSelect(item)}> + <Image src={getChainLogoSrc(item.logo)} width={16} height={16} alt={item.name} /> <p className="truncate whitespace-nowrap text-[12px] leading-[15px]">{item.name}</p> </div> ))} diff --git a/src/components/header.tsx b/src/components/header.tsx index 8c9260e..0e30928 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -2,7 +2,7 @@ import Image from "next/image"; import Link from "next/link"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import data from "../data/data.json"; import WalletButton from "./walletButton"; import AccountButton from "./accountButton"; @@ -37,12 +37,15 @@ export default function Header() { setShowMenu(false); }, []); - const senderOptions = - activeSenderWallet === WalletID.EVM && activeAddress - ? [{ address: activeAddress }] - : activeSenderWallet === WalletID.TALISMAN - ? talismanAccounts - : []; + const senderOptions = useMemo( + () => + activeSenderWallet === WalletID.EVM && activeAddress + ? [{ address: activeAddress }] + : activeSenderWallet === WalletID.TALISMAN + ? talismanAccounts + : [], + [activeAddress, activeSenderWallet, talismanAccounts], + ); useEffect(() => { if ((activeAddress || talismanAccounts.length > 0) && activeSenderWallet) { @@ -56,7 +59,15 @@ export default function Header() { setConnected(false); setSender(undefined); } - }, [activeAddress, talismanAccounts.length, activeSenderWallet]); + }, [ + activeAddress, + talismanAccounts.length, + activeSenderWallet, + setConnected, + setSender, + senderOptions, + sourceChain.addressType, + ]); return ( <section className="flex h-[50px] w-full items-center justify-between px-[10px] lg:h-[56px] lg:px-[30px]"> diff --git a/src/config/asset-categories.ts b/src/config/asset-categories.ts new file mode 100644 index 0000000..c33ae71 --- /dev/null +++ b/src/config/asset-categories.ts @@ -0,0 +1,24 @@ +import { AssetCategory } from "@/types"; + +export const assetCategories: { name: string; icon: string; category: AssetCategory }[] = [ + { + name: "USDT", + icon: "usdt.svg", + category: "usdt", + }, + { + name: "RING", + icon: "ring.png", + category: "ring", + }, + { + name: "PINK", + icon: "pink.jpg", + category: "pink", + }, + { + name: "DOT", + icon: "dot.svg", + category: "dot", + }, +]; diff --git a/src/config/chains/assethub-polkadot-chain.ts b/src/config/chains/assethub-polkadot-chain.ts index 933be1f..8d4f34b 100644 --- a/src/config/chains/assethub-polkadot-chain.ts +++ b/src/config/chains/assethub-polkadot-chain.ts @@ -64,6 +64,7 @@ export const assethubPolkadotChain: ChainConfig = { method: "limitedReserveTransferAssets", }, ], + category: "usdt", }, { icon: "pink.jpg", @@ -94,6 +95,7 @@ export const assethubPolkadotChain: ChainConfig = { method: "limitedReserveTransferAssets", }, ], + category: "pink", }, { icon: "dot.svg", @@ -124,6 +126,7 @@ export const assethubPolkadotChain: ChainConfig = { method: "limitedReserveTransferAssets", }, ], + category: "dot", }, ], wallets: [WalletID.TALISMAN], diff --git a/src/config/chains/assethub-rococo-chain.ts b/src/config/chains/assethub-rococo-chain.ts index d5d0244..9b79e21 100644 --- a/src/config/chains/assethub-rococo-chain.ts +++ b/src/config/chains/assethub-rococo-chain.ts @@ -65,6 +65,7 @@ export const assethubRococoChain: ChainConfig = { method: "limitedReserveTransferAssets", }, ], + category: "usdt", }, ], wallets: [WalletID.TALISMAN], diff --git a/src/config/chains/darwinia-chain.ts b/src/config/chains/darwinia-chain.ts index ff6e933..c2f0593 100644 --- a/src/config/chains/darwinia-chain.ts +++ b/src/config/chains/darwinia-chain.ts @@ -64,6 +64,7 @@ export const darwiniaChain: ChainConfig = { method: "reserveTransferAssets", }, ], + category: "ring", }, { icon: "usdt.svg", @@ -94,6 +95,7 @@ export const darwiniaChain: ChainConfig = { method: "transferMultiassets", }, ], + category: "usdt", }, { icon: "pink.jpg", @@ -124,6 +126,7 @@ export const darwiniaChain: ChainConfig = { method: "transferMultiassets", }, ], + category: "pink", }, { icon: "dot.svg", @@ -154,6 +157,7 @@ export const darwiniaChain: ChainConfig = { method: "transferMultiassets", }, ], + category: "dot", }, ], wallets: [WalletID.EVM, WalletID.TALISMAN], diff --git a/src/config/chains/hydradx-chain.ts b/src/config/chains/hydradx-chain.ts index 216fe16..7f9a1d9 100644 --- a/src/config/chains/hydradx-chain.ts +++ b/src/config/chains/hydradx-chain.ts @@ -64,6 +64,7 @@ export const hydradxChain: ChainConfig = { method: "transferMultiasset", }, ], + category: "ring", }, ], wallets: [WalletID.TALISMAN], diff --git a/src/config/chains/pangolin-chain.ts b/src/config/chains/pangolin-chain.ts index 5335523..7e2c86e 100644 --- a/src/config/chains/pangolin-chain.ts +++ b/src/config/chains/pangolin-chain.ts @@ -65,6 +65,7 @@ export const pangolinChain: ChainConfig = { method: "transferMultiassets", }, ], + category: "usdt", }, ], wallets: [WalletID.EVM, WalletID.TALISMAN], diff --git a/src/config/tokens/index.ts b/src/config/tokens/index.ts deleted file mode 100644 index a417e7b..0000000 --- a/src/config/tokens/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const supportedTokenList = [ - { - name: "USDT", - icon: "usdt.svg", - allowedSource: ["Darwinia", "Polkadot AssetHub"], - }, - { - name: "RING", - icon: "ring.png", - allowedSource: ["Darwinia", "Hydration"], - }, - { - name: "PINK", - icon: "pink.jpg", - allowedSource: ["Darwinia", "Polkadot AssetHub"], - }, - { - name: "DOT", - icon: "dot.svg", - allowedSource: ["Darwinia", "Polkadot AssetHub"], - }, -]; diff --git a/src/hooks/use-asset-balance.ts b/src/hooks/use-asset-balance.ts index e5e0dc5..8e116f5 100644 --- a/src/hooks/use-asset-balance.ts +++ b/src/hooks/use-asset-balance.ts @@ -12,6 +12,7 @@ export function useAssetBalance( const [value, setValue] = useState<{ currency: Currency; amount: BN }>(); const update = useCallback(() => { + console.log("update", bridge, account, position); if (bridge && account?.address && account.valid) { return from( position === "source" diff --git a/src/libs/bridge/base.ts b/src/libs/bridge/base.ts index 03d6246..ca19e95 100644 --- a/src/libs/bridge/base.ts +++ b/src/libs/bridge/base.ts @@ -82,6 +82,7 @@ export abstract class BaseBridge { */ private async getAssetBalance(api: ApiPromise, asset: Asset, account: string) { let amount = BN_ZERO; + console.log("getAssetBalance", asset, account); if (asset.id === AssetID.SYSTEM) { amount = (await this.getNativeBalance(api, account)).transferrable; diff --git a/src/providers/transfer-provider.tsx b/src/providers/transfer-provider.tsx index 1609025..743b532 100644 --- a/src/providers/transfer-provider.tsx +++ b/src/providers/transfer-provider.tsx @@ -2,13 +2,24 @@ import { Dispatch, PropsWithChildren, SetStateAction, createContext, useCallback, useMemo, useState } from "react"; import { BN, BN_ZERO } from "@polkadot/util"; -import { Asset, ChainConfig, Currency, WalletID } from "@/types"; +import { Asset, AssetCategory, ChainConfig, Currency, WalletID } from "@/types"; import { usePublicClient, useWalletClient } from "wagmi"; import { UniversalBridge } from "@/libs"; import { WalletAccount } from "@talismn/connect-wallets"; import { Signer } from "@polkadot/api/types"; -import { notifyError, notifyTransaction, parseCross, signAndSendExtrinsic } from "@/utils"; +import { + getAvailableSourceAsset, + getAvailableSourceChain, + getAvailableSourceChainOptions, + getAvailableTargetAsset, + getAvailableTargetChain, + getAvailableTargetChainOptions, + notifyError, + notifyTransaction, + parseCross, + signAndSendExtrinsic, +} from "@/utils"; import { useApi, useAssetSupply, @@ -20,6 +31,12 @@ import { } from "@/hooks"; import { ApiPromise } from "@polkadot/api"; +const defaultAssetCategory: AssetCategory = "usdt"; +const defaultSourceChain: ChainConfig = getAvailableSourceChain(getAvailableSourceChainOptions(defaultAssetCategory)); +const defaultSourceAsset: Asset = getAvailableSourceAsset(defaultSourceChain, defaultAssetCategory); +const defaultTargetChain: ChainConfig = getAvailableTargetChain(getAvailableTargetChainOptions(defaultSourceAsset)); +const defaultTargetAsset: Asset = getAvailableTargetAsset(defaultTargetChain, defaultAssetCategory); + interface TransferCtx { assetLimitOnTargetChain: { currency: Currency; amount: BN } | undefined; existentialDepositOnTargetChain: { currency: Currency; amount: BN } | undefined; @@ -31,6 +48,7 @@ interface TransferCtx { targetNativeBalance: { currency: Currency; amount: BN } | undefined; feeBalanceOnSourceChain: { currency: Currency; amount: BN } | undefined; transferAmount: { valid: boolean; input: string; amount: BN }; + assetCategory: AssetCategory; sourceChain: ChainConfig; targetChain: ChainConfig; sourceAsset: Asset; @@ -45,6 +63,7 @@ interface TransferCtx { targetApi: ApiPromise | undefined; setTransferAmount: Dispatch<SetStateAction<{ valid: boolean; input: string; amount: BN }>>; + setAssetCategory: Dispatch<SetStateAction<AssetCategory>>; setSourceChain: Dispatch<SetStateAction<ChainConfig>>; setTargetChain: Dispatch<SetStateAction<ChainConfig>>; setSourceAsset: Dispatch<SetStateAction<Asset>>; @@ -70,8 +89,6 @@ interface TransferCtx { updateFeeBalanceOnSourceChain: () => void; } -const { defaultSourceChain, defaultTargetChain, defaultSourceAsset, defaultTargetAsset } = parseCross(); - const transferCb = { successCb: (receipt: any) => {}, failedCb: () => {}, @@ -81,6 +98,7 @@ export const TransferContext = createContext({} as TransferCtx); export default function TransferProvider({ children }: PropsWithChildren<unknown>) { const [transferAmount, setTransferAmount] = useState({ valid: true, input: "", amount: BN_ZERO }); + const [assetCategory, setAssetCategory] = useState(defaultAssetCategory); const [sourceChain, setSourceChain] = useState(defaultSourceChain); const [targetChain, setTargetChain] = useState(defaultTargetChain); const [sourceAsset, setSourceAsset] = useState(defaultSourceAsset); @@ -223,6 +241,7 @@ export default function TransferProvider({ children }: PropsWithChildren<unknown sourceNativeBalance, targetNativeBalance, transferAmount, + assetCategory, sourceChain, targetChain, sourceAsset, @@ -235,6 +254,7 @@ export default function TransferProvider({ children }: PropsWithChildren<unknown activeRecipientWallet, setTransferAmount, + setAssetCategory, setSourceChain, setTargetChain, setSourceAsset, diff --git a/src/types/asset.ts b/src/types/asset.ts index 6fe27d7..49b2552 100644 --- a/src/types/asset.ts +++ b/src/types/asset.ts @@ -1,6 +1,7 @@ import { Cross } from "./cross"; export type AssetSymbol = "DOT" | "ROC" | "USDT" | "PRING" | "ahUSDT" | "PINK" | "ahPINK" | "RING" | "HDX"; +export type AssetCategory = "ring" | "usdt" | "pink" | "dot"; export enum AssetID { SYSTEM = -1, @@ -13,7 +14,7 @@ export interface Asset { symbol: AssetSymbol; decimals: number; cross: Cross[]; - + category: AssetCategory; // Defines where the asset is issued origin: { id: number | AssetID.SYSTEM; diff --git a/src/utils/cross.ts b/src/utils/cross.ts index 92bf955..81eb52e 100644 --- a/src/utils/cross.ts +++ b/src/utils/cross.ts @@ -1,5 +1,12 @@ import { darwiniaChain, hydradxChain } from "@/config/chains"; -import { AvailableSourceAssetOptions, AvailableTargetAssetOptions, AvailableTargetChainOptions } from "@/types"; +import { + Asset, + AssetCategory, + AvailableSourceAssetOptions, + AvailableTargetAssetOptions, + AvailableTargetChainOptions, + ChainConfig, +} from "@/types"; import { getChainConfig, getChainsConfig } from "."; let defaultSourceChain = darwiniaChain; @@ -72,3 +79,27 @@ export function parseCross() { availableTargetAssetOptions, }; } + +export function getAvailableSourceChainOptions(assetCategory: AssetCategory) { + return getChainsConfig().filter((chain) => chain.assets.some((asset) => asset.category === assetCategory)); +} + +export function getAvailableSourceChain(availableSourceChainOptions: ChainConfig[]) { + return availableSourceChainOptions[0]; +} + +export function getAvailableSourceAsset(availableSourceChain: ChainConfig, assetCategory: AssetCategory) { + return availableSourceChain.assets.find((asset) => asset.category === assetCategory)!; +} + +export function getAvailableTargetChainOptions(availableSourceAsset: Asset) { + return availableSourceAsset.cross.map((cross) => getChainConfig(cross.target.network)!); +} + +export function getAvailableTargetChain(availableTargetChainOptions: ChainConfig[]) { + return availableTargetChainOptions[0]; +} + +export function getAvailableTargetAsset(availableTargetChain: ChainConfig, assetCategory: AssetCategory) { + return availableTargetChain.assets.find((asset) => asset.category === assetCategory)!; +}