-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(L2): block import of unsupported tokens #2673
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Trans } from '@lingui/macro' | ||
import { Token } from '@uniswap/sdk-core' | ||
import { ButtonPrimary } from 'components/Button' | ||
import { AlertCircle, ArrowLeft } from 'react-feather' | ||
import styled from 'styled-components/macro' | ||
import { CloseIcon, TYPE } from 'theme' | ||
|
||
import TokenImportCard from './TokenImportCard' | ||
|
||
const Wrapper = styled.div` | ||
align-items: center; | ||
display: flex; | ||
flex-direction: column; | ||
flex: 1 1 auto; | ||
height: 100%; | ||
width: 100%; | ||
` | ||
const Button = styled(ButtonPrimary)` | ||
margin-top: 1em; | ||
padding: 10px 1em; | ||
` | ||
const Content = styled.div` | ||
padding: 1em; | ||
` | ||
const Copy = styled(TYPE.body)` | ||
text-align: center; | ||
margin: 0 2em 1em !important; | ||
font-weight: 400; | ||
font-size: 16px; | ||
` | ||
const Header = styled.div` | ||
align-items: center; | ||
display: flex; | ||
gap: 14px; | ||
justify-content: space-between; | ||
padding: 20px; | ||
width: 100%; | ||
` | ||
const Icon = styled(AlertCircle)` | ||
stroke: ${({ theme }) => theme.text2}; | ||
width: 48px; | ||
height: 48px; | ||
` | ||
interface BlockedTokenProps { | ||
onBack: (() => void) | undefined | ||
onDismiss: (() => void) | undefined | ||
blockedTokens: Token[] | ||
} | ||
|
||
const BlockedToken = ({ onBack, onDismiss, blockedTokens }: BlockedTokenProps) => ( | ||
<Wrapper> | ||
<Header> | ||
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />} | ||
<TYPE.mediumHeader> | ||
<Trans>Token not supported</Trans> | ||
</TYPE.mediumHeader> | ||
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />} | ||
</Header> | ||
<Icon /> | ||
<Content> | ||
<Copy> | ||
<Trans>This token is not supported in the Uniswap Labs app</Trans> | ||
</Copy> | ||
<TokenImportCard token={blockedTokens[0]} /> | ||
<Button disabled> | ||
<Trans>Import</Trans> | ||
</Button> | ||
</Content> | ||
</Wrapper> | ||
) | ||
export default BlockedToken |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,45 +2,26 @@ import { Plural, Trans } from '@lingui/macro' | |
import { Currency, Token } from '@uniswap/sdk-core' | ||
import { TokenList } from '@uniswap/token-lists' | ||
import { ButtonPrimary } from 'components/Button' | ||
import Card from 'components/Card' | ||
import { AutoColumn } from 'components/Column' | ||
import CurrencyLogo from 'components/CurrencyLogo' | ||
import ListLogo from 'components/ListLogo' | ||
import { RowBetween, RowFixed } from 'components/Row' | ||
import { RowBetween } from 'components/Row' | ||
import { SectionBreak } from 'components/swap/styleds' | ||
import { useUnsupportedTokens } from 'hooks/Tokens' | ||
import useTheme from 'hooks/useTheme' | ||
import { useActiveWeb3React } from 'hooks/web3' | ||
import { transparentize } from 'polished' | ||
import { AlertCircle, ArrowLeft } from 'react-feather' | ||
import { useAddUserToken } from 'state/user/hooks' | ||
import styled from 'styled-components/macro' | ||
import { CloseIcon, TYPE } from 'theme' | ||
|
||
import { ExternalLink } from '../../theme/components' | ||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink' | ||
import BlockedToken from './BlockedToken' | ||
import { PaddedColumn } from './styleds' | ||
import TokenImportCard from './TokenImportCard' | ||
|
||
const Wrapper = styled.div` | ||
position: relative; | ||
width: 100%; | ||
overflow: auto; | ||
` | ||
|
||
const WarningWrapper = styled(Card)<{ highWarning: boolean }>` | ||
background-color: ${({ theme, highWarning }) => | ||
highWarning ? transparentize(0.8, theme.red1) : transparentize(0.8, theme.yellow2)}; | ||
width: fit-content; | ||
` | ||
|
||
const AddressText = styled(TYPE.blue)` | ||
font-size: 12px; | ||
word-break: break-all; | ||
|
||
${({ theme }) => theme.mediaWidth.upToSmall` | ||
font-size: 10px; | ||
`} | ||
` | ||
|
||
interface ImportProps { | ||
tokens: Token[] | ||
list?: TokenList | ||
|
@@ -49,13 +30,18 @@ interface ImportProps { | |
handleCurrencySelect?: (currency: Currency) => void | ||
} | ||
|
||
export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySelect }: ImportProps) { | ||
export function ImportToken(props: ImportProps) { | ||
const { tokens, list, onBack, onDismiss, handleCurrencySelect } = props | ||
const theme = useTheme() | ||
|
||
const { chainId } = useActiveWeb3React() | ||
|
||
const addToken = useAddUserToken() | ||
|
||
const unsupportedTokens = useUnsupportedTokens() | ||
const unsupportedSet = new Set(Object.keys(unsupportedTokens)) | ||
const intersection = new Set(tokens.filter((token) => unsupportedSet.has(token.address))) | ||
if (intersection.size > 0) { | ||
return <BlockedToken onBack={onBack} onDismiss={onDismiss} blockedTokens={Array.from(intersection)} /> | ||
} | ||
Comment on lines
+39
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's the logic for checking whether or not to render the block modal. |
||
return ( | ||
<Wrapper> | ||
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}> | ||
|
@@ -78,52 +64,9 @@ export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySel | |
</Trans> | ||
</TYPE.body> | ||
</AutoColumn> | ||
{tokens.map((token) => { | ||
return ( | ||
<Card | ||
backgroundColor={theme.bg2} | ||
key={'import' + token.address} | ||
className=".token-warning-container" | ||
padding="2rem" | ||
> | ||
<AutoColumn gap="10px" justify="center"> | ||
<CurrencyLogo currency={token} size={'32px'} /> | ||
|
||
<AutoColumn gap="4px" justify="center"> | ||
<TYPE.body ml="8px" mr="8px" fontWeight={500} fontSize={20}> | ||
{token.symbol} | ||
</TYPE.body> | ||
<TYPE.darkGray fontWeight={400} fontSize={14}> | ||
{token.name} | ||
</TYPE.darkGray> | ||
</AutoColumn> | ||
{chainId && ( | ||
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}> | ||
<AddressText fontSize={12}>{token.address}</AddressText> | ||
</ExternalLink> | ||
)} | ||
{list !== undefined ? ( | ||
<RowFixed> | ||
{list.logoURI && <ListLogo logoURI={list.logoURI} size="16px" />} | ||
<TYPE.small ml="6px" fontSize={14} color={theme.text3}> | ||
<Trans>via {list.name} token list</Trans> | ||
</TYPE.small> | ||
</RowFixed> | ||
) : ( | ||
<WarningWrapper $borderRadius="4px" padding="4px" highWarning={true}> | ||
<RowFixed> | ||
<AlertCircle stroke={theme.red1} size="10px" /> | ||
<TYPE.body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}> | ||
<Trans>Unknown Source</Trans> | ||
</TYPE.body> | ||
</RowFixed> | ||
</WarningWrapper> | ||
)} | ||
</AutoColumn> | ||
</Card> | ||
) | ||
})} | ||
|
||
{tokens.map((token) => ( | ||
<TokenImportCard token={token} list={list} key={'import' + token.address} /> | ||
))} | ||
Comment on lines
+67
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made this code block a component so I could reuse it in the blocking modal. |
||
<ButtonPrimary | ||
altDisabledStyle={true} | ||
$borderRadius="20px" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { Trans } from '@lingui/macro' | ||
import { Token } from '@uniswap/sdk-core' | ||
import { TokenList } from '@uniswap/token-lists' | ||
import Card from 'components/Card' | ||
import { AutoColumn } from 'components/Column' | ||
import CurrencyLogo from 'components/CurrencyLogo' | ||
import ListLogo from 'components/ListLogo' | ||
import { RowFixed } from 'components/Row' | ||
import { useActiveWeb3React } from 'hooks/web3' | ||
import { transparentize } from 'polished' | ||
import { AlertCircle } from 'react-feather' | ||
import styled, { useTheme } from 'styled-components/macro' | ||
import { ExternalLink, TYPE } from 'theme' | ||
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' | ||
|
||
const WarningWrapper = styled(Card)<{ highWarning: boolean }>` | ||
background-color: ${({ theme, highWarning }) => | ||
highWarning ? transparentize(0.8, theme.red1) : transparentize(0.8, theme.yellow2)}; | ||
width: fit-content; | ||
` | ||
|
||
const AddressText = styled(TYPE.blue)` | ||
font-size: 12px; | ||
word-break: break-all; | ||
|
||
${({ theme }) => theme.mediaWidth.upToSmall` | ||
font-size: 10px; | ||
`} | ||
` | ||
interface TokenImportCardProps { | ||
list?: TokenList | ||
token: Token | ||
} | ||
const TokenImportCard = ({ list, token }: TokenImportCardProps) => { | ||
const theme = useTheme() | ||
const { chainId } = useActiveWeb3React() | ||
return ( | ||
<Card backgroundColor={theme.bg2} padding="2rem"> | ||
<AutoColumn gap="10px" justify="center"> | ||
<CurrencyLogo currency={token} size={'32px'} /> | ||
<AutoColumn gap="4px" justify="center"> | ||
<TYPE.body ml="8px" mr="8px" fontWeight={500} fontSize={20}> | ||
{token.symbol} | ||
</TYPE.body> | ||
<TYPE.darkGray fontWeight={400} fontSize={14}> | ||
{token.name} | ||
</TYPE.darkGray> | ||
</AutoColumn> | ||
{chainId && ( | ||
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}> | ||
<AddressText fontSize={12}>{token.address}</AddressText> | ||
</ExternalLink> | ||
)} | ||
{list !== undefined ? ( | ||
<RowFixed> | ||
{list.logoURI && <ListLogo logoURI={list.logoURI} size="16px" />} | ||
<TYPE.small ml="6px" fontSize={14} color={theme.text3}> | ||
<Trans>via {list.name} token list</Trans> | ||
</TYPE.small> | ||
</RowFixed> | ||
) : ( | ||
<WarningWrapper $borderRadius="4px" padding="4px" highWarning={true}> | ||
<RowFixed> | ||
<AlertCircle stroke={theme.red1} size="10px" /> | ||
<TYPE.body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}> | ||
<Trans>Unknown Source</Trans> | ||
</TYPE.body> | ||
</RowFixed> | ||
</WarningWrapper> | ||
)} | ||
</AutoColumn> | ||
</Card> | ||
) | ||
} | ||
|
||
export default TokenImportCard |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import { Trans } from '@lingui/macro' | ||
import { Currency, Token } from '@uniswap/sdk-core' | ||
import { Currency } from '@uniswap/sdk-core' | ||
import { ButtonEmpty } from 'components/Button' | ||
import Card, { OutlineCard } from 'components/Card' | ||
import { AutoColumn } from 'components/Column' | ||
|
@@ -62,7 +62,7 @@ export default function UnsupportedCurrencyFooter({ | |
}) | ||
: [] | ||
|
||
const unsupportedTokens: { [address: string]: Token } = useUnsupportedTokens() | ||
const unsupportedTokens = useUnsupportedTokens() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just a tiny TS simplification I saw while investigating. |
||
|
||
return ( | ||
<DetailsFooter show={show}> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to make the render cases a little easier to read