diff --git a/lib/modules/swap/SwapDetails.tsx b/lib/modules/swap/SwapDetails.tsx deleted file mode 100644 index 91cf48a9c..000000000 --- a/lib/modules/swap/SwapDetails.tsx +++ /dev/null @@ -1,134 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { NumberText } from '@/lib/shared/components/typography/NumberText' -import { useCurrency } from '@/lib/shared/hooks/useCurrency' -import { bn, fNum } from '@/lib/shared/utils/numbers' -import { HStack, VStack, Text, Tooltip, Box } from '@chakra-ui/react' -import { useSwap } from './SwapProvider' -import { GqlSorSwapType } from '@/lib/shared/services/api/generated/graphql' -import { useUserSettings } from '../user/settings/UserSettingsProvider' -import { usePriceImpact } from '@/lib/modules/price-impact/PriceImpactProvider' -import { SdkSimulateSwapResponse } from './swap.types' -import { DefaultSwapHandler } from './handlers/DefaultSwap.handler' -import { useTokens } from '../tokens/TokensProvider' -import { NativeWrapHandler } from './handlers/NativeWrap.handler' -import { InfoIcon } from '@/lib/shared/components/icons/InfoIcon' -import pluralize from 'pluralize' - -export function OrderRoute() { - const { simulationQuery } = useSwap() - - const queryData = simulationQuery.data as SdkSimulateSwapResponse - const orderRouteVersion = queryData ? queryData.protocolVersion : 2 - const hopCount = queryData.routes[0]?.hops?.length ?? 0 - - return ( - - Order route - - - BV{orderRouteVersion}: {hopCount} {pluralize('hop', hopCount)} - - - - - - - ) -} - -export function SwapDetails() { - const { toCurrency } = useCurrency() - const { slippage, slippageDecimal } = useUserSettings() - const { usdValueForToken } = useTokens() - const { tokenInInfo, tokenOutInfo, swapType, tokenIn, tokenOut, handler } = useSwap() - - const { priceImpactLevel, priceImpactColor, PriceImpactIcon, priceImpact } = usePriceImpact() - - const isDefaultSwap = handler instanceof DefaultSwapHandler - const isNativeWrapOrUnwrap = handler instanceof NativeWrapHandler - - const _slippage = isNativeWrapOrUnwrap ? 0 : slippage - const _slippageDecimal = isNativeWrapOrUnwrap ? 0 : slippageDecimal - - const returnAmountUsd = - swapType === GqlSorSwapType.ExactIn - ? usdValueForToken(tokenOutInfo, tokenOut.amount) - : usdValueForToken(tokenInInfo, tokenIn.amount) - - const priceImpactLabel = priceImpact ? fNum('priceImpact', priceImpact) : '-' - const priceImpacUsd = bn(priceImpact || 0).times(returnAmountUsd) - const maxSlippageUsd = bn(_slippage).div(100).times(returnAmountUsd) - - const isExactIn = swapType === GqlSorSwapType.ExactIn - - const limitLabel = isExactIn ? "You'll get at least" : "You'll pay at most" - const limitToken = isExactIn ? tokenOutInfo : tokenInInfo - const limitValue = isExactIn - ? bn(tokenOut.amount).minus(bn(tokenOut.amount).times(_slippageDecimal)).toString() - : bn(tokenIn.amount).plus(bn(tokenIn.amount).times(_slippageDecimal)).toString() - const limitTooltip = isExactIn - ? 'You will get at least this amount of token out.' - : 'You will pay at most this amount of token in.' - - const slippageLabel = isExactIn - ? `This is the maximum slippage that the swap will allow. - It is based on the quoted amount out minus your slippage tolerance, using current market prices. - You can change your slippage tolerance in your settings.` - : `This is the maximum slippage that the swap will allow. - It is based on the quoted amount in plus your slippage tolerance, using current market prices. - You can change your slippage tolerance in your settings.` - - return ( - - - Price impact - - {priceImpactLevel === 'unknown' ? ( - Unknown - ) : ( - - -{toCurrency(priceImpacUsd, { abbreviated: false })} (-{priceImpactLabel}) - - )} - - {priceImpactLevel === 'low' ? ( - - ) : ( - - - - )} - - - - - Max slippage - - - -{toCurrency(maxSlippageUsd, { abbreviated: false })} (-{fNum('slippage', _slippage)}) - - - - - - - - {limitLabel} - - - {fNum('token', limitValue, { abbreviated: false })} {limitToken?.symbol} - - - - - - - - {isDefaultSwap && } - - ) -} diff --git a/lib/modules/swap/SwapForm.tsx b/lib/modules/swap/SwapForm.tsx index 320f5fc07..5b2f07069 100644 --- a/lib/modules/swap/SwapForm.tsx +++ b/lib/modules/swap/SwapForm.tsx @@ -7,7 +7,7 @@ import { TransactionSettings } from '../user/settings/TransactionSettings' import { useSwap } from './SwapProvider' export function SwapForm() { - const { tokenIn, tokenOut, selectedChain, swapAction } = useSwap() + const { tokenIn, tokenOut, selectedChain } = useSwap() return ( @@ -20,12 +20,6 @@ export function SwapForm() { left={['-12px', '0']} > - - {capitalize(swapAction)} - - - - diff --git a/lib/modules/swap/SwapRate.tsx b/lib/modules/swap/SwapRate.tsx deleted file mode 100644 index 143f5f59c..000000000 --- a/lib/modules/swap/SwapRate.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Text } from '@chakra-ui/react' -import { useState } from 'react' -import { useSwap } from './SwapProvider' -import { useCurrency } from '@/lib/shared/hooks/useCurrency' -import { useTokens } from '../tokens/TokensProvider' -import { fNum } from '@/lib/shared/utils/numbers' - -export function SwapRate() { - const [priceDirection, setPriceDirection] = useState<'givenIn' | 'givenOut'>('givenIn') - const { simulationQuery, tokenInInfo, tokenOutInfo } = useSwap() - const { toCurrency } = useCurrency() - const { usdValueForToken } = useTokens() - - const effectivePrice = fNum('token', simulationQuery.data?.effectivePrice || '0', { - abbreviated: false, - }) - const effectivePriceReversed = fNum( - 'token', - simulationQuery.data?.effectivePriceReversed || '0', - { abbreviated: false } - ) - - const tokenInUsdValue = usdValueForToken(tokenInInfo, 1) - const tokenOutUsdValue = usdValueForToken(tokenOutInfo, 1) - - const priceLabel = - priceDirection === 'givenIn' - ? `1 ${tokenInInfo?.symbol} = ${effectivePriceReversed} ${tokenOutInfo?.symbol} (${toCurrency( - tokenInUsdValue, - { abbreviated: false } - )})` - : `1 ${tokenOutInfo?.symbol} = ${effectivePrice} ${tokenInInfo?.symbol} (${toCurrency( - tokenOutUsdValue, - { abbreviated: false } - )})` - - const togglePriceDirection = (e: React.MouseEvent) => { - e.preventDefault() - setPriceDirection(priceDirection === 'givenIn' ? 'givenOut' : 'givenIn') - } - - return ( - - {simulationQuery.data && priceLabel} - - ) -} diff --git a/lib/modules/swap/modal/SwapModal.tsx b/lib/modules/swap/modal/SwapModal.tsx deleted file mode 100644 index b015863fb..000000000 --- a/lib/modules/swap/modal/SwapModal.tsx +++ /dev/null @@ -1,95 +0,0 @@ -'use client' - -import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalProps } from '@chakra-ui/react' -import { RefObject, useEffect, useRef } from 'react' -import { DesktopStepTracker } from '../../transactions/transaction-steps/step-tracker/DesktopStepTracker' -import { useSwap } from '../SwapProvider' -import { SwapTimeout } from './SwapTimeout' -import { useBreakpoints } from '@/lib/shared/hooks/useBreakpoints' -import { capitalize } from 'lodash' -import { ActionModalFooter } from '../../../shared/components/modals/ActionModalFooter' -import { TransactionModalHeader } from '../../../shared/components/modals/TransactionModalHeader' -import { chainToSlugMap } from '../../pool/pool.utils' -// eslint-disable-next-line max-len -import { getStylesForModalContentWithStepTracker } from '../../transactions/transaction-steps/step-tracker/step-tracker.utils' -import { SuccessOverlay } from '@/lib/shared/components/modals/SuccessOverlay' -import { useResetStepIndexOnOpen } from '../../pool/actions/useResetStepIndexOnOpen' -import { useOnUserAccountChanged } from '../../web3/useOnUserAccountChanged' -import { SwapSummary } from './SwapSummary' -import { useSwapReceipt } from '../../transactions/transaction-steps/receipts/receipt.hooks' -import { useUserAccount } from '../../web3/UserAccountProvider' - -type Props = { - isOpen: boolean - onClose(): void - onOpen(): void - finalFocusRef?: RefObject -} - -export function SwapPreviewModal({ - isOpen, - onClose, - finalFocusRef, - ...rest -}: Props & Omit) { - const { isDesktop } = useBreakpoints() - const initialFocusRef = useRef(null) - const { userAddress } = useUserAccount() - - const { transactionSteps, swapAction, isWrap, selectedChain, swapTxHash, hasQuoteContext } = - useSwap() - - const swapReceipt = useSwapReceipt({ - txHash: swapTxHash, - userAddress, - chain: selectedChain, - }) - - useResetStepIndexOnOpen(isOpen, transactionSteps) - - useEffect(() => { - if (!isWrap && swapTxHash && !window.location.pathname.includes(swapTxHash)) { - window.history.pushState({}, '', `/swap/${chainToSlugMap[selectedChain]}/${swapTxHash}`) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [swapTxHash]) - - useOnUserAccountChanged(onClose) - - return ( - - - - - {isDesktop && hasQuoteContext && ( - - )} - } - txHash={swapTxHash} - chain={selectedChain} - isReceiptLoading={swapReceipt.isLoading} - /> - - - - - - - - ) -} diff --git a/lib/modules/swap/modal/SwapSummary.tsx b/lib/modules/swap/modal/SwapSummary.tsx deleted file mode 100644 index 8abc9fe88..000000000 --- a/lib/modules/swap/modal/SwapSummary.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { useBreakpoints } from '@/lib/shared/hooks/useBreakpoints' -import { Card, HStack, Text } from '@chakra-ui/react' -import { SwapTokenRow } from '../../tokens/TokenRow/SwapTokenRow' -import { MobileStepTracker } from '../../transactions/transaction-steps/step-tracker/MobileStepTracker' -import { SwapDetails } from '../SwapDetails' -import { SwapRate } from '../SwapRate' -import { useSwap } from '../SwapProvider' -import { SwapReceiptResult } from '../../transactions/transaction-steps/receipts/receipt.hooks' -import { useUserAccount } from '../../web3/UserAccountProvider' -import { BalAlert } from '@/lib/shared/components/alerts/BalAlert' -import { HumanAmount } from '@balancer/sdk' -import { slippageDiffLabel } from '@/lib/shared/utils/slippage' -import { AnimateHeightChange } from '@/lib/shared/components/modals/AnimatedModalBody' -import { CardPopAnim } from '@/lib/shared/components/animations/CardPopAnim' - -export function SwapSummary({ - isLoading: isLoadingReceipt, - receivedToken, - sentToken, - error, -}: SwapReceiptResult) { - const { isMobile } = useBreakpoints() - const { userAddress, isLoading: isUserAddressLoading } = useUserAccount() - const { - tokenIn, - tokenOut, - transactionSteps, - selectedChain, - isWrap, - swapTxHash, - swapTxConfirmed, - simulationQuery, - hasQuoteContext, - } = useSwap() - - const expectedTokenOut = simulationQuery?.data?.returnAmount as HumanAmount - - const shouldShowReceipt = - !isWrap && !!swapTxHash && !isLoadingReceipt && !!receivedToken && !!sentToken - const shouldShowErrors = hasQuoteContext ? swapTxConfirmed : swapTxHash - const isWrapComplete = isWrap && swapTxHash && swapTxConfirmed - - function tokenOutLabel() { - if (shouldShowReceipt || isWrapComplete) return 'You got' - if (isWrap) return "You'll get" - return "You'll get (if no slippage)" - } - - if (!isUserAddressLoading && !userAddress) { - return - } - if (shouldShowErrors && error) { - return - } - if (shouldShowErrors && !isLoadingReceipt && (!receivedToken || !sentToken)) { - return ( - - ) - } - - return ( - - {isMobile && } - - - - - - - - - - {!shouldShowReceipt && !isWrapComplete && ( - <> - - {!swapTxHash && ( - - - - )} - - - - - Exchange rate - - - - - - )} - - ) -} diff --git a/lib/modules/swap/modal/SwapTimeout.tsx b/lib/modules/swap/modal/SwapTimeout.tsx deleted file mode 100644 index c5ee19b47..000000000 --- a/lib/modules/swap/modal/SwapTimeout.tsx +++ /dev/null @@ -1,84 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { HStack, Text } from '@chakra-ui/react' -import { useEffect } from 'react' -import { useCountdown } from 'usehooks-ts' -import { useSwap } from '../SwapProvider' -import { NumberText } from '@/lib/shared/components/typography/NumberText' -import { useShouldFreezeQuote } from '../../transactions/transaction-steps/useShouldFreezeQuote' -import { swapStepId } from '../useSwapStep' - -function useSwapTimeout() { - // This countdown needs to be nested here and not at a higher level, like in - // useAddLiquidity, because otherwise it causes re-renders of the entire - // add-liquidity flow component tree every second. - const [secondsToRefetch, { startCountdown, stopCountdown, resetCountdown }] = useCountdown({ - countStart: 30, - intervalMs: 1000, - }) - - const { simulationQuery, previewModalDisclosure } = useSwap() - - // Disable query refetches: - // if the flow is complete - // if the swap transaction is confirming - const { shouldFreezeQuote } = useShouldFreezeQuote(swapStepId) - - // When the countdown timer reaches 0, refetch all add liquidity queries. - useEffect(() => { - const refetchQueries = async () => { - stopCountdown() - resetCountdown() - await simulationQuery.refetch() - startCountdown() - } - if (secondsToRefetch === 0 && !shouldFreezeQuote) refetchQueries() - }, [secondsToRefetch]) - - // If the transaction flow is complete or confirming, stop the countdown timer. - // Else start the timer. - useEffect(() => { - if (shouldFreezeQuote) { - stopCountdown() - resetCountdown() - } else { - startCountdown() - } - }, [shouldFreezeQuote]) - - // When the modal is closed the timeout should be stopped and reset. - useEffect(() => { - if (!previewModalDisclosure.isOpen) { - stopCountdown() - resetCountdown() - } - }, [previewModalDisclosure.isOpen]) - - // On first render, start the countdown. - useEffect(() => { - stopCountdown() - resetCountdown() - startCountdown() - }, []) - - return { secondsToRefetch, shouldFreezeQuote } -} - -export function SwapTimeout() { - const { secondsToRefetch, shouldFreezeQuote } = useSwapTimeout() - - return ( - !shouldFreezeQuote && ( - - Quote refresh in - - - {secondsToRefetch} - - - s - - - - ) - ) -} diff --git a/lib/modules/tokens/TokenRow/SwapTokenRow.tsx b/lib/modules/tokens/TokenRow/SwapTokenRow.tsx deleted file mode 100644 index 1fb028daf..000000000 --- a/lib/modules/tokens/TokenRow/SwapTokenRow.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { VStack, HStack, Text } from '@chakra-ui/react' -import { Address } from 'viem' -import TokenRow from './TokenRow' -import { GqlChain } from '@/lib/shared/services/api/generated/graphql' -import { HumanAmount } from '@balancer/sdk' -import { useSwap } from '../../swap/SwapProvider' -import { slippageDiffLabel } from '@/lib/shared/utils/slippage' - -export function ReceiptTokenOutRow({ - chain, - actualReceivedTokenAmount, - tokenAddress, -}: { - chain: GqlChain - actualReceivedTokenAmount: HumanAmount - tokenAddress: string -}) { - const { simulationQuery } = useSwap() - const expectedTokenOut = simulationQuery?.data?.returnAmount as HumanAmount - return ( - - ) -} - -export function SwapTokenRow({ - label, - rightLabel, - chain, - tokenAmount, - tokenAddress, -}: { - label: string - chain: GqlChain - tokenAmount: string - tokenAddress: string - rightLabel?: string -}) { - return ( - - - - {label} - - {rightLabel && {rightLabel}} - - - - - ) -}