import { UNSUPPORTED_LIST_URLS } from './../../constants/lists' ; import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list' ; import { Tags , TokenList } from '@uniswap/token-lists' ; import { useMemo } from 'react' ; import { useSelector } from 'react-redux' ; import { AppState } from '../index' ; import sortByListPriority from 'utils/listSort' ; import UNSUPPORTED_TOKEN_LIST from '../../constants/tokenLists/uniswap-v2-unsupported.tokenlist.json' ; import { WrappedTokenInfo } from './wrappedTokenInfo' ; type TagDetails = Tags [ keyof Tags ] ; export interface TagInfo extends TagDetails { id : string ; } export type TokenAddressMap = Readonly < { [ chainId ] : Readonly < { [ tokenAddress ] : { token : WrappedTokenInfo ; list : TokenList ; } ; } > ; } > ; type Mutable < T > = { - readonly [ P in keyof T ] : Mutable < T [ P ] > ; } ; const listCache = typeof WeakMap !== 'undefined' ? new WeakMap < TokenList , TokenAddressMap > ( ) : null ; function listToTokenMap ( list ) { const result = listCache ?. get ( list ) ; if ( result ) return result ; const map = list . tokens . reduce < Mutable < TokenAddressMap > > ( ( tokenMap , tokenInfo ) => { const token = new WrappedTokenInfo ( tokenInfo , list ) ; if ( tokenMap [ token . chainId ] ?. [ token . address ] !== undefined ) { console . error ( `Duplicate token! ${ token . address }` ) ; return tokenMap ; } if ( ! tokenMap [ token . chainId ] ) tokenMap [ token . chainId ] = { } ; tokenMap [ token . chainId ] [ token . address ] = { token , list , } ; return tokenMap ; } , { } ) as TokenAddressMap ; listCache ?. set ( list , map ) ; return map ; } const TRANSFORMED_DEFAULT_TOKEN_LIST = listToTokenMap ( DEFAULT_TOKEN_LIST ) ; export function useAllLists ( ) { return useSelector < AppState , AppState [ 'lists' ] [ 'byUrl' ] > ( ( state ) => state . lists . byUrl ) ; } param map1 param map2 export function combineMaps ( map1 , map2 ) { const chainIds = Object . keys ( Object . keys ( map1 ) . concat ( Object . keys ( map2 ) ) . reduce < { [ chainId ] : true ; } > ( ( memo , value ) => { memo [ value ] = true ; return memo ; } , { } ) ) . map ( ( id ) => parseInt ( id ) ) ; return chainIds . reduce < Mutable < TokenAddressMap > > ( ( memo , chainId ) => { memo [ chainId ] = { ... map2 [ chainId ] , ... map1 [ chainId ] , } ; return memo ; } , { } ) as TokenAddressMap ; } function useCombinedTokenMapFromUrls ( urls ) { const lists = useAllLists ( ) ; return useMemo ( ( ) => { if ( ! urls ) return { } ; return ( urls . slice ( ) . sort ( sortByListPriority ) . reduce ( ( allTokens , currentUrl ) => { const current = lists [ currentUrl ] ?. current ; if ( ! current ) return allTokens ; try { return combineMaps ( allTokens , listToTokenMap ( current ) ) ; } catch ( error ) { console . error ( 'Could not show token list due to error' , error ) ; return allTokens ; } } , { } ) ) ; } , [ lists , urls ] ) ; } export function useActiveListUrls ( ) { return useSelector < AppState , AppState [ 'lists' ] [ 'activeListUrls' ] > ( ( state ) => state . lists . activeListUrls ) ?. filter ( ( url ) => ! UNSUPPORTED_LIST_URLS . includes ( url ) ) ; } export function useInactiveListUrls ( ) { const lists = useAllLists ( ) ; const allActiveListUrls = useActiveListUrls ( ) ; return Object . keys ( lists ) . filter ( ( url ) => ! allActiveListUrls ?. includes ( url ) && ! UNSUPPORTED_LIST_URLS . includes ( url ) ) ; } export function useCombinedActiveList ( ) { const activeListUrls = useActiveListUrls ( ) ; const activeTokens = useCombinedTokenMapFromUrls ( activeListUrls ) ; return combineMaps ( activeTokens , TRANSFORMED_DEFAULT_TOKEN_LIST ) ; } export function useCombinedInactiveList ( ) { const allInactiveListUrls = useInactiveListUrls ( ) ; return useCombinedTokenMapFromUrls ( allInactiveListUrls ) ; } export function useUnsupportedTokenList ( ) { const localUnsupportedListMap = listToTokenMap ( UNSUPPORTED_TOKEN_LIST ) ; const loadedUnsupportedListMap = useCombinedTokenMapFromUrls ( UNSUPPORTED_LIST_URLS ) ; return combineMaps ( localUnsupportedListMap , loadedUnsupportedListMap ) ; } export function useIsListActive ( url ) { const activeListUrls = useActiveListUrls ( ) ; return Boolean ( activeListUrls ?. includes ( url ) ) ; }