Commit 3f6dc180 authored by cartcrom's avatar cartcrom Committed by GitHub

feat: update token icon sourcing (#5208)

* initial setup
* working version
* optimized image quality
* refactoring file structure
* updating backup logos
* cleaning up code
* refactored file structure
* fixing state update issue
* updated test
* fixed currency logo bug
* updated image background color
* finished pr comments
* fixed additional PR comments
parent 7ce58b55
...@@ -16,4 +16,4 @@ ...@@ -16,4 +16,4 @@
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
} }
} }
\ No newline at end of file
...@@ -5,7 +5,7 @@ import styled, { css } from 'styled-components/macro' ...@@ -5,7 +5,7 @@ import styled, { css } from 'styled-components/macro'
import { nativeOnChain } from '../../constants/tokens' import { nativeOnChain } from '../../constants/tokens'
import { useCurrency } from '../../hooks/Tokens' import { useCurrency } from '../../hooks/Tokens'
import CurrencyLogo from '../CurrencyLogo' import CurrencyLogo from '../Logo/CurrencyLogo'
const CurrencyWrap = styled.div` const CurrencyWrap = styled.div`
position: relative; position: relative;
......
...@@ -6,6 +6,7 @@ import { Pair } from '@uniswap/v2-sdk' ...@@ -6,6 +6,7 @@ import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled' import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { isSupportedChain } from 'constants/chains' import { isSupportedChain } from 'constants/chains'
import { darken } from 'polished' import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react' import { ReactNode, useCallback, useState } from 'react'
...@@ -18,7 +19,6 @@ import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg' ...@@ -18,7 +19,6 @@ import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useCurrencyBalance } from '../../state/connection/hooks' import { useCurrencyBalance } from '../../state/connection/hooks'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import { ButtonGray } from '../Button' import { ButtonGray } from '../Button'
import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo' import DoubleCurrencyLogo from '../DoubleLogo'
import { Input as NumericalInput } from '../NumericalInput' import { Input as NumericalInput } from '../NumericalInput'
import { RowBetween, RowFixed } from '../Row' import { RowBetween, RowFixed } from '../Row'
......
...@@ -18,8 +18,8 @@ import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg' ...@@ -18,8 +18,8 @@ import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useCurrencyBalance } from '../../state/connection/hooks' import { useCurrencyBalance } from '../../state/connection/hooks'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import { ButtonGray } from '../Button' import { ButtonGray } from '../Button'
import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo' import DoubleCurrencyLogo from '../DoubleLogo'
import CurrencyLogo from '../Logo/CurrencyLogo'
import { Input as NumericalInput } from '../NumericalInput' import { Input as NumericalInput } from '../NumericalInput'
import { RowBetween, RowFixed } from '../Row' import { RowBetween, RowFixed } from '../Row'
import CurrencySearchModal from '../SearchModal/CurrencySearchModal' import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
......
import { Currency } from '@uniswap/sdk-core'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import React, { useMemo } from 'react'
import styled from 'styled-components/macro'
import Logo from '../Logo'
const StyledLogo = styled(Logo)<{ size: string }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
background: radial-gradient(white 50%, #ffffff00 calc(75% + 1px), #ffffff00 100%);
border-radius: 50%;
-mox-box-shadow: 0 0 1px black;
-webkit-box-shadow: 0 0 1px black;
box-shadow: 0 0 1px black;
border: 0px solid rgba(255, 255, 255, 0);
`
const StyledNativeLogo = styled(StyledLogo)`
-mox-box-shadow: 0 0 1px white;
-webkit-box-shadow: 0 0 1px white;
box-shadow: 0 0 1px white;
`
export default function CurrencyLogo({
currency,
symbol,
size = '24px',
style,
src,
...rest
}: {
currency?: Currency | null
symbol?: string | null
size?: string
style?: React.CSSProperties
src?: string | null
}) {
const logoURIs = useCurrencyLogoURIs(currency)
const srcs = useMemo(() => (src ? [src, ...logoURIs] : logoURIs), [src, logoURIs])
const props = {
alt: `${currency?.symbol ?? 'token'} logo`,
size,
srcs,
symbol: symbol ?? currency?.symbol,
style,
...rest,
}
return currency?.isNative ? <StyledNativeLogo {...props} /> : <StyledLogo {...props} />
}
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import CurrencyLogo from '../CurrencyLogo' import CurrencyLogo from '../Logo/CurrencyLogo'
const Wrapper = styled.div<{ margin: boolean; sizeraw: number }>` const Wrapper = styled.div<{ margin: boolean; sizeraw: number }>`
position: relative; position: relative;
......
import { SupportedChainId } from 'constants/chains'
import useTokenLogoSource from 'hooks/useAssetLogoSource'
import React from 'react'
import styled from 'styled-components/macro'
export const MissingImageLogo = styled.div<{ size?: string }>`
--size: ${({ size }) => size};
border-radius: 100px;
color: ${({ theme }) => theme.textPrimary};
background-color: ${({ theme }) => theme.backgroundInteractive};
font-size: calc(var(--size) / 3);
font-weight: 500;
height: ${({ size }) => size ?? '24px'};
line-height: ${({ size }) => size ?? '24px'};
text-align: center;
width: ${({ size }) => size ?? '24px'};
`
const LogoImage = styled.img<{ size: string }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
background: radial-gradient(white 60%, #ffffff00 calc(70% + 1px));
border-radius: 50%;
box-shadow: 0 0 1px white;
`
export type AssetLogoBaseProps = {
symbol?: string | null
backupImg?: string | null
size?: string
style?: React.CSSProperties
}
type AssetLogoProps = AssetLogoBaseProps & { isNative?: boolean; address?: string | null; chainId?: number }
// TODO(cartcrom): add prop to optionally render an L2Icon w/ the logo
/**
* Renders an image by prioritizing a list of sources, and then eventually a fallback triangle alert
*/
export default function AssetLogo({
isNative,
address,
chainId = SupportedChainId.MAINNET,
symbol,
backupImg,
size = '24px',
style,
...rest
}: AssetLogoProps) {
const imageProps = {
alt: `${symbol ?? 'token'} logo`,
size,
style,
...rest,
}
const [src, nextSrc] = useTokenLogoSource(address, chainId, isNative, backupImg)
if (src) {
return <LogoImage {...imageProps} src={src} onError={nextSrc} />
} else {
return (
<MissingImageLogo size={size}>
{/* use only first 3 characters of Symbol for design reasons */}
{symbol?.toUpperCase().replace('$', '').replace(/\s+/g, '').slice(0, 3)}
</MissingImageLogo>
)
}
}
import { Currency } from '@uniswap/sdk-core'
import { TokenInfo } from '@uniswap/token-lists'
import AssetLogo, { AssetLogoBaseProps } from './AssetLogo'
export default function CurrencyLogo(
props: AssetLogoBaseProps & {
currency?: Currency | null
}
) {
return (
<AssetLogo
isNative={props.currency?.isNative}
chainId={props.currency?.chainId}
address={props.currency?.wrapped.address}
symbol={props.symbol ?? props.currency?.symbol}
backupImg={(props.currency as TokenInfo)?.logoURI}
{...props}
/>
)
}
import { NATIVE_CHAIN_ID } from 'constants/tokens'
import { TokenQueryData } from 'graphql/data/Token'
import { TopToken } from 'graphql/data/TopTokens'
import { CHAIN_NAME_TO_CHAIN_ID } from 'graphql/data/util'
import AssetLogo, { AssetLogoBaseProps } from './AssetLogo'
export default function QueryTokenLogo(
props: AssetLogoBaseProps & {
token?: TopToken | TokenQueryData
}
) {
const chainId = props.token?.chain ? CHAIN_NAME_TO_CHAIN_ID[props.token?.chain] : undefined
return (
<AssetLogo
isNative={props.token?.address === NATIVE_CHAIN_ID}
chainId={chainId}
address={props.token?.address}
symbol={props.token?.symbol}
backupImg={props.token?.project?.logoUrl}
{...props}
/>
)
}
import { useState } from 'react'
import { ImageProps } from 'rebass'
import styled from 'styled-components/macro'
const BAD_SRCS: { [tokenAddress: string]: true } = {}
interface LogoProps extends Pick<ImageProps, 'style' | 'alt' | 'className'> {
srcs: string[]
symbol?: string
size?: string
}
const MissingImageLogo = styled.div<{ size?: string }>`
--size: ${({ size }) => size};
border-radius: 100px;
color: ${({ theme }) => theme.textPrimary};
background-color: ${({ theme }) => theme.backgroundInteractive};
font-size: calc(var(--size) / 3);
font-weight: 500;
height: ${({ size }) => size ?? '24px'};
line-height: ${({ size }) => size ?? '24px'};
text-align: center;
width: ${({ size }) => size ?? '24px'};
`
/**
* Renders an image by sequentially trying a list of URIs, and then eventually a fallback triangle alert
*/
export default function Logo({ srcs, alt, style, size, symbol, ...rest }: LogoProps) {
const [, refresh] = useState<number>(0)
const src: string | undefined = srcs.find((src) => !BAD_SRCS[src])
if (src) {
return (
<img
{...rest}
alt={alt}
src={src}
style={style}
onError={() => {
if (src) BAD_SRCS[src] = true
refresh((i) => i + 1)
}}
/>
)
}
return (
<MissingImageLogo size={size}>
{/* use only first 3 characters of Symbol for design reasons */}
{symbol?.toUpperCase().replace('$', '').replace(/\s+/g, '').slice(0, 3)}
</MissingImageLogo>
)
}
...@@ -2,12 +2,13 @@ import { sendAnalyticsEvent } from '@uniswap/analytics' ...@@ -2,12 +2,13 @@ import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events' import { EventName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import clsx from 'clsx' import clsx from 'clsx'
import AssetLogo from 'components/Logo/AssetLogo'
import { L2NetworkLogo, LogoContainer } from 'components/Tokens/TokenTable/TokenRow' import { L2NetworkLogo, LogoContainer } from 'components/Tokens/TokenTable/TokenRow'
import TokenSafetyIcon from 'components/TokenSafety/TokenSafetyIcon' import TokenSafetyIcon from 'components/TokenSafety/TokenSafetyIcon'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { NATIVE_CHAIN_ID } from 'constants/tokens'
import { checkWarning } from 'constants/tokenSafety' import { checkWarning } from 'constants/tokenSafety'
import { getTokenDetailsURL } from 'graphql/data/util' import { getTokenDetailsURL } from 'graphql/data/util'
import uriToHttp from 'lib/utils/uriToHttp'
import { Box } from 'nft/components/Box' import { Box } from 'nft/components/Box'
import { Column, Row } from 'nft/components/Flex' import { Column, Row } from 'nft/components/Flex'
import { VerifiedIcon } from 'nft/components/icons' import { VerifiedIcon } from 'nft/components/icons'
...@@ -18,10 +19,15 @@ import { ethNumberStandardFormatter } from 'nft/utils/currency' ...@@ -18,10 +19,15 @@ import { ethNumberStandardFormatter } from 'nft/utils/currency'
import { putCommas } from 'nft/utils/putCommas' import { putCommas } from 'nft/utils/putCommas'
import { useCallback, useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import styled from 'styled-components/macro'
import { formatDollar } from 'utils/formatNumbers' import { formatDollar } from 'utils/formatNumbers'
import * as styles from './SearchBar.css' import * as styles from './SearchBar.css'
const StyledLogoContainer = styled(LogoContainer)`
margin-right: 8px;
`
interface CollectionRowProps { interface CollectionRowProps {
collection: GenieCollection collection: GenieCollection
isHovered: boolean isHovered: boolean
...@@ -127,8 +133,6 @@ interface TokenRowProps { ...@@ -127,8 +133,6 @@ interface TokenRowProps {
} }
export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index, eventProperties }: TokenRowProps) => { export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index, eventProperties }: TokenRowProps) => {
const [brokenImage, setBrokenImage] = useState(false)
const [loaded, setLoaded] = useState(false)
const addToSearchHistory = useSearchHistory( const addToSearchHistory = useSearchHistory(
(state: { addItem: (item: FungibleToken | GenieCollection) => void }) => state.addItem (state: { addItem: (item: FungibleToken | GenieCollection) => void }) => state.addItem
) )
...@@ -167,21 +171,17 @@ export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index, ...@@ -167,21 +171,17 @@ export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index,
style={{ background: isHovered ? vars.color.lightGrayOverlay : 'none' }} style={{ background: isHovered ? vars.color.lightGrayOverlay : 'none' }}
> >
<Row style={{ width: '65%' }}> <Row style={{ width: '65%' }}>
{!brokenImage && token.logoURI ? ( <StyledLogoContainer>
<LogoContainer> <AssetLogo
<Box isNative={token.address === NATIVE_CHAIN_ID}
as="img" address={token.address}
src={token.logoURI.includes('ipfs://') ? uriToHttp(token.logoURI)[0] : token.logoURI} chainId={token.chainId}
alt={token.name} symbol={token.symbol}
className={clsx(loaded ? styles.suggestionImage : styles.imageHolder)} size="36px"
onError={() => setBrokenImage(true)} backupImg={token.logoURI}
onLoad={() => setLoaded(true)} />
/> <L2NetworkLogo networkUrl={L2Icon} size="16px" />
<L2NetworkLogo networkUrl={L2Icon} size="16px" /> </StyledLogoContainer>
</LogoContainer>
) : (
<Box className={styles.imageHolder} />
)}
<Column className={styles.suggestionPrimaryContainer}> <Column className={styles.suggestionPrimaryContainer}>
<Row gap="4" width="full"> <Row gap="4" width="full">
<Box className={styles.primaryText}>{token.name}</Box> <Box className={styles.primaryText}>{token.name}</Box>
......
...@@ -19,9 +19,9 @@ import { unwrappedToken } from '../../utils/unwrappedToken' ...@@ -19,9 +19,9 @@ import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button' import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button'
import { LightCard } from '../Card' import { LightCard } from '../Card'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo' import DoubleCurrencyLogo from '../DoubleLogo'
import { CardNoise } from '../earn/styled' import { CardNoise } from '../earn/styled'
import CurrencyLogo from '../Logo/CurrencyLogo'
import { AutoRow, RowBetween, RowFixed } from '../Row' import { AutoRow, RowBetween, RowFixed } from '../Row'
import { Dots } from '../swap/styleds' import { Dots } from '../swap/styleds'
import { FixedHeightRow } from '.' import { FixedHeightRow } from '.'
......
...@@ -20,9 +20,9 @@ import { unwrappedToken } from '../../utils/unwrappedToken' ...@@ -20,9 +20,9 @@ import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button' import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button'
import { GrayCard, LightCard } from '../Card' import { GrayCard, LightCard } from '../Card'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo' import DoubleCurrencyLogo from '../DoubleLogo'
import { CardNoise } from '../earn/styled' import { CardNoise } from '../earn/styled'
import CurrencyLogo from '../Logo/CurrencyLogo'
import { AutoRow, RowBetween, RowFixed } from '../Row' import { AutoRow, RowBetween, RowFixed } from '../Row'
import { Dots } from '../swap/styleds' import { Dots } from '../swap/styleds'
......
...@@ -4,9 +4,9 @@ import { Position } from '@uniswap/v3-sdk' ...@@ -4,9 +4,9 @@ import { Position } from '@uniswap/v3-sdk'
import RangeBadge from 'components/Badge/RangeBadge' import RangeBadge from 'components/Badge/RangeBadge'
import { LightCard } from 'components/Card' import { LightCard } from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import { Break } from 'components/earn/styled' import { Break } from 'components/earn/styled'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import RateToggle from 'components/RateToggle' import RateToggle from 'components/RateToggle'
import { RowBetween, RowFixed } from 'components/Row' import { RowBetween, RowFixed } from 'components/Row'
import JSBI from 'jsbi' import JSBI from 'jsbi'
......
...@@ -28,7 +28,7 @@ const multiRoute: RoutingDiagramEntry[] = [ ...@@ -28,7 +28,7 @@ const multiRoute: RoutingDiagramEntry[] = [
] ]
jest.mock( jest.mock(
'components/CurrencyLogo', 'components/Logo/CurrencyLogo',
() => () =>
({ currency }: { currency: Currency }) => ({ currency }: { currency: Currency }) =>
`CurrencyLogo currency=${currency.symbol}` `CurrencyLogo currency=${currency.symbol}`
......
...@@ -3,8 +3,8 @@ import { Protocol } from '@uniswap/router-sdk' ...@@ -3,8 +3,8 @@ import { Protocol } from '@uniswap/router-sdk'
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge' import Badge from 'components/Badge'
import CurrencyLogo from 'components/CurrencyLogo'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import Row, { AutoRow } from 'components/Row' import Row, { AutoRow } from 'components/Row'
import { RoutingDiagramEntry } from 'components/swap/SwapRoute' import { RoutingDiagramEntry } from 'components/swap/SwapRoute'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList' import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
......
...@@ -2,7 +2,7 @@ import { TraceEvent } from '@uniswap/analytics' ...@@ -2,7 +2,7 @@ import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events' import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { AutoRow } from 'components/Row' import { AutoRow } from 'components/Row'
import { COMMON_BASES } from 'constants/routing' import { COMMON_BASES } from 'constants/routing'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList' import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
......
...@@ -16,7 +16,7 @@ const mockCurrencyAmt = { ...@@ -16,7 +16,7 @@ const mockCurrencyAmt = {
} }
jest.mock( jest.mock(
'components/CurrencyLogo', 'components/Logo/CurrencyLogo',
() => () =>
({ currency }: { currency: Currency }) => ({ currency }: { currency: Currency }) =>
`CurrencyLogo currency=${currency.symbol}` `CurrencyLogo currency=${currency.symbol}`
......
...@@ -15,8 +15,8 @@ import { useCurrencyBalance } from '../../../state/connection/hooks' ...@@ -15,8 +15,8 @@ import { useCurrencyBalance } from '../../../state/connection/hooks'
import { WrappedTokenInfo } from '../../../state/lists/wrappedTokenInfo' import { WrappedTokenInfo } from '../../../state/lists/wrappedTokenInfo'
import { ThemedText } from '../../../theme' import { ThemedText } from '../../../theme'
import Column, { AutoColumn } from '../../Column' import Column, { AutoColumn } from '../../Column'
import CurrencyLogo from '../../CurrencyLogo'
import Loader from '../../Loader' import Loader from '../../Loader'
import CurrencyLogo from '../../Logo/CurrencyLogo'
import Row, { RowFixed } from '../../Row' import Row, { RowFixed } from '../../Row'
import { MouseoverTooltip } from '../../Tooltip' import { MouseoverTooltip } from '../../Tooltip'
import { LoadingRows, MenuItem } from '../styleds' import { LoadingRows, MenuItem } from '../styleds'
......
...@@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro' ...@@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro'
import { Token } from '@uniswap/sdk-core' import { Token } from '@uniswap/sdk-core'
import { ButtonPrimary } from 'components/Button' import { ButtonPrimary } from 'components/Button'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import TokenSafetyLabel from 'components/TokenSafety/TokenSafetyLabel' import TokenSafetyLabel from 'components/TokenSafety/TokenSafetyLabel'
import { checkWarning, getWarningCopy, TOKEN_SAFETY_ARTICLE, Warning } from 'constants/tokenSafety' import { checkWarning, getWarningCopy, TOKEN_SAFETY_ARTICLE, Warning } from 'constants/tokenSafety'
import { useToken } from 'hooks/Tokens' import { useToken } from 'hooks/Tokens'
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { useStablecoinValue } from 'hooks/useStablecoinPrice' import { useStablecoinValue } from 'hooks/useStablecoinPrice'
import useCurrencyBalance from 'lib/hooks/useCurrencyBalance' import useCurrencyBalance from 'lib/hooks/useCurrencyBalance'
import { formatToDecimal } from 'lib/utils/analytics' import { formatToDecimal } from 'lib/utils/analytics'
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import { NATIVE_CHAIN_ID } from 'constants/tokens' import { NATIVE_CHAIN_ID } from 'constants/tokens'
import { TokenQueryData } from 'graphql/data/Token' import { chainIdToBackendName } from 'graphql/data/util'
import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useOnClickOutside } from 'hooks/useOnClickOutside'
import { useRef } from 'react' import { useRef } from 'react'
import { Twitter } from 'react-feather' import { Twitter } from 'react-feather'
...@@ -63,12 +64,7 @@ const ShareAction = styled.div` ...@@ -63,12 +64,7 @@ const ShareAction = styled.div`
} }
` `
interface TokenInfo { export default function ShareButton({ currency }: { currency: Currency }) {
token: NonNullable<TokenQueryData>
isNative: boolean
}
export default function ShareButton(tokenInfo: TokenInfo) {
const theme = useTheme() const theme = useTheme()
const node = useRef<HTMLDivElement | null>(null) const node = useRef<HTMLDivElement | null>(null)
const open = useModalIsOpen(ApplicationModal.SHARE) const open = useModalIsOpen(ApplicationModal.SHARE)
...@@ -76,12 +72,16 @@ export default function ShareButton(tokenInfo: TokenInfo) { ...@@ -76,12 +72,16 @@ export default function ShareButton(tokenInfo: TokenInfo) {
useOnClickOutside(node, open ? toggleShare : undefined) useOnClickOutside(node, open ? toggleShare : undefined)
const positionX = (window.screen.width - TWITTER_WIDTH) / 2 const positionX = (window.screen.width - TWITTER_WIDTH) / 2
const positionY = (window.screen.height - TWITTER_HEIGHT) / 2 const positionY = (window.screen.height - TWITTER_HEIGHT) / 2
const tokenAddress = tokenInfo.isNative ? NATIVE_CHAIN_ID : tokenInfo.token.address const address = currency.isNative ? NATIVE_CHAIN_ID : currency.wrapped.address
const shareTweet = () => { const shareTweet = () => {
toggleShare() toggleShare()
window.open( window.open(
`https://twitter.com/intent/tweet?text=Check%20out%20${tokenInfo.token.name}%20(${tokenInfo.token.symbol})%20https://app.uniswap.org/%23/tokens/${tokenInfo.token.chain}/${tokenAddress}%20via%20@uniswap`, `https://twitter.com/intent/tweet?text=Check%20out%20${currency.name}%20(${
currency.symbol
})%20https://app.uniswap.org/%23/tokens/${chainIdToBackendName(
currency.chainId
).toLowerCase()}/${address}%20via%20@uniswap`,
'newwindow', 'newwindow',
`left=${positionX}, top=${positionY}, width=${TWITTER_WIDTH}, height=${TWITTER_HEIGHT}` `left=${positionX}, top=${positionY}, width=${TWITTER_WIDTH}, height=${TWITTER_HEIGHT}`
) )
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics' import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events' import { PageName } from '@uniswap/analytics-events'
import { Currency, NativeCurrency, Token } from '@uniswap/sdk-core' import { Currency, Token } from '@uniswap/sdk-core'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { AboutSection } from 'components/Tokens/TokenDetails/About' import { AboutSection } from 'components/Tokens/TokenDetails/About'
import AddressSection from 'components/Tokens/TokenDetails/AddressSection' import AddressSection from 'components/Tokens/TokenDetails/AddressSection'
import BalanceSummary from 'components/Tokens/TokenDetails/BalanceSummary' import BalanceSummary from 'components/Tokens/TokenDetails/BalanceSummary'
...@@ -24,17 +24,14 @@ import TokenSafetyMessage from 'components/TokenSafety/TokenSafetyMessage' ...@@ -24,17 +24,14 @@ import TokenSafetyMessage from 'components/TokenSafety/TokenSafetyMessage'
import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal' import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal'
import Widget from 'components/Widget' import Widget from 'components/Widget'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import { DEFAULT_ERC20_DECIMALS, NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens' import { DEFAULT_ERC20_DECIMALS, NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens'
import { checkWarning } from 'constants/tokenSafety' import { checkWarning } from 'constants/tokenSafety'
import { TokenPriceQuery } from 'graphql/data/__generated__/TokenPriceQuery.graphql' import { TokenPriceQuery } from 'graphql/data/__generated__/TokenPriceQuery.graphql'
import { Chain, TokenQuery } from 'graphql/data/Token' import { Chain, TokenQuery } from 'graphql/data/Token'
import { QueryToken, tokenQuery, TokenQueryData } from 'graphql/data/Token' import { QueryToken, tokenQuery } from 'graphql/data/Token'
import { TopToken } from 'graphql/data/TopTokens'
import { CHAIN_NAME_TO_CHAIN_ID } from 'graphql/data/util' import { CHAIN_NAME_TO_CHAIN_ID } from 'graphql/data/util'
import { useIsUserAddedTokenOnChain } from 'hooks/Tokens' import { useIsUserAddedTokenOnChain } from 'hooks/Tokens'
import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch' import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import { useCallback, useMemo, useState, useTransition } from 'react' import { useCallback, useMemo, useState, useTransition } from 'react'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import { PreloadedQuery, usePreloadedQuery } from 'react-relay' import { PreloadedQuery, usePreloadedQuery } from 'react-relay'
...@@ -53,15 +50,6 @@ const TokenActions = styled.div` ...@@ -53,15 +50,6 @@ const TokenActions = styled.div`
color: ${({ theme }) => theme.textSecondary}; color: ${({ theme }) => theme.textSecondary};
` `
export function useTokenLogoURI(token?: TokenQueryData | TopToken, nativeCurrency?: Token | NativeCurrency) {
const chainId = token ? CHAIN_NAME_TO_CHAIN_ID[token.chain] : SupportedChainId.MAINNET
return [
...useCurrencyLogoURIs(nativeCurrency),
...useCurrencyLogoURIs({ ...token, chainId }),
token?.project?.logoUrl,
][0]
}
type TokenDetailsProps = { type TokenDetailsProps = {
tokenAddress: string | undefined tokenAddress: string | undefined
chain: Chain chain: Chain
...@@ -85,12 +73,12 @@ export default function TokenDetails({ ...@@ -85,12 +73,12 @@ export default function TokenDetails({
const isNative = tokenAddress === NATIVE_CHAIN_ID const isNative = tokenAddress === NATIVE_CHAIN_ID
const tokenQueryData = usePreloadedQuery(tokenQuery, tokenQueryReference).tokens?.[0] const tokenQueryData = usePreloadedQuery(tokenQuery, tokenQueryReference).tokens?.[0]
const token = useMemo(() => { const token = useMemo(() => {
if (isNative) return nativeCurrency if (isNative) return nativeCurrency
if (tokenQueryData) return new QueryToken(tokenQueryData) if (tokenQueryData) return new QueryToken(tokenQueryData)
return new Token(pageChainId, tokenAddress, DEFAULT_ERC20_DECIMALS) return new Token(pageChainId, tokenAddress, DEFAULT_ERC20_DECIMALS)
}, [isNative, nativeCurrency, pageChainId, tokenAddress, tokenQueryData]) }, [isNative, nativeCurrency, pageChainId, tokenAddress, tokenQueryData])
const tokenWarning = tokenAddress ? checkWarning(tokenAddress) : null const tokenWarning = tokenAddress ? checkWarning(tokenAddress) : null
const isBlockedToken = tokenWarning?.canProceed === false const isBlockedToken = tokenWarning?.canProceed === false
...@@ -133,7 +121,6 @@ export default function TokenDetails({ ...@@ -133,7 +121,6 @@ export default function TokenDetails({
[continueSwap, setContinueSwap] [continueSwap, setContinueSwap]
) )
const logoSrc = useTokenLogoURI(tokenQueryData, isNative ? nativeCurrency : undefined)
const L2Icon = getChainInfo(pageChainId)?.circleLogoUrl const L2Icon = getChainInfo(pageChainId)?.circleLogoUrl
return ( return (
...@@ -147,12 +134,7 @@ export default function TokenDetails({ ...@@ -147,12 +134,7 @@ export default function TokenDetails({
<TokenInfoContainer> <TokenInfoContainer>
<TokenNameCell> <TokenNameCell>
<LogoContainer> <LogoContainer>
<CurrencyLogo <CurrencyLogo currency={token} size="32px" />
src={logoSrc}
size="32px"
symbol={isNative ? nativeCurrency?.symbol : token?.symbol}
currency={isNative ? nativeCurrency : token}
/>
<L2NetworkLogo networkUrl={L2Icon} size="16px" /> <L2NetworkLogo networkUrl={L2Icon} size="16px" />
</LogoContainer> </LogoContainer>
{token?.name ?? <Trans>Name not found</Trans>} {token?.name ?? <Trans>Name not found</Trans>}
...@@ -160,7 +142,7 @@ export default function TokenDetails({ ...@@ -160,7 +142,7 @@ export default function TokenDetails({
</TokenNameCell> </TokenNameCell>
<TokenActions> <TokenActions>
{tokenQueryData?.name && tokenQueryData.symbol && tokenQueryData.address && ( {tokenQueryData?.name && tokenQueryData.symbol && tokenQueryData.address && (
<ShareButton token={tokenQueryData} isNative={!!nativeCurrency} /> <ShareButton currency={token} />
)} )}
</TokenActions> </TokenActions>
</TokenInfoContainer> </TokenInfoContainer>
......
...@@ -3,7 +3,7 @@ import { sendAnalyticsEvent } from '@uniswap/analytics' ...@@ -3,7 +3,7 @@ import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events' import { EventName } from '@uniswap/analytics-events'
import { ParentSize } from '@visx/responsive' import { ParentSize } from '@visx/responsive'
import SparklineChart from 'components/Charts/SparklineChart' import SparklineChart from 'components/Charts/SparklineChart'
import CurrencyLogo from 'components/CurrencyLogo' import QueryTokenLogo from 'components/Logo/QueryTokenLogo'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { SparklineMap, TopToken } from 'graphql/data/TopTokens' import { SparklineMap, TopToken } from 'graphql/data/TopTokens'
import { CHAIN_NAME_TO_CHAIN_ID, getTokenDetailsURL } from 'graphql/data/util' import { CHAIN_NAME_TO_CHAIN_ID, getTokenDetailsURL } from 'graphql/data/util'
...@@ -31,7 +31,6 @@ import { ...@@ -31,7 +31,6 @@ import {
TokenSortMethod, TokenSortMethod,
useSetSortMethod, useSetSortMethod,
} from '../state' } from '../state'
import { useTokenLogoURI } from '../TokenDetails'
import InfoTip from '../TokenDetails/InfoTip' import InfoTip from '../TokenDetails/InfoTip'
import { formatDelta, getDeltaArrow } from '../TokenDetails/PriceChart' import { formatDelta, getDeltaArrow } from '../TokenDetails/PriceChart'
...@@ -438,7 +437,8 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT ...@@ -438,7 +437,8 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
const lowercaseChainName = useParams<{ chainName?: string }>().chainName?.toUpperCase() ?? 'ethereum' const lowercaseChainName = useParams<{ chainName?: string }>().chainName?.toUpperCase() ?? 'ethereum'
const filterNetwork = lowercaseChainName.toUpperCase() const filterNetwork = lowercaseChainName.toUpperCase()
const L2Icon = getChainInfo(CHAIN_NAME_TO_CHAIN_ID[filterNetwork])?.circleLogoUrl const chainId = CHAIN_NAME_TO_CHAIN_ID[filterNetwork]
const L2Icon = getChainInfo(chainId)?.circleLogoUrl
const timePeriod = useAtomValue(filterTimeAtom) const timePeriod = useAtomValue(filterTimeAtom)
const delta = token.market?.pricePercentChange?.value const delta = token.market?.pricePercentChange?.value
const arrow = getDeltaArrow(delta) const arrow = getDeltaArrow(delta)
...@@ -446,7 +446,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT ...@@ -446,7 +446,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
const rank = sortAscending ? tokenListLength - tokenListIndex : tokenListIndex + 1 const rank = sortAscending ? tokenListLength - tokenListIndex : tokenListIndex + 1
const exploreTokenSelectedEventProperties = { const exploreTokenSelectedEventProperties = {
chain_id: filterNetwork, chain_id: chainId,
token_address: tokenAddress, token_address: tokenAddress,
token_symbol: tokenSymbol, token_symbol: tokenSymbol,
token_list_index: tokenListIndex, token_list_index: tokenListIndex,
...@@ -469,7 +469,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT ...@@ -469,7 +469,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
tokenInfo={ tokenInfo={
<ClickableName> <ClickableName>
<LogoContainer> <LogoContainer>
<CurrencyLogo src={useTokenLogoURI(token)} symbol={tokenSymbol} /> <QueryTokenLogo token={token} />
<L2NetworkLogo networkUrl={L2Icon} /> <L2NetworkLogo networkUrl={L2Icon} />
</LogoContainer> </LogoContainer>
<TokenInfoCell> <TokenInfoCell>
......
...@@ -17,7 +17,7 @@ import { ButtonPrimary } from '../Button' ...@@ -17,7 +17,7 @@ import { ButtonPrimary } from '../Button'
import { LightCard } from '../Card' import { LightCard } from '../Card'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import { FiatValue } from '../CurrencyInputPanel/FiatValue' import { FiatValue } from '../CurrencyInputPanel/FiatValue'
import CurrencyLogo from '../CurrencyLogo' import CurrencyLogo from '../Logo/CurrencyLogo'
import { RowBetween, RowFixed } from '../Row' import { RowBetween, RowFixed } from '../Row'
import TradePrice from '../swap/TradePrice' import TradePrice from '../swap/TradePrice'
import { AdvancedSwapDetails } from './AdvancedSwapDetails' import { AdvancedSwapDetails } from './AdvancedSwapDetails'
......
...@@ -4,7 +4,7 @@ import { useWeb3React } from '@web3-react/core' ...@@ -4,7 +4,7 @@ import { useWeb3React } from '@web3-react/core'
import { ButtonEmpty } from 'components/Button' import { ButtonEmpty } from 'components/Button'
import Card, { OutlineCard } from 'components/Card' import Card, { OutlineCard } from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import Modal from 'components/Modal' import Modal from 'components/Modal'
import { AutoRow, RowBetween } from 'components/Row' import { AutoRow, RowBetween } from 'components/Row'
import { useState } from 'react' import { useState } from 'react'
......
import store from 'state'
import { DEFAULT_LIST_OF_LISTS } from './lists'
class TokenLogoLookupTable {
private dict: { [key: string]: string[] | undefined } = {}
private initialized = false
initialize() {
const dict: { [key: string]: string[] | undefined } = {}
DEFAULT_LIST_OF_LISTS.forEach((list) =>
store.getState().lists.byUrl[list].current?.tokens.forEach((token) => {
if (token.logoURI) {
const lowercaseAddress = token.address.toLowerCase()
const currentEntry = dict[lowercaseAddress]
if (currentEntry) {
currentEntry.push(token.logoURI)
} else {
dict[lowercaseAddress] = [token.logoURI]
}
}
})
)
this.dict = dict
this.initialized = true
}
getIcons(address?: string | null) {
if (!address) return undefined
if (!this.initialized) {
this.initialize()
}
return this.dict[address.toLowerCase()]
}
}
export default new TokenLogoLookupTable()
...@@ -61,14 +61,14 @@ export type TokenQueryData = NonNullable<TokenQuery$data['tokens']>[number] ...@@ -61,14 +61,14 @@ export type TokenQueryData = NonNullable<TokenQuery$data['tokens']>[number]
// TODO: Return a QueryToken from useTokenQuery instead of TokenQueryData to make it more usable in Currency-centric interfaces. // TODO: Return a QueryToken from useTokenQuery instead of TokenQueryData to make it more usable in Currency-centric interfaces.
export class QueryToken extends WrappedTokenInfo { export class QueryToken extends WrappedTokenInfo {
constructor(data: NonNullable<TokenQueryData>) { constructor(data: NonNullable<TokenQueryData>, logoSrc?: string) {
super({ super({
chainId: CHAIN_NAME_TO_CHAIN_ID[data.chain], chainId: CHAIN_NAME_TO_CHAIN_ID[data.chain],
address: data.address, address: data.address,
decimals: data.decimals ?? DEFAULT_ERC20_DECIMALS, decimals: data.decimals ?? DEFAULT_ERC20_DECIMALS,
symbol: data.symbol ?? '', symbol: data.symbol ?? '',
name: data.name ?? '', name: data.name ?? '',
logoURI: data.project?.logoUrl ?? undefined, logoURI: logoSrc ?? data.project?.logoUrl ?? undefined,
}) })
} }
} }
import TokenLogoLookupTable from 'constants/TokenLogoLookupTable'
import { chainIdToNetworkName, getNativeLogoURI } from 'lib/hooks/useCurrencyLogoURIs'
import uriToHttp from 'lib/utils/uriToHttp'
import { useCallback, useEffect, useState } from 'react'
import { isAddress } from 'utils'
export const BAD_SRCS: { [tokenAddress: string]: true } = {}
// Converts uri's into fetchable urls
function parseLogoSources(uris: string[]) {
const urls: string[] = []
uris.forEach((uri) => urls.push(...uriToHttp(uri)))
return urls
}
// Parses uri's, favors non-coingecko images, and improves coingecko logo quality
function prioritizeLogoSources(uris: string[]) {
const parsedUris = uris.map((uri) => uriToHttp(uri)).flat(1)
const preferredUris: string[] = []
// Consolidate duplicate coingecko urls into one fallback source
let coingeckoUrl: string | undefined = undefined
parsedUris.forEach((uri) => {
if (uri.startsWith('https://assets.coingecko')) {
if (!coingeckoUrl) {
coingeckoUrl = uri.replace(/small|thumb/g, 'large')
}
} else {
preferredUris.push(uri)
}
})
// Places coingecko urls in the back of the source array
return coingeckoUrl ? [...preferredUris, coingeckoUrl] : preferredUris
}
function getInitialUrl(address?: string | null, chainId?: number | null, isNative?: boolean) {
if (chainId && isNative) return getNativeLogoURI(chainId)
const networkName = chainId ? chainIdToNetworkName(chainId) : 'ethereum'
const checksummedAddress = isAddress(address)
if (checksummedAddress) {
return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${checksummedAddress}/logo.png`
} else {
return undefined
}
}
export default function useAssetLogoSource(
address?: string | null,
chainId?: number | null,
isNative?: boolean,
backupImg?: string | null
): [string | undefined, () => void] {
const [current, setCurrent] = useState<string | undefined>(getInitialUrl(address, chainId, isNative))
const [fallbackSrcs, setFallbackSrcs] = useState<string[] | undefined>(undefined)
useEffect(() => {
setCurrent(getInitialUrl(address, chainId, isNative))
setFallbackSrcs(undefined)
}, [address, chainId, isNative])
const nextSrc = useCallback(() => {
if (current) {
BAD_SRCS[current] = true
}
// Parses and stores logo sources from tokenlists if assets repo url fails
if (!fallbackSrcs) {
const uris = TokenLogoLookupTable.getIcons(address) ?? []
if (backupImg) uris.push(backupImg)
const tokenListIcons = prioritizeLogoSources(parseLogoSources(uris))
setCurrent(tokenListIcons.find((src) => !BAD_SRCS[src]))
setFallbackSrcs(tokenListIcons)
} else {
setCurrent(fallbackSrcs.find((src) => !BAD_SRCS[src]))
}
}, [current, fallbackSrcs, address, backupImg])
return [current, nextSrc]
}
...@@ -5,7 +5,7 @@ import { useMemo } from 'react' ...@@ -5,7 +5,7 @@ import { useMemo } from 'react'
import useENSContentHash from './useENSContentHash' import useENSContentHash from './useENSContentHash'
export default function useHttpLocations(uri: string | undefined): string[] { export default function useHttpLocations(uri: string | undefined | null): string[] {
const ens = useMemo(() => (uri ? parseENSAddress(uri) : undefined), [uri]) const ens = useMemo(() => (uri ? parseENSAddress(uri) : undefined), [uri])
const resolvedContentHash = useENSContentHash(ens?.ensName) const resolvedContentHash = useENSContentHash(ens?.ensName)
return useMemo(() => { return useMemo(() => {
......
...@@ -10,7 +10,7 @@ import { isCelo, NATIVE_CHAIN_ID, nativeOnChain } from '../../constants/tokens' ...@@ -10,7 +10,7 @@ import { isCelo, NATIVE_CHAIN_ID, nativeOnChain } from '../../constants/tokens'
type Network = 'ethereum' | 'arbitrum' | 'optimism' | 'polygon' type Network = 'ethereum' | 'arbitrum' | 'optimism' | 'polygon'
function chainIdToNetworkName(networkId: SupportedChainId): Network { export function chainIdToNetworkName(networkId: SupportedChainId): Network {
switch (networkId) { switch (networkId) {
case SupportedChainId.MAINNET: case SupportedChainId.MAINNET:
return 'ethereum' return 'ethereum'
...@@ -60,7 +60,7 @@ export default function useCurrencyLogoURIs( ...@@ -60,7 +60,7 @@ export default function useCurrencyLogoURIs(
isToken?: boolean isToken?: boolean
address?: string address?: string
chainId: number chainId: number
logoURI?: string logoURI?: string | null
} }
| null | null
| undefined | undefined
......
...@@ -3,7 +3,7 @@ import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core' ...@@ -3,7 +3,7 @@ import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core'
import { Text } from 'rebass' import { Text } from 'rebass'
import { ButtonPrimary } from '../../components/Button' import { ButtonPrimary } from '../../components/Button'
import CurrencyLogo from '../../components/CurrencyLogo' import CurrencyLogo from '../../components/Logo/CurrencyLogo'
import { RowBetween, RowFixed } from '../../components/Row' import { RowBetween, RowFixed } from '../../components/Row'
import { Field } from '../../state/mint/actions' import { Field } from '../../state/mint/actions'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
......
...@@ -35,8 +35,8 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' ...@@ -35,8 +35,8 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import { unwrappedToken } from 'utils/unwrappedToken' import { unwrappedToken } from 'utils/unwrappedToken'
import { AutoColumn } from '../../components/Column' import { AutoColumn } from '../../components/Column'
import CurrencyLogo from '../../components/CurrencyLogo'
import FormattedCurrencyAmount from '../../components/FormattedCurrencyAmount' import FormattedCurrencyAmount from '../../components/FormattedCurrencyAmount'
import CurrencyLogo from '../../components/Logo/CurrencyLogo'
import { AutoRow, RowBetween, RowFixed } from '../../components/Row' import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
import { V2_FACTORY_ADDRESSES } from '../../constants/addresses' import { V2_FACTORY_ADDRESSES } from '../../constants/addresses'
import { WRAPPED_NATIVE_CURRENCY } from '../../constants/tokens' import { WRAPPED_NATIVE_CURRENCY } from '../../constants/tokens'
......
...@@ -11,9 +11,9 @@ import Badge from 'components/Badge' ...@@ -11,9 +11,9 @@ import Badge from 'components/Badge'
import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button' import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button'
import { DarkCard, LightCard } from 'components/Card' import { DarkCard, LightCard } from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { RowBetween, RowFixed } from 'components/Row' import { RowBetween, RowFixed } from 'components/Row'
import { Dots } from 'components/swap/styleds' import { Dots } from 'components/swap/styleds'
import Toggle from 'components/Toggle' import Toggle from 'components/Toggle'
......
...@@ -13,7 +13,7 @@ import { ButtonDropdownLight } from '../../components/Button' ...@@ -13,7 +13,7 @@ import { ButtonDropdownLight } from '../../components/Button'
import { LightCard } from '../../components/Card' import { LightCard } from '../../components/Card'
import { BlueCard } from '../../components/Card' import { BlueCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import CurrencyLogo from '../../components/CurrencyLogo' import CurrencyLogo from '../../components/Logo/CurrencyLogo'
import { FindPoolTabs } from '../../components/NavigationTabs' import { FindPoolTabs } from '../../components/NavigationTabs'
import { MinimalPositionCard } from '../../components/PositionCard' import { MinimalPositionCard } from '../../components/PositionCard'
import Row from '../../components/Row' import Row from '../../components/Row'
......
...@@ -9,11 +9,11 @@ import RangeBadge from 'components/Badge/RangeBadge' ...@@ -9,11 +9,11 @@ import RangeBadge from 'components/Badge/RangeBadge'
import { ButtonConfirmed, ButtonPrimary } from 'components/Button' import { ButtonConfirmed, ButtonPrimary } from 'components/Button'
import { LightCard } from 'components/Card' import { LightCard } from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import { Break } from 'components/earn/styled' import { Break } from 'components/earn/styled'
import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount' import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { AddRemoveTabs } from 'components/NavigationTabs' import { AddRemoveTabs } from 'components/NavigationTabs'
import { AutoRow, RowBetween, RowFixed } from 'components/Row' import { AutoRow, RowBetween, RowFixed } from 'components/Row'
import Slider from 'components/Slider' import Slider from 'components/Slider'
......
...@@ -18,8 +18,8 @@ import { ButtonConfirmed, ButtonError, ButtonLight, ButtonPrimary } from '../../ ...@@ -18,8 +18,8 @@ import { ButtonConfirmed, ButtonError, ButtonLight, ButtonPrimary } from '../../
import { BlueCard, LightCard } from '../../components/Card' import { BlueCard, LightCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import CurrencyInputPanel from '../../components/CurrencyInputPanel' import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import CurrencyLogo from '../../components/CurrencyLogo'
import DoubleCurrencyLogo from '../../components/DoubleLogo' import DoubleCurrencyLogo from '../../components/DoubleLogo'
import CurrencyLogo from '../../components/Logo/CurrencyLogo'
import { AddRemoveTabs } from '../../components/NavigationTabs' import { AddRemoveTabs } from '../../components/NavigationTabs'
import { MinimalPositionCard } from '../../components/PositionCard' import { MinimalPositionCard } from '../../components/PositionCard'
import Row, { RowBetween, RowFixed } from '../../components/Row' import Row, { RowBetween, RowFixed } from '../../components/Row'
......
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