feat: use router depending on the origin (#6982)
* feat: initial commit * chore: whitelist vercel * chore: fix e2e test * chore: update all occurences of # * chore: tweaks * chore: remove todo * chore: revert changes * chore: bring back old tweet logic and fix nested URLs * chore: fix merge * improve check * fix: cypress * chore: fix tests * chore: update snapshot * chore: update readme * address review * satisfy eslint * chore: fix ui issue * fix: tests * fix: e2e test
This commit is contained in:
parent
a7135c9ab1
commit
c9b4016b78
@ -69,10 +69,10 @@ Other things to note:
|
|||||||
|
|
||||||
The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2.
|
The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2.
|
||||||
|
|
||||||
- Swap on Uniswap V2: <https://app.uniswap.org/#/swap?use=v2>
|
- Swap on Uniswap V2: <https://app.uniswap.org/swap?use=v2>
|
||||||
- View V2 liquidity: <https://app.uniswap.org/#/pools/v2>
|
- View V2 liquidity: <https://app.uniswap.org/pools/v2>
|
||||||
- Add V2 liquidity: <https://app.uniswap.org/#/add/v2>
|
- Add V2 liquidity: <https://app.uniswap.org/add/v2>
|
||||||
- Migrate V2 liquidity to V3: <https://app.uniswap.org/#/migrate/v2>
|
- Migrate V2 liquidity to V3: <https://app.uniswap.org/migrate/v2>
|
||||||
|
|
||||||
## Accessing Uniswap V1
|
## Accessing Uniswap V1
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ describe('Testing nfts', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should load pudgy penguin collection page', () => {
|
it('should load pudgy penguin collection page', () => {
|
||||||
cy.visit(`/#/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
cy.visit(`/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
||||||
cy.get(getTestSelector('nft-collection-asset')).should('exist')
|
cy.get(getTestSelector('nft-collection-asset')).should('exist')
|
||||||
cy.get(getTestSelector('nft-collection-filter-buy-now')).should('not.exist')
|
cy.get(getTestSelector('nft-collection-filter-buy-now')).should('not.exist')
|
||||||
cy.get(getTestSelector('nft-filter')).first().click()
|
cy.get(getTestSelector('nft-filter')).first().click()
|
||||||
@ -20,13 +20,13 @@ describe('Testing nfts', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to navigate to activity', () => {
|
it('should be able to navigate to activity', () => {
|
||||||
cy.visit(`/#/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
cy.visit(`/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
||||||
cy.get(getTestSelector('nft-activity')).first().click()
|
cy.get(getTestSelector('nft-activity')).first().click()
|
||||||
cy.get(getTestSelector('nft-activity-row')).should('exist')
|
cy.get(getTestSelector('nft-activity-row')).should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should go to the details page', () => {
|
it('should go to the details page', () => {
|
||||||
cy.visit(`/#/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
cy.visit(`/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
||||||
cy.get(getTestSelector('nft-filter')).first().click()
|
cy.get(getTestSelector('nft-filter')).first().click()
|
||||||
cy.get(getTestSelector('nft-collection-filter-buy-now')).click()
|
cy.get(getTestSelector('nft-collection-filter-buy-now')).click()
|
||||||
cy.get(getTestSelector('nft-collection-asset')).first().click()
|
cy.get(getTestSelector('nft-collection-asset')).first().click()
|
||||||
@ -37,7 +37,7 @@ describe('Testing nfts', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should toggle buy now on details page', () => {
|
it('should toggle buy now on details page', () => {
|
||||||
cy.visit(`/#/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
cy.visit(`/nfts/collection/${PUDGY_COLLECTION_ADDRESS}`)
|
||||||
cy.get(getTestSelector('nft-filter')).first().click()
|
cy.get(getTestSelector('nft-filter')).first().click()
|
||||||
cy.get(getTestSelector('nft-collection-filter-buy-now')).click()
|
cy.get(getTestSelector('nft-collection-filter-buy-now')).click()
|
||||||
cy.get(getTestSelector('nft-collection-asset')).first().click()
|
cy.get(getTestSelector('nft-collection-asset')).first().click()
|
||||||
|
@ -69,8 +69,5 @@ describe('Token explore', () => {
|
|||||||
cy.get(getTestSelector('tokens-network-filter-selected')).click()
|
cy.get(getTestSelector('tokens-network-filter-selected')).click()
|
||||||
cy.get(getTestSelector('tokens-network-filter-option-optimism')).click()
|
cy.get(getTestSelector('tokens-network-filter-option-optimism')).click()
|
||||||
cy.get(getTestSelector('tokens-network-filter-selected')).should('contain', 'Optimism')
|
cy.get(getTestSelector('tokens-network-filter-selected')).should('contain', 'Optimism')
|
||||||
cy.reload()
|
|
||||||
cy.get(getTestSelector('tokens-network-filter-selected')).should('contain', 'Optimism')
|
|
||||||
cy.get(getTestSelector('chain-selector-logo')).invoke('attr', 'alt').should('eq', 'Ethereum')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -25,7 +25,7 @@ describe('Universal search bar', () => {
|
|||||||
.and('contain.text', '$')
|
.and('contain.text', '$')
|
||||||
.and('contain.text', '%')
|
.and('contain.text', '%')
|
||||||
.click()
|
.click()
|
||||||
cy.location('hash').should('equal', '#/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984')
|
cy.location('pathname').should('equal', '/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984')
|
||||||
|
|
||||||
openSearch()
|
openSearch()
|
||||||
cy.get(getTestSelector('searchbar-dropdown'))
|
cy.get(getTestSelector('searchbar-dropdown'))
|
||||||
|
@ -26,11 +26,11 @@ describe('Wallet Dropdown', () => {
|
|||||||
cy.contains('Uniswap available in: English').should('not.exist')
|
cy.contains('Uniswap available in: English').should('not.exist')
|
||||||
|
|
||||||
cy.get(getTestSelector('wallet-language-item')).contains('Afrikaans').click({ force: true })
|
cy.get(getTestSelector('wallet-language-item')).contains('Afrikaans').click({ force: true })
|
||||||
cy.location('hash').should('match', /\?lng=af-ZA$/)
|
cy.location('search').should('match', /\?lng=af-ZA$/)
|
||||||
cy.contains('Uniswap available in: English')
|
cy.contains('Uniswap available in: English')
|
||||||
|
|
||||||
cy.get(getTestSelector('wallet-language-item')).contains('English').click({ force: true })
|
cy.get(getTestSelector('wallet-language-item')).contains('English').click({ force: true })
|
||||||
cy.location('hash').should('match', /\?lng=en-US$/)
|
cy.location('search').should('match', /\?lng=en-US$/)
|
||||||
cy.contains('Uniswap available in: English').should('not.exist')
|
cy.contains('Uniswap available in: English').should('not.exist')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ describe('translations', () => {
|
|||||||
cy.get(getTestSelector('web3-status-connected')).click()
|
cy.get(getTestSelector('web3-status-connected')).click()
|
||||||
cy.get(getTestSelector('wallet-settings')).click()
|
cy.get(getTestSelector('wallet-settings')).click()
|
||||||
cy.get(getTestSelector('wallet-language-item')).contains('français').click({ force: true })
|
cy.get(getTestSelector('wallet-language-item')).contains('français').click({ force: true })
|
||||||
cy.location('hash').should('match', /\?lng=fr-FR$/)
|
cy.location('search').should('match', /\?lng=fr-FR$/)
|
||||||
cy.contains('Échanger')
|
cy.contains('Échanger')
|
||||||
cy.contains('Uniswap disponible en : English')
|
cy.contains('Uniswap disponible en : English')
|
||||||
})
|
})
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
"name": "@uniswap/interface",
|
"name": "@uniswap/interface",
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"description": "Uniswap Interface",
|
"description": "Uniswap Interface",
|
||||||
"homepage": ".",
|
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ajv": "node scripts/compile-ajv-validators.js",
|
"ajv": "node scripts/compile-ajv-validators.js",
|
||||||
@ -94,7 +93,6 @@
|
|||||||
"@types/react": "^18.0.15",
|
"@types/react": "^18.0.15",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-redux": "^7.1.24",
|
"@types/react-redux": "^7.1.24",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
|
||||||
"@types/react-table": "^7.7.12",
|
"@types/react-table": "^7.7.12",
|
||||||
"@types/react-virtualized-auto-sizer": "^1.0.0",
|
"@types/react-virtualized-auto-sizer": "^1.0.0",
|
||||||
"@types/react-window": "^1.8.2",
|
"@types/react-window": "^1.8.2",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
|
import { useHref } from 'react-router-dom'
|
||||||
import { useCloseModal, useModalIsOpen } from 'state/application/hooks'
|
import { useCloseModal, useModalIsOpen } from 'state/application/hooks'
|
||||||
import { ApplicationModal } from 'state/application/reducer'
|
import { ApplicationModal } from 'state/application/reducer'
|
||||||
import styled, { useTheme } from 'styled-components/macro'
|
import styled, { useTheme } from 'styled-components/macro'
|
||||||
@ -79,6 +80,8 @@ export default function FiatOnrampModal() {
|
|||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
const swapUrl = useHref('/swap')
|
||||||
|
|
||||||
const fetchSignedIframeUrl = useCallback(async () => {
|
const fetchSignedIframeUrl = useCallback(async () => {
|
||||||
if (!account) {
|
if (!account) {
|
||||||
setError('Please connect an account before making a purchase.')
|
setError('Please connect an account before making a purchase.')
|
||||||
@ -98,7 +101,7 @@ export default function FiatOnrampModal() {
|
|||||||
theme: isDarkMode ? 'dark' : 'light',
|
theme: isDarkMode ? 'dark' : 'light',
|
||||||
colorCode: theme.accentAction,
|
colorCode: theme.accentAction,
|
||||||
defaultCurrencyCode: 'eth',
|
defaultCurrencyCode: 'eth',
|
||||||
redirectUrl: 'https://app.uniswap.org/#/swap',
|
redirectUrl: swapUrl,
|
||||||
walletAddresses: JSON.stringify(
|
walletAddresses: JSON.stringify(
|
||||||
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
|
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
|
||||||
(acc, currencyCode) => ({
|
(acc, currencyCode) => ({
|
||||||
@ -118,7 +121,7 @@ export default function FiatOnrampModal() {
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}, [account, isDarkMode, theme.accentAction])
|
}, [account, isDarkMode, swapUrl, theme.accentAction])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSignedIframeUrl()
|
fetchSignedIframeUrl()
|
||||||
|
@ -343,7 +343,7 @@ exports[`LoadedRow.tsx renders a row 1`] = `
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c0"
|
class="c0"
|
||||||
href="#/tokens/ethereum/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
href="/tokens/ethereum/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c1"
|
class="c1"
|
||||||
|
@ -12,8 +12,9 @@ import { StrictMode } from 'react'
|
|||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query'
|
import { QueryClient, QueryClientProvider } from 'react-query'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { HashRouter } from 'react-router-dom'
|
import { BrowserRouter, HashRouter } from 'react-router-dom'
|
||||||
import { SystemThemeUpdater } from 'theme/components/ThemeToggle'
|
import { SystemThemeUpdater } from 'theme/components/ThemeToggle'
|
||||||
|
import { isBrowserRouterEnabled } from 'utils/env'
|
||||||
|
|
||||||
import Web3Provider from './components/Web3Provider'
|
import Web3Provider from './components/Web3Provider'
|
||||||
import { LanguageProvider } from './i18n'
|
import { LanguageProvider } from './i18n'
|
||||||
@ -51,12 +52,14 @@ const queryClient = new QueryClient()
|
|||||||
|
|
||||||
const container = document.getElementById('root') as HTMLElement
|
const container = document.getElementById('root') as HTMLElement
|
||||||
|
|
||||||
|
const Router = isBrowserRouterEnabled() ? BrowserRouter : HashRouter
|
||||||
|
|
||||||
createRoot(container).render(
|
createRoot(container).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<FeatureFlagsProvider>
|
<FeatureFlagsProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<HashRouter>
|
<Router>
|
||||||
<LanguageProvider>
|
<LanguageProvider>
|
||||||
<Web3Provider>
|
<Web3Provider>
|
||||||
<ApolloProvider client={apolloClient}>
|
<ApolloProvider client={apolloClient}>
|
||||||
@ -70,7 +73,7 @@ createRoot(container).render(
|
|||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
</Web3Provider>
|
</Web3Provider>
|
||||||
</LanguageProvider>
|
</LanguageProvider>
|
||||||
</HashRouter>
|
</Router>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</FeatureFlagsProvider>
|
</FeatureFlagsProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
|
@ -95,7 +95,7 @@ const ActionButton = ({
|
|||||||
<StyledActionButton
|
<StyledActionButton
|
||||||
selected={isSelected}
|
selected={isSelected}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
onClick={(e: React.MouseEvent) => (isDisabled ? undefined : clickActionButton(e))}
|
onClick={(e) => (isDisabled ? undefined : clickActionButton(e))}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</StyledActionButton>
|
</StyledActionButton>
|
||||||
|
@ -38,6 +38,7 @@ export const eventRow = style([
|
|||||||
borderBottomColor: 'backgroundOutline',
|
borderBottomColor: 'backgroundOutline',
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
textDecoration: 'none',
|
||||||
height: '84px',
|
height: '84px',
|
||||||
':hover': {
|
':hover': {
|
||||||
background: themeVars.colors.backgroundSurface,
|
background: themeVars.colors.backgroundSurface,
|
||||||
|
@ -5,10 +5,11 @@ import { Box } from 'nft/components/Box'
|
|||||||
import { Column, Row } from 'nft/components/Flex'
|
import { Column, Row } from 'nft/components/Flex'
|
||||||
import { themeVars, vars } from 'nft/css/sprinkles.css'
|
import { themeVars, vars } from 'nft/css/sprinkles.css'
|
||||||
import { useBag, useIsMobile } from 'nft/hooks'
|
import { useBag, useIsMobile } from 'nft/hooks'
|
||||||
import { ActivityEvent, ActivityEventType } from 'nft/types'
|
import { ActivityEventType } from 'nft/types'
|
||||||
import { fetchPrice } from 'nft/utils/fetchPrice'
|
import { fetchPrice } from 'nft/utils/fetchPrice'
|
||||||
import { useCallback, useEffect, useReducer, useState } from 'react'
|
import { useCallback, useEffect, useReducer, useState } from 'react'
|
||||||
import InfiniteScroll from 'react-infinite-scroll-component'
|
import InfiniteScroll from 'react-infinite-scroll-component'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
import styled from 'styled-components/macro'
|
import styled from 'styled-components/macro'
|
||||||
import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
||||||
|
|
||||||
@ -60,8 +61,6 @@ export const reduceFilters = (state: typeof initialFilterState, action: { eventT
|
|||||||
return { ...state, [action.eventType]: !state[action.eventType] }
|
return { ...state, [action.eventType]: !state[action.eventType] }
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseHref = (event: ActivityEvent) => `/#/nfts/asset/${event.collectionAddress}/${event.tokenId}?origin=activity`
|
|
||||||
|
|
||||||
export const Activity = ({ contractAddress, rarityVerified, collectionName, chainId }: ActivityProps) => {
|
export const Activity = ({ contractAddress, rarityVerified, collectionName, chainId }: ActivityProps) => {
|
||||||
const [activeFilters, filtersDispatch] = useReducer(reduceFilters, initialFilterState)
|
const [activeFilters, filtersDispatch] = useReducer(reduceFilters, initialFilterState)
|
||||||
|
|
||||||
@ -138,9 +137,11 @@ export const Activity = ({ contractAddress, rarityVerified, collectionName, chai
|
|||||||
(event, i) =>
|
(event, i) =>
|
||||||
event.eventType && (
|
event.eventType && (
|
||||||
<Box
|
<Box
|
||||||
as="a"
|
as={Link}
|
||||||
data-testid="nft-activity-row"
|
data-testid="nft-activity-row"
|
||||||
href={baseHref(event)}
|
// @ts-ignore Box component is not typed properly to typecheck
|
||||||
|
// custom components' props and will incorrectly report `to` as invalid
|
||||||
|
to={`/nfts/asset/${event.collectionAddress}/${event.tokenId}?origin=activity`}
|
||||||
className={styles.eventRow}
|
className={styles.eventRow}
|
||||||
key={i}
|
key={i}
|
||||||
>
|
>
|
||||||
|
@ -309,7 +309,7 @@ exports[`NftCard renders correctly 1`] = `
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c1"
|
class="c1"
|
||||||
href="#/nfts/asset/0xed5af388653567af2f388e6224dc7c4b3241c544/3318?origin=collection"
|
href="/nfts/asset/0xed5af388653567af2f388e6224dc7c4b3241c544/3318?origin=collection"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c2"
|
class="c2"
|
||||||
|
@ -106,6 +106,14 @@ const LazyLoadSpinner = () => (
|
|||||||
</SpinnerSVG>
|
</SpinnerSVG>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const RedirectHashToPath = ({ children }: { children: JSX.Element }) => {
|
||||||
|
const { hash } = useLocation()
|
||||||
|
if (hash) {
|
||||||
|
return <Navigate to={hash.replace('#', '')} replace />
|
||||||
|
}
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const isLoaded = useFeatureFlagsIsLoaded()
|
const isLoaded = useFeatureFlagsIsLoaded()
|
||||||
const [shouldDisableNFTRoutes, setShouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom)
|
const [shouldDisableNFTRoutes, setShouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom)
|
||||||
@ -209,7 +217,16 @@ export default function App() {
|
|||||||
<Suspense fallback={<Loader />}>
|
<Suspense fallback={<Loader />}>
|
||||||
{isLoaded ? (
|
{isLoaded ? (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Landing />} />
|
<Route
|
||||||
|
path="/"
|
||||||
|
element={
|
||||||
|
// if react-router-dom matches "/" with window.location.hash defined, it means that we're
|
||||||
|
// using BrowserRouter and can safely redirect to a path route
|
||||||
|
<RedirectHashToPath>
|
||||||
|
<Landing />
|
||||||
|
</RedirectHashToPath>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route path="tokens" element={<Tokens />}>
|
<Route path="tokens" element={<Tokens />}>
|
||||||
<Route path=":chainName" />
|
<Route path=":chainName" />
|
||||||
|
@ -1741,7 +1741,7 @@ exports[`disable nft on landing page does not render nft information and card 1`
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c2"
|
class="c2"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c3"
|
class="c3"
|
||||||
@ -2031,7 +2031,7 @@ exports[`disable nft on landing page does not render nft information and card 1`
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c2 c25 c56 c57"
|
class="c2 c25 c56 c57"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
class="0 c58"
|
class="0 c58"
|
||||||
@ -2098,7 +2098,7 @@ exports[`disable nft on landing page does not render nft information and card 1`
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c64"
|
class="c64"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c65"
|
class="c65"
|
||||||
@ -2178,7 +2178,7 @@ exports[`disable nft on landing page does not render nft information and card 1`
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="c70"
|
class="c70"
|
||||||
href="#/pools"
|
href="/pools"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c65"
|
class="c65"
|
||||||
@ -2363,19 +2363,19 @@ exports[`disable nft on landing page does not render nft information and card 1`
|
|||||||
</span>
|
</span>
|
||||||
<a
|
<a
|
||||||
class="1 c94 c95"
|
class="1 c94 c95"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
Swap
|
Swap
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="1 c94 c95"
|
class="1 c94 c95"
|
||||||
href="#/tokens"
|
href="/tokens"
|
||||||
>
|
>
|
||||||
Tokens
|
Tokens
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="1 c94 c95"
|
class="1 c94 c95"
|
||||||
href="#/pools"
|
href="/pools"
|
||||||
>
|
>
|
||||||
Pools
|
Pools
|
||||||
</a>
|
</a>
|
||||||
@ -4315,7 +4315,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c2"
|
class="c2"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c3"
|
class="c3"
|
||||||
@ -4605,7 +4605,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c2 c25 c56 c57"
|
class="c2 c25 c56 c57"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
class="0 c58"
|
class="0 c58"
|
||||||
@ -4672,7 +4672,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="c64"
|
class="c64"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c65"
|
class="c65"
|
||||||
@ -4698,7 +4698,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="c69"
|
class="c69"
|
||||||
href="#/nfts"
|
href="/nfts"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c65"
|
class="c65"
|
||||||
@ -4778,7 +4778,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="c71"
|
class="c71"
|
||||||
href="#/pools"
|
href="/pools"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c65"
|
class="c65"
|
||||||
@ -4963,25 +4963,25 @@ exports[`disable nft on landing page renders nft information and card 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
<a
|
<a
|
||||||
class="1 c95 c96"
|
class="1 c95 c96"
|
||||||
href="#/swap"
|
href="/swap"
|
||||||
>
|
>
|
||||||
Swap
|
Swap
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="1 c95 c96"
|
class="1 c95 c96"
|
||||||
href="#/tokens"
|
href="/tokens"
|
||||||
>
|
>
|
||||||
Tokens
|
Tokens
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="1 c95 c96"
|
class="1 c95 c96"
|
||||||
href="#/nfts"
|
href="/nfts"
|
||||||
>
|
>
|
||||||
NFTs
|
NFTs
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="1 c95 c96"
|
class="1 c95 c96"
|
||||||
href="#/pools"
|
href="/pools"
|
||||||
>
|
>
|
||||||
Pools
|
Pools
|
||||||
</a>
|
</a>
|
||||||
|
@ -3,7 +3,7 @@ import type { TransactionResponse } from '@ethersproject/providers'
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { InterfacePageName } from '@uniswap/analytics-events'
|
import { InterfacePageName } from '@uniswap/analytics-events'
|
||||||
import { formatPrice, NumberType } from '@uniswap/conedison/format'
|
import { formatPrice, NumberType } from '@uniswap/conedison/format'
|
||||||
import { ChainId, Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
|
||||||
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
import { Trace } from 'analytics'
|
import { Trace } from 'analytics'
|
||||||
@ -30,12 +30,12 @@ import { useV3PositionFees } from 'hooks/useV3PositionFees'
|
|||||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||||
import { useSingleCallResult } from 'lib/hooks/multicall'
|
import { useSingleCallResult } from 'lib/hooks/multicall'
|
||||||
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
|
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
|
||||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
import { PropsWithChildren, useCallback, useMemo, useRef, useState } from 'react'
|
||||||
import { Link, useParams } from 'react-router-dom'
|
import { Link, useParams } from 'react-router-dom'
|
||||||
import { Bound } from 'state/mint/v3/actions'
|
import { Bound } from 'state/mint/v3/actions'
|
||||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||||
import styled, { useTheme } from 'styled-components/macro'
|
import styled, { useTheme } from 'styled-components/macro'
|
||||||
import { ExternalLink, HideExtraSmall, HideSmall, ThemedText } from 'theme'
|
import { ExternalLink, HideExtraSmall, HideSmall, StyledRouterLink, ThemedText } from 'theme'
|
||||||
import { currencyId } from 'utils/currencyId'
|
import { currencyId } from 'utils/currencyId'
|
||||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||||
import { formatTickPrice } from 'utils/formatTickPrice'
|
import { formatTickPrice } from 'utils/formatTickPrice'
|
||||||
@ -52,15 +52,6 @@ import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
|||||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||||
import { LoadingRows } from './styleds'
|
import { LoadingRows } from './styleds'
|
||||||
|
|
||||||
const getTokenLink = (chainId: ChainId, address: string) => {
|
|
||||||
if (isGqlSupportedChain(chainId)) {
|
|
||||||
const chainName = CHAIN_IDS_TO_NAMES[chainId]
|
|
||||||
return `${window.location.origin}/#/tokens/${chainName}/${address}`
|
|
||||||
} else {
|
|
||||||
return getExplorerLink(chainId, address, ExplorerDataType.TOKEN)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const PositionPageButtonPrimary = styled(ButtonPrimary)`
|
const PositionPageButtonPrimary = styled(ButtonPrimary)`
|
||||||
width: 228px;
|
width: 228px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
@ -210,17 +201,31 @@ function CurrentPriceCard({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TokenLink = ({
|
||||||
|
children,
|
||||||
|
chainId,
|
||||||
|
address,
|
||||||
|
}: PropsWithChildren<{ chainId: keyof typeof CHAIN_IDS_TO_NAMES; address: string }>) => {
|
||||||
|
const chainName = CHAIN_IDS_TO_NAMES[chainId]
|
||||||
|
return <StyledRouterLink to={`/tokens/${chainName}/${address}`}>{children}</StyledRouterLink>
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExternalTokenLink = ({ children, chainId, address }: PropsWithChildren<{ chainId: number; address: string }>) => {
|
||||||
|
return <ExternalLink href={getExplorerLink(chainId, address, ExplorerDataType.TOKEN)}>{children}</ExternalLink>
|
||||||
|
}
|
||||||
|
|
||||||
function LinkedCurrency({ chainId, currency }: { chainId?: number; currency?: Currency }) {
|
function LinkedCurrency({ chainId, currency }: { chainId?: number; currency?: Currency }) {
|
||||||
const address = (currency as Token)?.address
|
const address = (currency as Token)?.address
|
||||||
|
|
||||||
if (typeof chainId === 'number' && address) {
|
if (typeof chainId === 'number' && address) {
|
||||||
|
const Link = isGqlSupportedChain(chainId) ? TokenLink : ExternalTokenLink
|
||||||
return (
|
return (
|
||||||
<ExternalLink href={getTokenLink(chainId, address)}>
|
<Link chainId={chainId} address={address}>
|
||||||
<RowFixed>
|
<RowFixed>
|
||||||
<CurrencyLogo currency={currency} size="20px" style={{ marginRight: '0.5rem' }} />
|
<CurrencyLogo currency={currency} size="20px" style={{ marginRight: '0.5rem' }} />
|
||||||
<ThemedText.DeprecatedMain>{currency?.symbol} ↗</ThemedText.DeprecatedMain>
|
<ThemedText.DeprecatedMain>{currency?.symbol} ↗</ThemedText.DeprecatedMain>
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
</ExternalLink>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,15 +17,15 @@ describe('document', () => {
|
|||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'example.com', pathname: '' } }, false],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'example.com', pathname: '' } }, false],
|
||||||
[{ request: {}, url: { hostname: 'app.uniswap.org', pathname: '' } }, false],
|
[{ request: {}, url: { hostname: 'app.uniswap.org', pathname: '' } }, false],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap.org', pathname: '' } }, true],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap.org', pathname: '' } }, true],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap.org', pathname: '/#/swap' } }, true],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap.org', pathname: '/swap' } }, true],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap.org', pathname: '/asset.gif' } }, false],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap.org', pathname: '/asset.gif' } }, false],
|
||||||
[{ request: {}, url: { hostname: 'app.uniswap-staging.org', pathname: '' } }, false],
|
[{ request: {}, url: { hostname: 'app.uniswap-staging.org', pathname: '' } }, false],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap-staging.org', pathname: '' } }, true],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap-staging.org', pathname: '' } }, true],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap-staging.org', pathname: '/#/swap' } }, true],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap-staging.org', pathname: '/swap' } }, true],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap-staging.org', pathname: '/asset.gif' } }, false],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'app.uniswap-staging.org', pathname: '/asset.gif' } }, false],
|
||||||
[{ request: {}, url: { hostname: 'localhost', pathname: '' } }, false],
|
[{ request: {}, url: { hostname: 'localhost', pathname: '' } }, false],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'localhost', pathname: '' } }, true],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'localhost', pathname: '' } }, true],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'localhost', pathname: '/#/swap' } }, true],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'localhost', pathname: '/swap' } }, true],
|
||||||
[{ request: { mode: 'navigate' }, url: { hostname: 'localhost', pathname: '/asset.gif' } }, false],
|
[{ request: { mode: 'navigate' }, url: { hostname: 'localhost', pathname: '/asset.gif' } }, false],
|
||||||
] as [RouteMatchCallbackOptions, boolean][]
|
] as [RouteMatchCallbackOptions, boolean][]
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import { en } from 'make-plural/plurals'
|
|||||||
import { ReactElement, ReactNode } from 'react'
|
import { ReactElement, ReactNode } from 'react'
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query'
|
import { QueryClient, QueryClientProvider } from 'react-query'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { HashRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import store from 'state'
|
import store from 'state'
|
||||||
import ThemeProvider from 'theme'
|
import ThemeProvider from 'theme'
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ const WithProviders = ({ children }: { children?: ReactNode }) => {
|
|||||||
<MockedI18nProvider>
|
<MockedI18nProvider>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<HashRouter>
|
<BrowserRouter>
|
||||||
{/*
|
{/*
|
||||||
* Web3Provider is mocked through setupTests.ts
|
* Web3Provider is mocked through setupTests.ts
|
||||||
* To test behavior that depends on Web3Provider, use jest.unmock('@web3-react/core')
|
* To test behavior that depends on Web3Provider, use jest.unmock('@web3-react/core')
|
||||||
@ -40,7 +40,7 @@ const WithProviders = ({ children }: { children?: ReactNode }) => {
|
|||||||
<ThemeProvider>{children}</ThemeProvider>
|
<ThemeProvider>{children}</ThemeProvider>
|
||||||
</BlockNumberProvider>
|
</BlockNumberProvider>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
</HashRouter>
|
</BrowserRouter>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
</MockedI18nProvider>
|
</MockedI18nProvider>
|
||||||
|
@ -103,7 +103,7 @@ describe('trace', () => {
|
|||||||
const errorEvent: ErrorEvent = {
|
const errorEvent: ErrorEvent = {
|
||||||
type: undefined,
|
type: undefined,
|
||||||
request: {
|
request: {
|
||||||
url: 'https://app.uniswap.org/#/pools',
|
url: 'https://app.uniswap.org/pools',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const eventHint: EventHint = {}
|
const eventHint: EventHint = {}
|
||||||
@ -114,7 +114,7 @@ describe('trace', () => {
|
|||||||
const errorEvent: ErrorEvent = {
|
const errorEvent: ErrorEvent = {
|
||||||
type: undefined,
|
type: undefined,
|
||||||
request: {
|
request: {
|
||||||
url: 'https://app.uniswap.org/#',
|
url: 'https://app.uniswap.org/',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const eventHint: EventHint = {}
|
const eventHint: EventHint = {}
|
||||||
|
@ -23,6 +23,25 @@ export function isAppUniswapStagingOrg({ hostname }: { hostname: string }): bool
|
|||||||
return hostname === 'app.uniswap-staging.org'
|
return hostname === 'app.uniswap-staging.org'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isBrowserRouterEnabled(): boolean {
|
||||||
|
if (isProductionEnv()) {
|
||||||
|
if (
|
||||||
|
isAppUniswapOrg(window.location) ||
|
||||||
|
isAppUniswapStagingOrg(window.location) ||
|
||||||
|
// Cypress tests
|
||||||
|
isLocalhost(window.location)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLocalhost({ hostname }: { hostname: string }): boolean {
|
||||||
|
return hostname === 'localhost'
|
||||||
|
}
|
||||||
|
|
||||||
export function isSentryEnabled(): boolean {
|
export function isSentryEnabled(): boolean {
|
||||||
// Disable in e2e test environments
|
// Disable in e2e test environments
|
||||||
if (isStagingEnv() && !isAppUniswapStagingOrg(window.location)) return false
|
if (isStagingEnv() && !isAppUniswapStagingOrg(window.location)) return false
|
||||||
|
22
yarn.lock
22
yarn.lock
@ -5559,11 +5559,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/history@*", "@types/history@^4.7.11":
|
|
||||||
version "4.7.11"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
|
|
||||||
integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
|
|
||||||
|
|
||||||
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
|
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
||||||
@ -5766,23 +5761,6 @@
|
|||||||
hoist-non-react-statics "^3.3.0"
|
hoist-non-react-statics "^3.3.0"
|
||||||
redux "^4.0.0"
|
redux "^4.0.0"
|
||||||
|
|
||||||
"@types/react-router-dom@^5.3.3":
|
|
||||||
version "5.3.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
|
|
||||||
integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==
|
|
||||||
dependencies:
|
|
||||||
"@types/history" "^4.7.11"
|
|
||||||
"@types/react" "*"
|
|
||||||
"@types/react-router" "*"
|
|
||||||
|
|
||||||
"@types/react-router@*":
|
|
||||||
version "5.1.16"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.16.tgz#f3ba045fb96634e38b21531c482f9aeb37608a99"
|
|
||||||
integrity sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg==
|
|
||||||
dependencies:
|
|
||||||
"@types/history" "*"
|
|
||||||
"@types/react" "*"
|
|
||||||
|
|
||||||
"@types/react-table@^7.7.12":
|
"@types/react-table@^7.7.12":
|
||||||
version "7.7.12"
|
version "7.7.12"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-7.7.12.tgz#628011d3cb695b07c678704a61f2f1d5b8e567fd"
|
resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-7.7.12.tgz#628011d3cb695b07c678704a61f2f1d5b8e567fd"
|
||||||
|
Loading…
Reference in New Issue
Block a user