From 68786672055236accbd942d2026186831c1e88b5 Mon Sep 17 00:00:00 2001 From: Hamid Roohi Date: Tue, 13 Aug 2024 14:39:13 +0330 Subject: [PATCH] fix(balance input): fix balance input --- src/components/appBox.tsx | 118 +++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 7 deletions(-) diff --git a/src/components/appBox.tsx b/src/components/appBox.tsx index 855c41c..1e54429 100644 --- a/src/components/appBox.tsx +++ b/src/components/appBox.tsx @@ -1,11 +1,16 @@ "use client"; -import { useCallback, useState } from "react"; +import { ChangeEventHandler, useCallback, useMemo, useState } from "react"; import data from "../data/data.json"; import Image from "next/image"; import ChainSelectInput, { chainType } from "./chainSelectInput"; import SuccessModal from "./successModal"; import PendingModal from "./pendingModal"; +import { formatBalance } from "@/utils"; +import { useTransfer } from "@/hooks"; +import { BN, BN_ZERO, bnToBn } from "@polkadot/util"; +import { formatUnits, parseUnits } from "viem"; +import { InputAlert } from "@/old_components/input-alert"; export default function AppBox() { const [selectedToken, setSelectedToken] = useState("USDT"); @@ -17,6 +22,15 @@ export default function AppBox() { const [successModal, setSuccessModal] = useState(false); const [pendingModal, setPendingModal] = useState(false); + const { + sourceAssetBalance, + sourceAsset, + setTransferAmount, + transferAmount, + bridgeInstance, + assetLimitOnTargetChain, + targetAssetSupply, + } = useTransfer(); const handleCloseSuccessModal = useCallback(() => { setSuccessModal(false); }, []); @@ -25,6 +39,39 @@ export default function AppBox() { setPendingModal(false); }, []); + const cross = bridgeInstance?.getCrossInfo(); + const assetLimit = assetLimitOnTargetChain?.amount; + const assetSupply = targetAssetSupply?.amount; + + const min = useMemo(() => { + if (cross && cross.fee.asset.local.id === sourceAsset.id) { + return cross.fee.amount; + } + return undefined; + }, [cross, sourceAsset.id]); + + const insufficient = + sourceAssetBalance?.amount && transferAmount?.input && sourceAssetBalance.amount.lt(transferAmount?.amount) + ? true + : false; + const requireMin = min && transferAmount?.input && transferAmount.amount.lt(min) ? true : false; + const requireLimit = isExcess(assetLimitOnTargetChain?.amount, targetAssetSupply?.amount, transferAmount?.amount); + + const handleInputChange = useCallback>( + (e) => { + if (e.target.value) { + if (!Number.isNaN(Number(e.target.value)) && sourceAsset) { + setTransferAmount( + parseValue(e.target.value, sourceAsset.decimals, min, sourceAssetBalance?.amount, assetLimit, assetSupply), + ); + } + } else { + setTransferAmount({ valid: true, input: e.target.value, amount: BN_ZERO }); + } + }, + [sourceAsset, min, sourceAssetBalance, assetLimit, assetSupply, setTransferAmount], + ); + return (
@@ -82,18 +129,58 @@ export default function AppBox() {
{ - setAmount(e.target.value); - }} + value={transferAmount?.input} + onChange={handleInputChange} className="h-[24px] flex-grow text-ellipsis whitespace-nowrap border-none bg-transparent text-[14px] font-[700] leading-[24px] outline-none" /> -
-

Balance: 994,744.238 USDT

+ {sourceAssetBalance && ( +

+ Balance: {formatBalance(sourceAssetBalance.amount, sourceAsset.decimals)} {sourceAsset.name} +

+ )} + {requireLimit ? ( +

+ {`* Limit: ${formatBalance(assetLimit ?? BN_ZERO, sourceAsset?.decimals ?? 0)}, supply: ${formatBalance( + (assetSupply ?? BN_ZERO).add(transferAmount?.amount ?? BN_ZERO), + sourceAsset?.decimals ?? 0, + )}.`} +

+ ) : requireMin ? ( +

+ {`* At least ${formatBalance(min ?? BN_ZERO, sourceAsset?.decimals ?? 0)} ${ + sourceAsset.symbol + } for tx fee.`} +

+ ) : insufficient ? ( +

* Insufficient.

+ ) : null}
); } + +function parseValue(origin: string, decimals: number, min?: BN, max?: BN, limit?: BN, supply?: BN) { + let input = ""; + let amount = BN_ZERO; + const [i, d] = origin.split(".").concat("-1"); + if (i) { + input = d === "-1" ? i : d ? `${i}.${d.slice(0, decimals)}` : `${i}.`; + amount = bnToBn(parseUnits(input, decimals)); + } + const valid = + min && amount.lt(min) ? false : max && amount.gt(max) ? false : isExcess(limit, supply, amount) ? false : true; + return { input, amount, valid }; +} + +function isExcess(limit?: BN, supply?: BN, amount = BN_ZERO) { + return limit && supply && supply.add(amount).gt(limit) ? true : false; +}