Commit bbe42b81 authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: display token images on first pageload (#6956)

* fix: always show img for common bases

* fix: include backup img in first render

* fix: initialize and update token safety lookup

* test: update snapshots to include initial logos

* refactor: better code colocation

* test: updating token safety lookup table

* refactor: tokenSafetyLookup

* refactor: tokenLogoLookup

* fix: pass lists state to token safety update

* test: mock initial update
parent e9f469d3
...@@ -80,7 +80,7 @@ exports[`PortfolioLogo renders with L2 icon 1`] = ` ...@@ -80,7 +80,7 @@ exports[`PortfolioLogo renders with L2 icon 1`] = `
> >
<img <img
class="c2 c3" class="c2 c3"
src="blank_token.svg" src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/arbitrum/assets/0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1/logo.png"
/> />
<img <img
class="c2 c3" class="c2 c3"
...@@ -152,11 +152,11 @@ exports[`PortfolioLogo renders without L2 icon 1`] = ` ...@@ -152,11 +152,11 @@ exports[`PortfolioLogo renders without L2 icon 1`] = `
> >
<img <img
class="c2 c3" class="c2 c3"
src="blank_token.svg" src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"
/> />
<img <img
class="c2 c3" class="c2 c3"
src="blank_token.svg" src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
/> />
</div> </div>
</div> </div>
......
...@@ -19,16 +19,11 @@ exports[`LoadedRow.tsx renders a row 1`] = ` ...@@ -19,16 +19,11 @@ exports[`LoadedRow.tsx renders a row 1`] = `
} }
.c8 { .c8 {
--size: 24px;
border-radius: 100px;
color: #0D111C;
background-color: #E8ECFB;
font-size: calc(var(--size) / 3);
font-weight: 500;
height: 24px;
line-height: 24px;
text-align: center;
width: 24px; width: 24px;
height: 24px;
border-radius: 50%;
background: radial-gradient(white 60%,#ffffff00 calc(70% + 1px));
box-shadow: 0 0 1px white;
} }
.c7 { .c7 {
...@@ -351,11 +346,11 @@ exports[`LoadedRow.tsx renders a row 1`] = ` ...@@ -351,11 +346,11 @@ exports[`LoadedRow.tsx renders a row 1`] = `
<div <div
class="c7" class="c7"
> >
<div <img
alt="USDC logo"
class="c8" class="c8"
> src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
USD />
</div>
<div <div
class="c9" class="c9"
/> />
......
...@@ -252,7 +252,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -252,7 +252,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
color: #0D111C; color: #0D111C;
} }
.c12 { .c13 {
width: 100%; width: 100%;
height: 1px; height: 1px;
border-width: 0; border-width: 0;
...@@ -296,7 +296,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -296,7 +296,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
grid-row-gap: 8px; grid-row-gap: 8px;
} }
.c11 { .c12 {
--size: 36px; --size: 36px;
border-radius: 100px; border-radius: 100px;
color: #0D111C; color: #0D111C;
...@@ -309,6 +309,14 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -309,6 +309,14 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
width: 36px; width: 36px;
} }
.c11 {
width: 36px;
height: 36px;
border-radius: 50%;
background: radial-gradient(white 60%,#ffffff00 calc(70% + 1px));
box-shadow: 0 0 1px white;
}
.c10 { .c10 {
position: relative; position: relative;
display: -webkit-box; display: -webkit-box;
...@@ -328,7 +336,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -328,7 +336,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
margin-right: 8px; margin-right: 8px;
} }
.c13 { .c14 {
margin: 16px 2px 24px 2px; margin: 16px 2px 24px 2px;
} }
...@@ -378,11 +386,11 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -378,11 +386,11 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
<div <div
class="c10" class="c10"
> >
<div <img
alt="ETH logo"
class="c11" class="c11"
> src="ethereum-logo.png"
ETH />
</div>
</div> </div>
</div> </div>
<div <div
...@@ -422,7 +430,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -422,7 +430,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
class="c10" class="c10"
> >
<div <div
class="c11" class="c12"
> >
DEF DEF
</div> </div>
...@@ -430,7 +438,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s ...@@ -430,7 +438,7 @@ exports[`SwapModalHeader.tsx renders ETH input token for an ETH input UniswapX s
</div> </div>
</div> </div>
<div <div
class="c12 c13" class="c13 c14"
/> />
</div> </div>
</DocumentFragment> </DocumentFragment>
......
...@@ -4,7 +4,7 @@ import { SearchToken } from 'graphql/data/SearchTokens' ...@@ -4,7 +4,7 @@ import { SearchToken } from 'graphql/data/SearchTokens'
import { ZERO_ADDRESS } from './misc' import { ZERO_ADDRESS } from './misc'
import { NATIVE_CHAIN_ID } from './tokens' import { NATIVE_CHAIN_ID } from './tokens'
import WarningCache, { TOKEN_LIST_TYPES } from './TokenSafetyLookupTable' import tokenSafetyLookup, { TOKEN_LIST_TYPES } from './tokenSafetyLookup'
export const TOKEN_SAFETY_ARTICLE = 'https://support.uniswap.org/hc/en-us/articles/8723118437133' export const TOKEN_SAFETY_ARTICLE = 'https://support.uniswap.org/hc/en-us/articles/8723118437133'
...@@ -84,11 +84,11 @@ export const NotFoundWarning: Warning = { ...@@ -84,11 +84,11 @@ export const NotFoundWarning: Warning = {
canProceed: false, canProceed: false,
} }
export function checkWarning(tokenAddress: string) { export function checkWarning(tokenAddress: string, chainId?: number | null) {
if (tokenAddress === NATIVE_CHAIN_ID || tokenAddress === ZERO_ADDRESS) { if (tokenAddress === NATIVE_CHAIN_ID || tokenAddress === ZERO_ADDRESS) {
return null return null
} }
switch (WarningCache.checkToken(tokenAddress.toLowerCase())) { switch (tokenSafetyLookup.checkToken(tokenAddress.toLowerCase(), chainId)) {
case TOKEN_LIST_TYPES.UNI_DEFAULT: case TOKEN_LIST_TYPES.UNI_DEFAULT:
return null return null
case TOKEN_LIST_TYPES.UNI_EXTENDED: case TOKEN_LIST_TYPES.UNI_EXTENDED:
......
import { TokenInfo } from '@uniswap/token-lists' import { TokenInfo } from '@uniswap/token-lists'
import { ListsState } from 'state/lists/reducer'
import store from '../state' import store from '../state'
import { UNI_EXTENDED_LIST, UNI_LIST, UNSUPPORTED_LIST_URLS } from './lists' import { UNI_EXTENDED_LIST, UNI_LIST, UNSUPPORTED_LIST_URLS } from './lists'
import { COMMON_BASES } from './routing'
import brokenTokenList from './tokenLists/broken.tokenlist.json' import brokenTokenList from './tokenLists/broken.tokenlist.json'
import { NATIVE_CHAIN_ID } from './tokens' import { NATIVE_CHAIN_ID } from './tokens'
...@@ -14,44 +16,47 @@ export enum TOKEN_LIST_TYPES { ...@@ -14,44 +16,47 @@ export enum TOKEN_LIST_TYPES {
} }
class TokenSafetyLookupTable { class TokenSafetyLookupTable {
dict: { [key: string]: TOKEN_LIST_TYPES } | null = null initialized = false
dict: { [key: string]: TOKEN_LIST_TYPES } = {}
createMap() { // TODO(WEB-2488): Index lookups by chainId
const dict: { [key: string]: TOKEN_LIST_TYPES } = {} update(lists: ListsState) {
this.initialized = true
// Initialize extended tokens first // Initialize extended tokens first
store.getState().lists.byUrl[UNI_EXTENDED_LIST].current?.tokens.forEach((token) => { lists.byUrl[UNI_EXTENDED_LIST].current?.tokens.forEach((token) => {
dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.UNI_EXTENDED this.dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.UNI_EXTENDED
}) })
// Initialize default tokens second, so that any tokens on both default and extended will display as default (no warning) // Initialize default tokens second, so that any tokens on both default and extended will display as default (no warning)
store.getState().lists.byUrl[UNI_LIST].current?.tokens.forEach((token) => { lists.byUrl[UNI_LIST].current?.tokens.forEach((token) => {
dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.UNI_DEFAULT this.dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.UNI_DEFAULT
}) })
// TODO: Figure out if this list is still relevant // TODO: Figure out if this list is still relevant
brokenTokenList.tokens.forEach((token) => { brokenTokenList.tokens.forEach((token) => {
dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.BROKEN this.dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.BROKEN
}) })
// Initialize blocked tokens from all urls included // Initialize blocked tokens from all urls included
UNSUPPORTED_LIST_URLS.map((url) => store.getState().lists.byUrl[url].current?.tokens) UNSUPPORTED_LIST_URLS.map((url) => lists.byUrl[url].current?.tokens)
.filter((x): x is TokenInfo[] => !!x) .filter((x): x is TokenInfo[] => !!x)
.flat(1) .flat(1)
.forEach((token) => { .forEach((token) => {
dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.BLOCKED this.dict[token.address.toLowerCase()] = TOKEN_LIST_TYPES.BLOCKED
}) })
return dict
} }
checkToken(address: string) { checkToken(address: string, chainId?: number | null) {
if (!this.dict) { if (!this.initialized) this.update(store.getState().lists)
this.dict = this.createMap()
}
if (address === NATIVE_CHAIN_ID.toLowerCase()) { if (address === NATIVE_CHAIN_ID.toLowerCase()) {
return TOKEN_LIST_TYPES.UNI_DEFAULT return TOKEN_LIST_TYPES.UNI_DEFAULT
} else if (chainId && COMMON_BASES[chainId]?.some((base) => address === base.wrapped.address.toLowerCase())) {
return TOKEN_LIST_TYPES.UNI_DEFAULT
} else {
return this.dict[address] ?? TOKEN_LIST_TYPES.UNKNOWN
} }
return this.dict[address] ?? TOKEN_LIST_TYPES.UNKNOWN
} }
} }
......
import TokenLogoLookupTable from 'constants/TokenLogoLookupTable' import tokenLogoLookup from 'constants/tokenLogoLookup'
import { isCelo, nativeOnChain } from 'constants/tokens' import { isCelo, nativeOnChain } from 'constants/tokens'
import { chainIdToNetworkName, getNativeLogoURI } from 'lib/hooks/useCurrencyLogoURIs' import { chainIdToNetworkName, getNativeLogoURI } from 'lib/hooks/useCurrencyLogoURIs'
import uriToHttp from 'lib/utils/uriToHttp' import uriToHttp from 'lib/utils/uriToHttp'
...@@ -38,7 +38,12 @@ function prioritizeLogoSources(uris: string[]) { ...@@ -38,7 +38,12 @@ function prioritizeLogoSources(uris: string[]) {
return coingeckoUrl ? [...preferredUris, coingeckoUrl] : preferredUris return coingeckoUrl ? [...preferredUris, coingeckoUrl] : preferredUris
} }
function getInitialUrl(address?: string | null, chainId?: number | null, isNative?: boolean) { function getInitialUrl(
address?: string | null,
chainId?: number | null,
isNative?: boolean,
backupImg?: string | null
) {
if (chainId && isNative) return getNativeLogoURI(chainId) if (chainId && isNative) return getNativeLogoURI(chainId)
const networkName = chainId ? chainIdToNetworkName(chainId) : 'ethereum' const networkName = chainId ? chainIdToNetworkName(chainId) : 'ethereum'
...@@ -51,7 +56,7 @@ function getInitialUrl(address?: string | null, chainId?: number | null, isNativ ...@@ -51,7 +56,7 @@ function getInitialUrl(address?: string | null, chainId?: number | null, isNativ
if (checksummedAddress) { if (checksummedAddress) {
return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${checksummedAddress}/logo.png` return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${checksummedAddress}/logo.png`
} else { } else {
return undefined return backupImg ?? undefined
} }
} }
...@@ -61,17 +66,17 @@ export default function useAssetLogoSource( ...@@ -61,17 +66,17 @@ export default function useAssetLogoSource(
isNative?: boolean, isNative?: boolean,
backupImg?: string | null backupImg?: string | null
): [string | undefined, () => void] { ): [string | undefined, () => void] {
const hasWarning = Boolean(address && checkWarning(address)) const showLogo = Boolean((address && checkWarning(address, chainId) === null) || isNative)
const [current, setCurrent] = useState<string | undefined>( const [current, setCurrent] = useState<string | undefined>(
hasWarning ? undefined : getInitialUrl(address, chainId, isNative) showLogo ? getInitialUrl(address, chainId, isNative, backupImg) : undefined
) )
const [fallbackSrcs, setFallbackSrcs] = useState<string[] | undefined>(undefined) const [fallbackSrcs, setFallbackSrcs] = useState<string[] | undefined>(undefined)
useEffect(() => { useEffect(() => {
if (hasWarning) return if (!showLogo) return
setCurrent(getInitialUrl(address, chainId, isNative)) setCurrent(getInitialUrl(address, chainId, isNative))
setFallbackSrcs(undefined) setFallbackSrcs(undefined)
}, [hasWarning, address, chainId, isNative]) }, [address, chainId, isNative, showLogo])
const nextSrc = useCallback(() => { const nextSrc = useCallback(() => {
if (current) { if (current) {
...@@ -79,7 +84,7 @@ export default function useAssetLogoSource( ...@@ -79,7 +84,7 @@ export default function useAssetLogoSource(
} }
// Parses and stores logo sources from tokenlists if assets repo url fails // Parses and stores logo sources from tokenlists if assets repo url fails
if (!fallbackSrcs) { if (!fallbackSrcs) {
const uris = TokenLogoLookupTable.getIcons(address, chainId) ?? [] const uris = tokenLogoLookup.getIcons(address, chainId) ?? []
if (backupImg) uris.push(backupImg) if (backupImg) uris.push(backupImg)
const tokenListIcons = prioritizeLogoSources(parseLogoSources(uris)) const tokenListIcons = prioritizeLogoSources(parseLogoSources(uris))
......
...@@ -698,16 +698,11 @@ exports[`disable nft on landing page does not render nft information and card 1` ...@@ -698,16 +698,11 @@ exports[`disable nft on landing page does not render nft information and card 1`
} }
.c29 { .c29 {
--size: 24px;
border-radius: 100px;
color: #0D111C;
background-color: #E8ECFB;
font-size: calc(var(--size) / 3);
font-weight: 500;
height: 24px;
line-height: 24px;
text-align: center;
width: 24px; width: 24px;
height: 24px;
border-radius: 50%;
background: radial-gradient(white 60%,#ffffff00 calc(70% + 1px));
box-shadow: 0 0 1px white;
} }
.c28 { .c28 {
...@@ -1779,11 +1774,11 @@ exports[`disable nft on landing page does not render nft information and card 1` ...@@ -1779,11 +1774,11 @@ exports[`disable nft on landing page does not render nft information and card 1`
class="c28" class="c28"
style="margin-right: 2px;" style="margin-right: 2px;"
> >
<div <img
alt="ETH logo"
class="c29" class="c29"
> src="ethereum-logo.png"
ETH />
</div>
</div> </div>
<span <span
class="c30 token-symbol-container" class="c30 token-symbol-container"
...@@ -3193,16 +3188,11 @@ exports[`disable nft on landing page renders nft information and card 1`] = ` ...@@ -3193,16 +3188,11 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
} }
.c29 { .c29 {
--size: 24px;
border-radius: 100px;
color: #0D111C;
background-color: #E8ECFB;
font-size: calc(var(--size) / 3);
font-weight: 500;
height: 24px;
line-height: 24px;
text-align: center;
width: 24px; width: 24px;
height: 24px;
border-radius: 50%;
background: radial-gradient(white 60%,#ffffff00 calc(70% + 1px));
box-shadow: 0 0 1px white;
} }
.c28 { .c28 {
...@@ -4286,11 +4276,11 @@ exports[`disable nft on landing page renders nft information and card 1`] = ` ...@@ -4286,11 +4276,11 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
class="c28" class="c28"
style="margin-right: 2px;" style="margin-right: 2px;"
> >
<div <img
alt="ETH logo"
class="c29" class="c29"
> src="ethereum-logo.png"
ETH />
</div>
</div> </div>
<span <span
class="c30 token-symbol-container" class="c30 token-symbol-container"
......
import { createStore, Store } from 'redux' import { createStore, Store } from 'redux'
import { DEFAULT_LIST_OF_LISTS } from '../../constants/lists' import { DEFAULT_LIST_OF_LISTS } from '../../constants/lists'
import tokenSafetyLookup from '../../constants/tokenSafetyLookup'
import { updateVersion } from '../global/actions' import { updateVersion } from '../global/actions'
import { acceptListUpdate, addList, fetchTokenList, removeList } from './actions' import { acceptListUpdate, addList, fetchTokenList, removeList } from './actions'
import reducer, { ListsState } from './reducer' import reducer, { ListsState } from './reducer'
...@@ -79,10 +80,15 @@ describe('list reducer', () => { ...@@ -79,10 +80,15 @@ describe('list reducer', () => {
}) })
describe('fulfilled', () => { describe('fulfilled', () => {
beforeEach(() => {
jest.spyOn(tokenSafetyLookup, 'update').mockReturnValue(undefined)
})
it('saves the list', () => { it('saves the list', () => {
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalled()
expect(store.getState()).toEqual({ expect(store.getState()).toEqual({
byUrl: { byUrl: {
'fake-url': { 'fake-url': {
...@@ -100,9 +106,11 @@ describe('list reducer', () => { ...@@ -100,9 +106,11 @@ describe('list reducer', () => {
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalled()
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalledTimes(1) // should not be called again
expect(store.getState()).toEqual({ expect(store.getState()).toEqual({
byUrl: { byUrl: {
'fake-url': { 'fake-url': {
...@@ -120,10 +128,11 @@ describe('list reducer', () => { ...@@ -120,10 +128,11 @@ describe('list reducer', () => {
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalled()
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: PATCHED_STUB_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: PATCHED_STUB_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalledTimes(1) // should not be called again
expect(store.getState()).toEqual({ expect(store.getState()).toEqual({
byUrl: { byUrl: {
'fake-url': { 'fake-url': {
...@@ -140,10 +149,11 @@ describe('list reducer', () => { ...@@ -140,10 +149,11 @@ describe('list reducer', () => {
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalled()
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: MINOR_UPDATED_STUB_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: MINOR_UPDATED_STUB_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalledTimes(1) // should not be called again
expect(store.getState()).toEqual({ expect(store.getState()).toEqual({
byUrl: { byUrl: {
'fake-url': { 'fake-url': {
...@@ -160,10 +170,11 @@ describe('list reducer', () => { ...@@ -160,10 +170,11 @@ describe('list reducer', () => {
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: STUB_TOKEN_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalled()
store.dispatch( store.dispatch(
fetchTokenList.fulfilled({ tokenList: MAJOR_UPDATED_STUB_LIST, requestId: 'request-id', url: 'fake-url' }) fetchTokenList.fulfilled({ tokenList: MAJOR_UPDATED_STUB_LIST, requestId: 'request-id', url: 'fake-url' })
) )
expect(tokenSafetyLookup.update).toHaveBeenCalledTimes(1) // should not be called again
expect(store.getState()).toEqual({ expect(store.getState()).toEqual({
byUrl: { byUrl: {
'fake-url': { 'fake-url': {
......
import { createReducer } from '@reduxjs/toolkit' import { createReducer } from '@reduxjs/toolkit'
import { getVersionUpgrade, TokenList, VersionUpgrade } from '@uniswap/token-lists' import { getVersionUpgrade, TokenList, VersionUpgrade } from '@uniswap/token-lists'
import tokenSafetyLookup from 'constants/tokenSafetyLookup'
import { DEFAULT_LIST_OF_LISTS } from '../../constants/lists' import { DEFAULT_LIST_OF_LISTS } from '../../constants/lists'
import { updateVersion } from '../global/actions' import { updateVersion } from '../global/actions'
...@@ -76,6 +77,7 @@ export default createReducer(initialState, (builder) => ...@@ -76,6 +77,7 @@ export default createReducer(initialState, (builder) =>
loadingRequestId: null, loadingRequestId: null,
error: null, error: null,
} }
tokenSafetyLookup.update(state)
} }
}) })
.addCase(fetchTokenList.rejected, (state, { payload: { url, requestId, errorMessage } }) => { .addCase(fetchTokenList.rejected, (state, { payload: { url, requestId, errorMessage } }) => {
......
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