Commit 496408b3 authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: token list fetching performance (#3480)

* fix: token list fetching

* fix: simplify naming
parent 78b6f5c7
import { NativeCurrency, Token } from '@uniswap/sdk-core'
import { TokenInfo, TokenList } from '@uniswap/token-lists'
import { atom } from 'jotai'
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
import { atom, useAtom } from 'jotai'
import { useAtomValue } from 'jotai/utils'
import useActiveWeb3React from 'lib/hooks/useActiveWeb3React'
import resolveENSContentHash from 'lib/utils/resolveENSContentHash'
import { useCallback, useEffect, useMemo, useState } from 'react'
......@@ -14,31 +14,35 @@ import { validateTokens } from './validateTokenList'
export const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org'
const chainTokenMapAtom = atom<ChainTokenMap | undefined>(undefined)
const chainTokenMapAtom = atom<ChainTokenMap | null>(null)
export function useIsTokenListLoaded() {
return Boolean(useAtomValue(chainTokenMapAtom))
}
export function useSyncTokenList(list: string | TokenInfo[] = DEFAULT_TOKEN_LIST): void {
const { chainId, library } = useActiveWeb3React()
const setChainTokenMap = useUpdateAtom(chainTokenMapAtom)
// Error boundaries will not catch (non-rendering) async errors, but it should still be shown
const [error, setError] = useState<Error>()
if (error) throw error
const [chainTokenMap, setChainTokenMap] = useAtom(chainTokenMapAtom)
useEffect(() => setChainTokenMap(null), [list, setChainTokenMap])
const { chainId, library } = useActiveWeb3React()
const resolver = useCallback(
(ensName: string) => {
if (library && chainId === 1) {
// TODO(zzmp): Use network resolver when wallet is not on chainId === 1.
return resolveENSContentHash(ensName, library)
}
throw new Error('Could not construct mainnet ENS resolver')
},
[chainId, library]
)
useEffect(() => {
// If the list was already loaded, don't reload it.
if (chainTokenMap) return
let stale = false
activateList(list)
return () => {
......@@ -53,19 +57,20 @@ export function useSyncTokenList(list: string | TokenInfo[] = DEFAULT_TOKEN_LIST
} else {
tokens = await validateTokens(list)
}
const tokenMap = tokensToChainTokenMap(tokens) // also caches the fetched tokens, so it is invoked even if stale
// tokensToChainTokenMap also caches the fetched tokens, so it must be invoked even if stale.
const map = tokensToChainTokenMap(tokens)
if (!stale) {
setChainTokenMap(tokenMap)
setChainTokenMap(map)
setError(undefined)
}
} catch (e: unknown) {
if (!stale) {
setChainTokenMap(undefined)
// Do not update the token map, in case the map was already resolved without error on mainnet.
setError(e as Error)
}
}
}
}, [list, resolver, setChainTokenMap])
}, [chainTokenMap, list, resolver, setChainTokenMap])
}
export default function useTokenList(): WrappedTokenInfo[] {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment