import { Currency , CurrencyAmount , Pair , Token , Trade } from '@pancakeswap-libs/sdk' ; import flatMap from 'lodash.flatmap' ; import { useMemo } from 'react' ; import { BASES_TO_CHECK_TRADES_AGAINST , CUSTOM_BASES } from '../constants' ; import { PairState , usePairs } from '../data/Reserves' ; import { wrappedCurrency } from '../utils/wrappedCurrency' ; import { useActiveWeb3React } from './index' ; function useAllCommonPairs ( currencyA ? , currencyB ? ) { const { chainId } = useActiveWeb3React ( ) ; const bases = useMemo ( ( ) => ( chainId ? BASES_TO_CHECK_TRADES_AGAINST [ chainId ] : [ ] ) , [ chainId ] ) ; const basePairs = useMemo ( ( ) => flatMap ( bases , ( base ) : [ Token , Token ] [ ] => bases . map ( ( otherBase ) => [ base , otherBase ] ) ) . filter ( ( [ t0 , t1 ] ) => t0 . address !== t1 . address ) , [ bases ] ) ; const [ tokenA , tokenB ] = chainId ? [ wrappedCurrency ( currencyA , chainId ) , wrappedCurrency ( currencyB , chainId ) ] : [ undefined , undefined ] ; const allPairCombinations = useMemo ( ( ) => tokenA && tokenB ? [ [ tokenA , tokenB ] , ... bases . map ( ( base ) : [ Token , Token ] => [ tokenA , base ] ) , ... bases . map ( ( base ) : [ Token , Token ] => [ tokenB , base ] ) , ... basePairs , ] . filter ( ( tokens ) : tokens is [ Token , Token ] => Boolean ( tokens [ 0 ] && tokens [ 1 ] ) ) . filter ( ( [ t0 , t1 ] ) => t0 . address !== t1 . address ) . filter ( ( [ t0 , t1 ] ) => { if ( ! chainId ) return true ; const customBases = CUSTOM_BASES [ chainId ] ; if ( ! customBases ) return true ; const customBasesA = customBases [ t0 . address ] ; const customBasesB = customBases [ t1 . address ] ; if ( ! customBasesA && ! customBasesB ) return true ; if ( customBasesA && ! customBasesA . find ( ( base ) => t1 . equals ( base ) ) ) return false ; if ( customBasesB && ! customBasesB . find ( ( base ) => t0 . equals ( base ) ) ) return false ; return true ; } ) : [ ] , [ tokenA , tokenB , bases , basePairs , chainId ] ) ; const allPairs = usePairs ( allPairCombinations ) ; return useMemo ( ( ) => Object . values ( allPairs . filter ( ( result ) : result is [ PairState . EXISTS , Pair ] => Boolean ( result [ 0 ] === PairState . EXISTS && result [ 1 ] ) ) . reduce < { [ pairAddress ] : Pair ; } > ( ( memo , [ , curr ] ) => { memo [ curr . liquidityToken . address ] = memo [ curr . liquidityToken . address ] ?? curr ; return memo ; } , { } ) ) , [ allPairs ] ) ; } /**
 * Returns the best trade for the exact amount of tokens in to the given token out
 */ export function useTradeExactIn ( currencyAmountIn ? , currencyOut ? ) { const allowedPairs = useAllCommonPairs ( currencyAmountIn ?. currency , currencyOut ) ; return useMemo ( ( ) => { if ( currencyAmountIn && currencyOut && allowedPairs . length > 0 ) { return ( Trade . bestTradeExactIn ( allowedPairs , currencyAmountIn , currencyOut , { maxHops : 3 , maxNumResults : 1 } ) [ 0 ] ?? null ) ; } return null ; } , [ allowedPairs , currencyAmountIn , currencyOut ] ) ; } /**
 * Returns the best trade for the token in to the exact amount of token out
 */ export function useTradeExactOut ( currencyIn ? , currencyAmountOut ? ) { const allowedPairs = useAllCommonPairs ( currencyIn , currencyAmountOut ?. currency ) ; return useMemo ( ( ) => { if ( currencyIn && currencyAmountOut && allowedPairs . length > 0 ) { return ( Trade . bestTradeExactOut ( allowedPairs , currencyIn , currencyAmountOut , { maxHops : 3 , maxNumResults : 1 } ) [ 0 ] ?? null ) ; } return null ; } , [ allowedPairs , currencyIn , currencyAmountOut ] ) ; }