import type { RouteExtended } from '@lifi/sdk' import { Box } from '@mui/material' import { useNavigate } from '@tanstack/react-router' import { useRef } from 'react' import { useTranslation } from 'react-i18next' import type { BottomSheetBase } from '../../components/BottomSheet/types.js' import { Card } from '../../components/Card/Card.js' import { WarningMessages } from '../../components/Messages/WarningMessages.js' import { RouteTokens } from '../../components/RouteCard/RouteTokens.js' import { useAddressActivity } from '../../hooks/useAddressActivity.js' import { useWidgetEvents } from '../../hooks/useWidgetEvents.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' import { useHeaderStore } from '../../stores/header/useHeaderStore.js' import { WidgetEvent } from '../../types/events.js' import { getAccumulatedFeeCostsBreakdown } from '../../utils/fees.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { ConfirmToAddressSheet } from './ConfirmToAddressSheet.js' import { StartTransactionButton } from './StartTransactionButton.js' import { TokenValueBottomSheet } from './TokenValueBottomSheet.js' import { calculateValueLossPercentage, getTokenValueLossThreshold, } from './utils.js' interface TransactionReviewProps { route: RouteExtended executeRoute: () => void routeRefreshing: boolean } export const TransactionReview: React.FC = ({ route, executeRoute, routeRefreshing, }) => { const { t } = useTranslation() const navigate = useNavigate() const { setFieldValue } = useFieldActions() const emitter = useWidgetEvents() const setBackAction = useHeaderStore((state) => state.setBackAction) const { mode, modeOptions, hiddenUI, defaultUI } = useWidgetConfig() const tokenValueBottomSheetRef = useRef(null) const confirmToAddressSheetRef = useRef(null) const { toAddress, hasActivity, isLoading: isLoadingAddressActivity, isFetched: isActivityAddressFetched, } = useAddressActivity(route.toChainId) const handleExecuteRoute = () => { if (tokenValueBottomSheetRef.current?.isOpen()) { const { gasCostUSD, feeCostUSD } = getAccumulatedFeeCostsBreakdown(route) const fromAmountUSD = Number.parseFloat(route.fromAmountUSD) const toAmountUSD = Number.parseFloat(route.toAmountUSD) emitter.emit(WidgetEvent.RouteHighValueLoss, { fromAmountUSD, toAmountUSD, gasCostUSD, feeCostUSD, valueLoss: calculateValueLossPercentage( fromAmountUSD, toAmountUSD, gasCostUSD, feeCostUSD ), }) } tokenValueBottomSheetRef.current?.close() executeRoute() setFieldValue('fromAmount', '') if (mode === 'custom') { setFieldValue('fromToken', '') setFieldValue('toToken', '') } setBackAction(() => { navigate({ to: navigationRoutes.home, replace: true }) }) } const handleStartClick = () => { if ( toAddress && !hasActivity && !isLoadingAddressActivity && isActivityAddressFetched && !hiddenUI?.lowAddressActivityConfirmation ) { confirmToAddressSheetRef.current?.open() return } const { gasCostUSD, feeCostUSD } = getAccumulatedFeeCostsBreakdown(route) const fromAmountUSD = Number.parseFloat(route.fromAmountUSD) const toAmountUSD = Number.parseFloat(route.toAmountUSD) const tokenValueLossThresholdExceeded = getTokenValueLossThreshold( fromAmountUSD, toAmountUSD, gasCostUSD, feeCostUSD ) if (tokenValueLossThresholdExceeded && mode !== 'custom') { tokenValueBottomSheetRef.current?.open() } else { handleExecuteRoute() } } const getButtonText = (): string => { switch (mode) { case 'custom': return modeOptions?.custom?.type === 'deposit' ? t('button.deposit') : t('button.buy') case 'refuel': return t('button.startBridging') default: { const transactionType = route.fromChainId === route.toChainId ? 'Swapping' : 'Bridging' return t(`button.start${transactionType}`) } } } return ( <> {mode !== 'custom' ? ( ) : null} {!hiddenUI?.lowAddressActivityConfirmation ? ( ) : null} ) }