uniswap-interface-uncensored/src/hooks/useAllV3Routes.ts

76 lines
2.3 KiB
TypeScript
Raw Normal View History

import { Currency } from '@uniswap/sdk-core'
import { Pool, Route } from '@uniswap/v3-sdk'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useMemo } from 'react'
import { useV3SwapPools } from './useV3SwapPools'
/**
* Returns true if poolA is equivalent to poolB
* @param poolA one of the two pools
* @param poolB the other pool
*/
function poolEquals(poolA: Pool, poolB: Pool): boolean {
return (
poolA === poolB ||
(poolA.token0.equals(poolB.token0) && poolA.token1.equals(poolB.token1) && poolA.fee === poolB.fee)
)
}
function computeAllRoutes(
currencyIn: Currency,
currencyOut: Currency,
pools: Pool[],
chainId: number,
currentPath: Pool[] = [],
allPaths: Route<Currency, Currency>[] = [],
startCurrencyIn: Currency = currencyIn,
maxHops = 2
): Route<Currency, Currency>[] {
const tokenIn = currencyIn?.wrapped
const tokenOut = currencyOut?.wrapped
if (!tokenIn || !tokenOut) throw new Error('Missing tokenIn/tokenOut')
for (const pool of pools) {
if (!pool.involvesToken(tokenIn) || currentPath.find((pathPool) => poolEquals(pool, pathPool))) continue
const outputToken = pool.token0.equals(tokenIn) ? pool.token1 : pool.token0
if (outputToken.equals(tokenOut)) {
allPaths.push(new Route([...currentPath, pool], startCurrencyIn, currencyOut))
} else if (maxHops > 1) {
computeAllRoutes(
outputToken,
currencyOut,
pools,
chainId,
[...currentPath, pool],
allPaths,
startCurrencyIn,
maxHops - 1
)
}
}
return allPaths
}
/**
* Returns all the routes from an input currency to an output currency
* @param currencyIn the input currency
* @param currencyOut the output currency
*/
export function useAllV3Routes(
currencyIn?: Currency,
currencyOut?: Currency
): { loading: boolean; routes: Route<Currency, Currency>[] } {
const { chainId } = useActiveWeb3React()
const { pools, loading: poolsLoading } = useV3SwapPools(currencyIn, currencyOut)
return useMemo(() => {
if (poolsLoading || !chainId || !pools || !currencyIn || !currencyOut) return { loading: true, routes: [] }
const routes = computeAllRoutes(currencyIn, currencyOut, pools, chainId, [], [], currencyIn, 2)
return { loading: false, routes }
}, [chainId, currencyIn, currencyOut, pools, poolsLoading])
}