import { OptionKey, Stack, Heading, Box, Body, Button, } from '@biom3/react'; import { IMTBLWidgetEvents } from '@imtbl/checkout-sdk'; import { Dispatch, SetStateAction, useContext, useMemo, useCallback, } from 'react'; import { useTranslation } from 'react-i18next'; import { SelectInput } from '../../components/FormComponents/SelectInput/SelectInput'; import { TextInputForm } from '../../components/FormComponents/TextInputForm/TextInputForm'; import { HeaderNavigation } from '../../components/Header/HeaderNavigation'; import { SimpleLayout } from '../../components/SimpleLayout/SimpleLayout'; import { CryptoFiatContext } from '../../context/crypto-fiat-context/CryptoFiatContext'; import { EventTargetContext } from '../../context/event-target-context/EventTargetContext'; import { orchestrationEvents } from '../../lib/orchestrationEvents'; import { tokenValueFormat, getDefaultTokenImage, calculateCryptoToFiat, formatZeroAmount, } from '../../lib/utils'; import { amountInputValidation } from '../../lib/validations/amountInputValidations'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; import { TransferFormState, TransferState } from './context'; import { getOptionKey, getFiatAmount, validatePartialAddress } from './functions'; import { sendCloseWidgetEvent } from '../connect/connectWidgetEvents'; export function TransferForm({ config, viewState, setViewState, onSend, showBackButton, showHeader, title, coinAmountTitle, }: { config: StrongCheckoutWidgetsConfig; viewState: TransferFormState; setViewState: Dispatch>; onSend: () => void; showBackButton: boolean | undefined; showHeader: boolean; title: string; coinAmountTitle: string; }) { const { t } = useTranslation(); const { eventTargetState: { eventTarget } } = useContext(EventTargetContext); const { cryptoFiatState } = useContext(CryptoFiatContext); const tokenOptions = useMemo( () => viewState.allowedBalances.map( (tokenBalance) => ({ id: getOptionKey(tokenBalance.token), name: tokenBalance.token.name, symbol: tokenBalance.token.symbol, defaultTokenImage: tokenBalance.token.icon || 'TODO', balance: { fullBalance: tokenBalance.formattedBalance, formattedAmount: tokenValueFormat(tokenBalance.formattedBalance), formattedFiatAmount: getFiatAmount(cryptoFiatState, tokenBalance), }, }), ), [viewState.allowedBalances, cryptoFiatState], ); const token = useMemo( () => tokenOptions.find((option) => option.id === viewState.tokenAddress), [tokenOptions, viewState.tokenAddress], ); const defaultTokenImage = useMemo( () => getDefaultTokenImage(viewState.checkout.config.environment, config.theme), [viewState.checkout.config.environment, config.theme], ); const fromFiatValue = useMemo( () => calculateCryptoToFiat( viewState.amount, token?.symbol || '', cryptoFiatState.conversions, ), [viewState.amount, token, cryptoFiatState.conversions], ); const handleTokenChange = useCallback( (optionKey: OptionKey) => { if (typeof optionKey !== 'string') throw new Error('Invalid token address'); setViewState((s) => ({ ...s, tokenAddress: optionKey, amountError: '' })); }, [setViewState], ); const handleMaxButtonClick = useCallback(() => { if (!token) throw new Error('Token not found'); if (!token.balance) throw new Error('Token balance not found'); setViewState((s) => { if (!token.balance) throw new Error('Token balance not found'); return { ...s, amount: token.balance.fullBalance }; }); }, [token, setViewState]); const handleRecipientAddressChange = useCallback((value: string) => { setViewState((s) => ({ ...s, toAddress: value, toAddressError: '' })); }, [setViewState]); const handleAmountChange = useCallback((value: string) => { setViewState((s) => ({ ...s, amount: value, amountError: '' })); }, [setViewState]); const selectSubtext = useMemo(() => { if (!token) return ''; return `${t('views.TRANSFER.content.availableBalancePrefix')} ${ token.balance?.formattedAmount }`; }, [token, t]); const isButtonDisabled = useMemo( () => !viewState.amount || !viewState.toAddress || !token, [viewState.amount, viewState.toAddress, token], ); return ( sendCloseWidgetEvent(eventTarget)} showBack={showBackButton} onBackButtonClick={() => { orchestrationEvents.sendRequestGoBackEvent( eventTarget, IMTBLWidgetEvents.IMTBL_TRANSFER_WIDGET_EVENT, {}, ); }} /> ) : undefined} > {coinAmountTitle} {t('views.TRANSFER.form.toAddressHeading')} } size="xSmall" weight="bold" sx={{ color: 'base.color.text.status.fatal.primary' }} > {t('views.TRANSFER.content.notAllExchangesSupportImmutableZkEVM')} } size="xxSmall" weight="regular" sx={{ mb: 'base.spacing.x4' }} > {t( 'views.TRANSFER.content.notAllExchangesSupportImmutableZkEVMDescription', )} ); }