import { Currency, Token } from '@uniswap/sdk-core' import { useMemo } from 'react' import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants/routing' export function useAllCurrencyCombinations(currencyA?: Currency, currencyB?: Currency): [Token, Token][] { const chainId = currencyA?.chainId const [tokenA, tokenB] = chainId ? [currencyA?.wrapped, currencyB?.wrapped] : [undefined, undefined] const bases: Token[] = useMemo(() => { if (!chainId || chainId !== tokenB?.chainId) return [] const common = BASES_TO_CHECK_TRADES_AGAINST[chainId] ?? [] const additionalA = tokenA ? ADDITIONAL_BASES[chainId]?.[tokenA.address] ?? [] : [] const additionalB = tokenB ? ADDITIONAL_BASES[chainId]?.[tokenB.address] ?? [] : [] return [...common, ...additionalA, ...additionalB] }, [chainId, tokenA, tokenB]) const basePairs: [Token, Token][] = useMemo( () => bases .flatMap((base): [Token, Token][] => bases.map((otherBase) => [base, otherBase])) // though redundant with the first filter below, that expression runs more often, so this is probably worthwhile .filter(([t0, t1]) => !t0.equals(t1)), [bases] ) return useMemo( () => tokenA && tokenB ? [ // the direct pair [tokenA, tokenB] as [Token, Token], // token A against all bases ...bases.map((base): [Token, Token] => [tokenA, base]), // token B against all bases ...bases.map((base): [Token, Token] => [tokenB, base]), // each base against all bases ...basePairs, ] // filter out invalid pairs comprised of the same asset (e.g. WETH<>WETH) .filter(([t0, t1]) => !t0.equals(t1)) // filter out duplicate pairs .filter(([t0, t1], i, otherPairs) => { // find the first index in the array at which there are the same 2 tokens as the current const firstIndexInOtherPairs = otherPairs.findIndex(([t0Other, t1Other]) => { return (t0.equals(t0Other) && t1.equals(t1Other)) || (t0.equals(t1Other) && t1.equals(t0Other)) }) // only accept the first occurrence of the same 2 tokens return firstIndexInOtherPairs === i }) // optionally filter out some pairs for tokens with custom bases defined .filter(([tokenA, tokenB]) => { if (!chainId) return true const customBases = CUSTOM_BASES[chainId] const customBasesA: Token[] | undefined = customBases?.[tokenA.address] const customBasesB: Token[] | undefined = customBases?.[tokenB.address] if (!customBasesA && !customBasesB) return true if (customBasesA && !customBasesA.find((base) => tokenB.equals(base))) return false if (customBasesB && !customBasesB.find((base) => tokenA.equals(base))) return false return true }) : [], [tokenA, tokenB, bases, basePairs, chainId] ) }