Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
719754c46c | ||
|
|
9170af888e | ||
|
|
b258f557d1 | ||
|
|
9d8c7f8e12 | ||
|
|
9c44e61e23 | ||
|
|
71db11b6ac | ||
|
|
db3328c8d9 |
@@ -115,7 +115,13 @@ export default function Modal({
|
|||||||
{fadeTransition.map(
|
{fadeTransition.map(
|
||||||
({ item, key, props }) =>
|
({ item, key, props }) =>
|
||||||
item && (
|
item && (
|
||||||
<StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
|
<StyledDialogOverlay
|
||||||
|
key={key}
|
||||||
|
style={props}
|
||||||
|
onDismiss={onDismiss}
|
||||||
|
initialFocusRef={initialFocusRef}
|
||||||
|
unstable_lockFocusAcrossFrames={false}
|
||||||
|
>
|
||||||
<StyledDialogContent
|
<StyledDialogContent
|
||||||
{...(isMobile
|
{...(isMobile
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { Token } from '@uniswap/sdk'
|
import { Token } from '@uniswap/sdk'
|
||||||
import React, { useCallback } from 'react'
|
import React from 'react'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { ImportToken } from 'components/SearchModal/ImportToken'
|
import { ImportToken } from 'components/SearchModal/ImportToken'
|
||||||
|
|
||||||
export default function TokenWarningModal({
|
export default function TokenWarningModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
tokens,
|
tokens,
|
||||||
onConfirm
|
onConfirm,
|
||||||
|
onDismiss
|
||||||
}: {
|
}: {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
tokens: Token[]
|
tokens: Token[]
|
||||||
onConfirm: () => void
|
onConfirm: () => void
|
||||||
|
onDismiss: () => void
|
||||||
}) {
|
}) {
|
||||||
const handleDismiss = useCallback(() => null, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onDismiss={handleDismiss} maxHeight={90}>
|
<Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={100}>
|
||||||
<ImportToken tokens={tokens} handleCurrencySelect={onConfirm} />
|
<ImportToken tokens={tokens} handleCurrencySelect={onConfirm} />
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
|
|||||||
{!showRoute && (
|
{!showRoute && (
|
||||||
<AutoColumn style={{ padding: '12px 16px 0 16px' }}>
|
<AutoColumn style={{ padding: '12px 16px 0 16px' }}>
|
||||||
<InfoLink
|
<InfoLink
|
||||||
href={'https://uniswap.info/pair/' + trade.route.pairs[0].liquidityToken.address}
|
href={'https://info.uniswap.org/pair/' + trade.route.pairs[0].liquidityToken.address}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
View pair analytics ↗
|
View pair analytics ↗
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ export default function UnsupportedCurrencyFooter({
|
|||||||
<AutoColumn gap="lg">
|
<AutoColumn gap="lg">
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.mediumHeader>Unsupported Assets</TYPE.mediumHeader>
|
<TYPE.mediumHeader>Unsupported Assets</TYPE.mediumHeader>
|
||||||
|
|
||||||
<CloseIcon onClick={() => setShowDetails(false)} />
|
<CloseIcon onClick={() => setShowDetails(false)} />
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
{tokens.map(token => {
|
{tokens.map(token => {
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
// used to mark unsupported tokens, these are hosted lists of unsupported tokens
|
// used to mark unsupported tokens, these are hosted lists of unsupported tokens
|
||||||
/**
|
|
||||||
* @TODO add list from blockchain association
|
|
||||||
*/
|
|
||||||
export const UNSUPPORTED_LIST_URLS: string[] = []
|
|
||||||
|
|
||||||
const COMPOUND_LIST = 'https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json'
|
const COMPOUND_LIST = 'https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json'
|
||||||
const UMA_LIST = 'https://umaproject.org/uma.tokenlist.json'
|
const UMA_LIST = 'https://umaproject.org/uma.tokenlist.json'
|
||||||
@@ -17,6 +13,9 @@ const CMC_ALL_LIST = 'defi.cmc.eth'
|
|||||||
const CMC_STABLECOIN = 'stablecoin.cmc.eth'
|
const CMC_STABLECOIN = 'stablecoin.cmc.eth'
|
||||||
const KLEROS_LIST = 't2crtokens.eth'
|
const KLEROS_LIST = 't2crtokens.eth'
|
||||||
const GEMINI_LIST = 'https://www.gemini.com/uniswap/manifest.json'
|
const GEMINI_LIST = 'https://www.gemini.com/uniswap/manifest.json'
|
||||||
|
const BA_LIST = 'https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json'
|
||||||
|
|
||||||
|
export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST]
|
||||||
|
|
||||||
// lower index == higher priority for token import
|
// lower index == higher priority for token import
|
||||||
export const DEFAULT_LIST_OF_LISTS: string[] = [
|
export const DEFAULT_LIST_OF_LISTS: string[] = [
|
||||||
|
|||||||
@@ -150,18 +150,18 @@ export function useTradeExactOut(currencyIn?: Currency, currencyAmountOut?: Curr
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useIsTransactionUnsupported(currencyIn?: Currency, currencyOut?: Currency): boolean {
|
export function useIsTransactionUnsupported(currencyIn?: Currency, currencyOut?: Currency): boolean {
|
||||||
const unsupportedToken: { [address: string]: Token } = useUnsupportedTokens()
|
const unsupportedTokens: { [address: string]: Token } = useUnsupportedTokens()
|
||||||
const { chainId } = useActiveWeb3React()
|
const { chainId } = useActiveWeb3React()
|
||||||
|
|
||||||
const tokenIn = wrappedCurrency(currencyIn, chainId)
|
const tokenIn = wrappedCurrency(currencyIn, chainId)
|
||||||
const tokenOut = wrappedCurrency(currencyOut, chainId)
|
const tokenOut = wrappedCurrency(currencyOut, chainId)
|
||||||
|
|
||||||
// if unsupported list loaded & either token on list, mark as unsupported
|
// if unsupported list loaded & either token on list, mark as unsupported
|
||||||
if (unsupportedToken) {
|
if (unsupportedTokens) {
|
||||||
if (tokenIn && Object.keys(unsupportedToken).includes(tokenIn.address)) {
|
if (tokenIn && Object.keys(unsupportedTokens).includes(tokenIn.address)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (tokenOut && Object.keys(unsupportedToken).includes(tokenOut.address)) {
|
if (tokenOut && Object.keys(unsupportedTokens).includes(tokenOut.address)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,4 +77,4 @@ ReactDOM.render(
|
|||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
)
|
)
|
||||||
|
|
||||||
serviceWorkerRegistration.register()
|
serviceWorkerRegistration.unregister()
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ import Loader from '../../components/Loader'
|
|||||||
import { useIsTransactionUnsupported } from 'hooks/Trades'
|
import { useIsTransactionUnsupported } from 'hooks/Trades'
|
||||||
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
|
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
|
||||||
import { isTradeBetter } from 'utils/trades'
|
import { isTradeBetter } from 'utils/trades'
|
||||||
|
import { RouteComponentProps } from 'react-router-dom'
|
||||||
|
|
||||||
export default function Swap() {
|
export default function Swap({ history }: RouteComponentProps) {
|
||||||
const loadedUrlParams = useDefaultsFromURLSearch()
|
const loadedUrlParams = useDefaultsFromURLSearch()
|
||||||
|
|
||||||
// token warning stuff
|
// token warning stuff
|
||||||
@@ -97,6 +98,7 @@ export default function Swap() {
|
|||||||
currencies,
|
currencies,
|
||||||
inputError: swapInputError
|
inputError: swapInputError
|
||||||
} = useDerivedSwapInfo()
|
} = useDerivedSwapInfo()
|
||||||
|
|
||||||
const { wrapType, execute: onWrap, inputError: wrapInputError } = useWrapCallback(
|
const { wrapType, execute: onWrap, inputError: wrapInputError } = useWrapCallback(
|
||||||
currencies[Field.INPUT],
|
currencies[Field.INPUT],
|
||||||
currencies[Field.OUTPUT],
|
currencies[Field.OUTPUT],
|
||||||
@@ -142,6 +144,12 @@ export default function Swap() {
|
|||||||
[onUserInput]
|
[onUserInput]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// reset if they close warning without tokens in params
|
||||||
|
const handleDismissTokenWarning = useCallback(() => {
|
||||||
|
setDismissTokenWarning(true)
|
||||||
|
history.push('/swap/')
|
||||||
|
}, [history])
|
||||||
|
|
||||||
// modal and loading
|
// modal and loading
|
||||||
const [{ showConfirm, tradeToConfirm, swapErrorMessage, attemptingTxn, txHash }, setSwapState] = useState<{
|
const [{ showConfirm, tradeToConfirm, swapErrorMessage, attemptingTxn, txHash }, setSwapState] = useState<{
|
||||||
showConfirm: boolean
|
showConfirm: boolean
|
||||||
@@ -297,6 +305,7 @@ export default function Swap() {
|
|||||||
isOpen={importTokensNotInDefault.length > 0 && !dismissTokenWarning}
|
isOpen={importTokensNotInDefault.length > 0 && !dismissTokenWarning}
|
||||||
tokens={importTokensNotInDefault}
|
tokens={importTokensNotInDefault}
|
||||||
onConfirm={handleConfirmTokenWarning}
|
onConfirm={handleConfirmTokenWarning}
|
||||||
|
onDismiss={handleDismissTokenWarning}
|
||||||
/>
|
/>
|
||||||
<SwapPoolTabs active={'swap'} />
|
<SwapPoolTabs active={'swap'} />
|
||||||
<AppBody>
|
<AppBody>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DEFAULT_ACTIVE_LIST_URLS } from './../../constants/lists'
|
import { DEFAULT_ACTIVE_LIST_URLS, UNSUPPORTED_LIST_URLS } from './../../constants/lists'
|
||||||
import { createReducer } from '@reduxjs/toolkit'
|
import { createReducer } from '@reduxjs/toolkit'
|
||||||
import { getVersionUpgrade, VersionUpgrade } from '@uniswap/token-lists'
|
import { getVersionUpgrade, VersionUpgrade } from '@uniswap/token-lists'
|
||||||
import { TokenList } from '@uniswap/token-lists/dist/types'
|
import { TokenList } from '@uniswap/token-lists/dist/types'
|
||||||
@@ -36,7 +36,7 @@ type Mutable<T> = { -readonly [P in keyof T]: T[P] extends ReadonlyArray<infer U
|
|||||||
const initialState: ListsState = {
|
const initialState: ListsState = {
|
||||||
lastInitializedDefaultListOfLists: DEFAULT_LIST_OF_LISTS,
|
lastInitializedDefaultListOfLists: DEFAULT_LIST_OF_LISTS,
|
||||||
byUrl: {
|
byUrl: {
|
||||||
...DEFAULT_LIST_OF_LISTS.reduce<Mutable<ListsState['byUrl']>>((memo, listUrl) => {
|
...DEFAULT_LIST_OF_LISTS.concat(...UNSUPPORTED_LIST_URLS).reduce<Mutable<ListsState['byUrl']>>((memo, listUrl) => {
|
||||||
memo[listUrl] = NEW_LIST_STATE
|
memo[listUrl] = NEW_LIST_STATE
|
||||||
return memo
|
return memo
|
||||||
}, {})
|
}, {})
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { AppDispatch } from '../index'
|
|||||||
import { acceptListUpdate } from './actions'
|
import { acceptListUpdate } from './actions'
|
||||||
import { useActiveListUrls } from './hooks'
|
import { useActiveListUrls } from './hooks'
|
||||||
import { useAllInactiveTokens } from 'hooks/Tokens'
|
import { useAllInactiveTokens } from 'hooks/Tokens'
|
||||||
|
import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
|
||||||
|
|
||||||
export default function Updater(): null {
|
export default function Updater(): null {
|
||||||
const { library } = useActiveWeb3React()
|
const { library } = useActiveWeb3React()
|
||||||
@@ -44,6 +45,16 @@ export default function Updater(): null {
|
|||||||
})
|
})
|
||||||
}, [dispatch, fetchList, library, lists])
|
}, [dispatch, fetchList, library, lists])
|
||||||
|
|
||||||
|
// if any lists from unsupported lists are loaded, check them too (in case new updates since last visit)
|
||||||
|
useEffect(() => {
|
||||||
|
Object.keys(UNSUPPORTED_LIST_URLS).forEach(listUrl => {
|
||||||
|
const list = lists[listUrl]
|
||||||
|
if (!list || (!list.current && !list.loadingRequestId && !list.error)) {
|
||||||
|
fetchList(listUrl).catch(error => console.debug('list added fetching error', error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [dispatch, fetchList, library, lists])
|
||||||
|
|
||||||
// automatically update lists if versions are minor/patch
|
// automatically update lists if versions are minor/patch
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Object.keys(lists).forEach(listUrl => {
|
Object.keys(lists).forEach(listUrl => {
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export function useUserAddedTokens(): Token[] {
|
|||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
if (!chainId) return []
|
if (!chainId) return []
|
||||||
return Object.values(serializedTokensMap[chainId as ChainId] ?? {}).map(deserializeToken)
|
return Object.values(serializedTokensMap?.[chainId as ChainId] ?? {}).map(deserializeToken)
|
||||||
}, [serializedTokensMap, chainId])
|
}, [serializedTokensMap, chainId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,11 +111,17 @@ export default createReducer(initialState, builder =>
|
|||||||
state.userSingleHopOnly = action.payload.userSingleHopOnly
|
state.userSingleHopOnly = action.payload.userSingleHopOnly
|
||||||
})
|
})
|
||||||
.addCase(addSerializedToken, (state, { payload: { serializedToken } }) => {
|
.addCase(addSerializedToken, (state, { payload: { serializedToken } }) => {
|
||||||
|
if (!state.tokens) {
|
||||||
|
state.tokens = {}
|
||||||
|
}
|
||||||
state.tokens[serializedToken.chainId] = state.tokens[serializedToken.chainId] || {}
|
state.tokens[serializedToken.chainId] = state.tokens[serializedToken.chainId] || {}
|
||||||
state.tokens[serializedToken.chainId][serializedToken.address] = serializedToken
|
state.tokens[serializedToken.chainId][serializedToken.address] = serializedToken
|
||||||
state.timestamp = currentTimestamp()
|
state.timestamp = currentTimestamp()
|
||||||
})
|
})
|
||||||
.addCase(removeSerializedToken, (state, { payload: { address, chainId } }) => {
|
.addCase(removeSerializedToken, (state, { payload: { address, chainId } }) => {
|
||||||
|
if (!state.tokens) {
|
||||||
|
state.tokens = {}
|
||||||
|
}
|
||||||
state.tokens[chainId] = state.tokens[chainId] || {}
|
state.tokens[chainId] = state.tokens[chainId] || {}
|
||||||
delete state.tokens[chainId][address]
|
delete state.tokens[chainId][address]
|
||||||
state.timestamp = currentTimestamp()
|
state.timestamp = currentTimestamp()
|
||||||
|
|||||||
Reference in New Issue
Block a user