import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' import { Trade } from '@uniswap/v3-sdk' import { V3TradeState } from 'state/routing/types' import { useRoutingAPITrade } from 'state/routing/useRoutingAPITrade' import { useRoutingAPIEnabled } from 'state/user/hooks' import { useClientSideV3Trade } from './useClientSideV3Trade' import useDebounce from './useDebounce' import useIsWindowVisible from './useIsWindowVisible' /** * Returns the best v3 trade for a desired swap. * Uses optimized routes from the Routing API and falls back to the v3 router. * @param tradeType whether the swap is an exact in/out * @param amountSpecified the exact amount to swap in/out * @param otherCurrency the desired output/payment currency */ export function useBestV3Trade( tradeType: TradeType, amountSpecified?: CurrencyAmount, otherCurrency?: Currency ): { state: V3TradeState trade: Trade | null } { const routingAPIEnabled = useRoutingAPIEnabled() const isWindowVisible = useIsWindowVisible() const debouncedAmount = useDebounce(amountSpecified, 100) const routingAPITrade = useRoutingAPITrade( tradeType, routingAPIEnabled && isWindowVisible ? debouncedAmount : undefined, otherCurrency ) const isLoading = amountSpecified !== undefined && debouncedAmount === undefined // consider trade debouncing when inputs/outputs do not match const debouncing = routingAPITrade.trade && amountSpecified && (tradeType === TradeType.EXACT_INPUT ? !routingAPITrade.trade.inputAmount.equalTo(amountSpecified) || !amountSpecified.currency.equals(routingAPITrade.trade.inputAmount.currency) || !otherCurrency?.equals(routingAPITrade.trade.outputAmount.currency) : !routingAPITrade.trade.outputAmount.equalTo(amountSpecified) || !amountSpecified.currency.equals(routingAPITrade.trade.outputAmount.currency) || !otherCurrency?.equals(routingAPITrade.trade.inputAmount.currency)) const useFallback = !routingAPIEnabled || (!debouncing && routingAPITrade.state === V3TradeState.NO_ROUTE_FOUND) // only use client side router if routing api trade failed const bestV3Trade = useClientSideV3Trade( tradeType, useFallback ? debouncedAmount : undefined, useFallback ? otherCurrency : undefined ) return { ...(useFallback ? bestV3Trade : routingAPITrade), ...(debouncing ? { state: V3TradeState.SYNCING } : {}), ...(isLoading ? { state: V3TradeState.LOADING } : {}), } }