import type { RouteExtended } from '@lifi/sdk' import { useEthereumContext } from '@lifi/widget-provider' import { Box, Tooltip } from '@mui/material' import type { JSX } from 'react' import { useTranslation } from 'react-i18next' import { useTokenRateText } from '../../hooks/useTokenRateText.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { isRouteDone } from '../../stores/routes/utils.js' import { getAccumulatedFeeCostsBreakdown } from '../../utils/fees.js' import { formatDuration, formatTokenAmount, formatTokenPrice, } from '../../utils/format.js' import { getPriceImpact } from '../../utils/getPriceImpact.js' import { FeeBreakdownTooltip } from '../FeeBreakdownTooltip.js' import { StepActions } from '../Step/StepActions.js' import { DetailInfoIcon, DetailLabel, DetailLabelContainer, DetailRow, DetailValue, } from './RouteDetails.style.js' interface RouteDetailsProps { route: RouteExtended } export const RouteDetails = ({ route }: RouteDetailsProps): JSX.Element => { const { t, i18n } = useTranslation() const { rateText, toggleRate } = useTokenRateText(route) const { feeConfig } = useWidgetConfig() const { isGaslessStep } = useEthereumContext() const { gasCosts, feeCosts, gasCostUSD, feeCostUSD } = getAccumulatedFeeCostsBreakdown(route) const priceImpact = getPriceImpact({ fromAmount: BigInt(route.fromAmount), toAmount: BigInt(route.toAmount), fromToken: route.fromToken, toToken: route.toToken, }) let feeAmountUSD = 0 let feePercentage = 0 const feeCollectionStep = route.steps[0].includedSteps.find( (includedStep) => includedStep.tool === 'feeCollection' ) if (feeCollectionStep) { const estimatedFromAmount = BigInt(feeCollectionStep.estimate.fromAmount) - BigInt(feeCollectionStep.estimate.toAmount) feeAmountUSD = formatTokenPrice( estimatedFromAmount, feeCollectionStep.action.fromToken.priceUSD, feeCollectionStep.action.fromToken.decimals ) feePercentage = feeCollectionStep.estimate.feeCosts?.reduce( (percentage, feeCost) => percentage + Number.parseFloat(feeCost.percentage || '0'), 0 ) ?? 0 } const executionTimeSeconds = Math.floor( route.steps.reduce( (duration, step) => duration + step.estimate.executionDuration, 0 ) ) const hasGaslessSupport = route.steps.every((step) => isGaslessStep?.(step)) const showIntegratorFeeCollectionDetails = (feeAmountUSD || Number.isFinite(feeConfig?.fee)) && !hasGaslessSupport return ( {t('main.fees.network')} {!gasCostUSD ? t('main.fees.free') : t('format.currency', { value: gasCostUSD })} {feeCosts.length ? ( {t('main.fees.provider')} {t('format.currency', { value: feeCostUSD })} ) : null} {showIntegratorFeeCollectionDetails ? ( {feeConfig?.name || t('main.fees.defaultIntegrator')} {feeConfig?.showFeePercentage && ( <> ({t('format.percent', { value: feePercentage })}) )} {feeConfig?.showFeeTooltip && (feeConfig?.name || feeConfig?.feeTooltipComponent) ? ( ) : null} {t('format.currency', { value: feeAmountUSD })} ) : null} {t('main.priceImpact')} {t('format.percent', { value: priceImpact, usePlusSign: true })} {!isRouteDone(route) ? ( <> {t('main.maxSlippage')} {route.steps[0].action.slippage ? t('format.percent', { value: route.steps[0].action.slippage, }) : t('button.auto')} {t('main.minReceived')} {t('format.tokenAmount', { value: formatTokenAmount( BigInt(route.toAmountMin), route.toToken.decimals ), })}{' '} {route.toToken.symbol} ) : null} {t('main.exchangeRate')} {rateText} {t('main.estimatedTime')} {formatDuration(executionTimeSeconds, i18n.language)} ) }