import React, { useEffect, useState, useRef, useCallback, useMemo } from 'react' import { useDispatch } from 'react-redux' import { useAccount } from 'wagmi' import { debounce } from 'lodash' import { useTranslations } from 'next-intl' import { TokenSelector } from '@/components/ui/TokenSelector' import { formatBigIntToString, stringToBigInt } from '@/utils/bigint/format' import { cleanNumberInput } from '@/utils/cleanNumberInput' import { ConnectToNetworkButton, ConnectWalletButton, ConnectedIndicator, } from '@/components/ConnectionIndicators' import { ChainSelector } from '@/components/ui/ChainSelector' import { usePortfolioState } from '@/slices/portfolio/hooks' import { initialState, setSwapChainId, setSwapFromToken, updateSwapFromValue, } from '@/slices/swap/reducer' import { useSwapState } from '@/slices/swap/hooks' import { BridgeSectionContainer } from '@/components/ui/BridgeSectionContainer' import { BridgeAmountContainer } from '@/components/ui/BridgeAmountContainer' import { CHAINS_BY_ID } from '@/constants/chains' import { useSwapChainListArray } from '@/components/StateManagedSwap//hooks/useSwapChainListArray' import { useSwapFromTokenListArray } from '@/components/StateManagedSwap/hooks/useSwapFromTokenListOverlay' import { AmountInput } from '@/components/ui/AmountInput' import { joinClassNames } from '@/utils/joinClassNames' import { trimTrailingZeroesAfterDecimal } from '@/utils/trimTrailingZeroesAfterDecimal' import { formatAmount } from '@/utils/formatAmount' import { getParsedBalance } from '@/utils/getParsedBalance' import { useWalletState } from '@/slices/wallet/hooks' import { useUsdDisplay } from '@hooks/useUsdDisplay' interface InputContainerProps { setIsTyping: React.Dispatch> } export const SwapInputContainer: React.FC = ({ setIsTyping, }) => { const inputRef = useRef(null) const { swapChainId, swapFromToken, swapToToken, swapFromValue } = useSwapState() const [showValue, setShowValue] = useState('') const [hasMounted, setHasMounted] = useState(false) const { balances } = usePortfolioState() const { isWalletPending } = useWalletState() useEffect(() => { setHasMounted(true) }, []) const { isConnected } = useAccount() const { chain } = useAccount() const dispatch = useDispatch() const tokenData = balances[swapChainId]?.find( (token) => token.tokenAddress === swapFromToken?.addresses[swapChainId] ) const balance = tokenData?.balance const decimals = tokenData?.token?.decimals[swapChainId] const parsedBalance = balance !== undefined && decimals !== undefined ? getParsedBalance(balance, decimals) : '0.0' const formattedBalance = formatAmount(parsedBalance) const isInputMax = parsedBalance === swapFromValue const isBalanceClickable = balance && !isInputMax const t = useTranslations('Swap') // Fetch token price and calculate USD value const usdValue = useUsdDisplay(swapFromToken, showValue) useEffect(() => { if ( swapFromToken && swapFromToken.decimals[swapChainId] && stringToBigInt(swapFromValue, swapFromToken.decimals[swapChainId]) !== 0n ) { setShowValue(swapFromValue) } if (swapFromValue === initialState.swapFromValue) { setShowValue(initialState.swapFromValue) } }, [swapFromValue, swapChainId, swapFromToken]) const debouncedUpdateSwapFromValue = useMemo( () => debounce((value: string) => dispatch(updateSwapFromValue(value)), 400), [dispatch] ) useEffect(() => { return () => { debouncedUpdateSwapFromValue.cancel() } }, [debouncedUpdateSwapFromValue]) const handleFromValueChange = ( event: React.ChangeEvent ) => { const swapFromValueString: string = cleanNumberInput(event.target.value) try { setShowValue(swapFromValueString) debouncedUpdateSwapFromValue(swapFromValueString) } catch (error) { console.error('Invalid value for conversion to BigInteger') const inputValue = event.target.value const regex = /^[0-9]*[.,]?[0-9]*$/ if (regex.test(inputValue) || inputValue === '') { debouncedUpdateSwapFromValue(inputValue) setShowValue(inputValue) } } } const onMaxBalance = useCallback(() => { dispatch( updateSwapFromValue( trimTrailingZeroesAfterDecimal( formatBigIntToString(balance, swapFromToken.decimals[swapChainId]) ) ) ) }, [balance, swapChainId, swapFromToken]) const connectedStatus = useMemo(() => { if (hasMounted && isConnected) { if (swapChainId === chain.id) { return } else if (swapChainId !== chain.id) { return } } else if (hasMounted && !isConnected) { return } }, [chain, swapChainId, isConnected, hasMounted]) const labelClassNames = { space: 'block', textColor: 'text-xxs md:text-xs', cursor: 'cursor-default', } return (
{connectedStatus}
{usdValue}
{hasMounted && isConnected && ( )}
) } const SwapChainSelector = () => { const { swapChainId } = useSwapState() const { isWalletPending } = useWalletState() const t = useTranslations('Bridge') return ( ) } const SwapFromTokenSelector = () => { const { swapFromToken } = useSwapState() const { isWalletPending } = useWalletState() const t = useTranslations('Bridge') return ( ) }