diff --git a/README.md b/README.md index 9c850bf342..959e9c5eae 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,10 @@ Other things to note: The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2. -- Swap on Uniswap V2: -- View V2 liquidity: -- Add V2 liquidity: -- Migrate V2 liquidity to V3: +- Swap on Uniswap V2: +- View V2 liquidity: +- Add V2 liquidity: +- Migrate V2 liquidity to V3: ## Accessing Uniswap V1 diff --git a/cypress/e2e/nfts.test.ts b/cypress/e2e/nfts.test.ts index cd882b5e1f..22b08a8b61 100644 --- a/cypress/e2e/nfts.test.ts +++ b/cypress/e2e/nfts.test.ts @@ -12,7 +12,7 @@ describe('Testing nfts', () => { }) 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-filter-buy-now')).should('not.exist') cy.get(getTestSelector('nft-filter')).first().click() @@ -20,13 +20,13 @@ describe('Testing nfts', () => { }) 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-row')).should('exist') }) 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-collection-filter-buy-now')).click() cy.get(getTestSelector('nft-collection-asset')).first().click() @@ -37,7 +37,7 @@ describe('Testing nfts', () => { }) 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-collection-filter-buy-now')).click() cy.get(getTestSelector('nft-collection-asset')).first().click() diff --git a/cypress/e2e/token-explore.test.ts b/cypress/e2e/token-explore.test.ts index d41bd510c8..a418ac6b23 100644 --- a/cypress/e2e/token-explore.test.ts +++ b/cypress/e2e/token-explore.test.ts @@ -69,5 +69,8 @@ describe('Token explore', () => { cy.get(getTestSelector('tokens-network-filter-selected')).click() cy.get(getTestSelector('tokens-network-filter-option-optimism')).click() 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') }) }) diff --git a/cypress/e2e/universal-search.test.ts b/cypress/e2e/universal-search.test.ts index aaddb41f9d..e1841a8e91 100644 --- a/cypress/e2e/universal-search.test.ts +++ b/cypress/e2e/universal-search.test.ts @@ -30,7 +30,7 @@ describe('Universal search bar', () => { .and('contain.text', '$') .and('contain.text', '%') .click() - cy.location('pathname').should('equal', '/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984') + cy.location('hash').should('equal', '#/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984') openSearch() cy.get(getTestSelector('searchbar-dropdown')) diff --git a/cypress/e2e/wallet-dropdown.test.ts b/cypress/e2e/wallet-dropdown.test.ts index 0df0645895..24d711289b 100644 --- a/cypress/e2e/wallet-dropdown.test.ts +++ b/cypress/e2e/wallet-dropdown.test.ts @@ -32,11 +32,11 @@ describe('Wallet Dropdown', () => { } cy.get(getTestSelector('wallet-language-item')).contains('Afrikaans').click({ force: true }) - cy.location('search').should('match', /\?lng=af-ZA$/) + cy.location('hash').should('match', /\?lng=af-ZA$/) cy.contains('Uniswap available in: English') cy.get(getTestSelector('wallet-language-item')).contains('English').click({ force: true }) - cy.location('search').should('match', /\?lng=en-US$/) + cy.location('hash').should('match', /\?lng=en-US$/) cy.contains('Uniswap available in: English').should('not.exist') }) } diff --git a/cypress/staging/t9n.test.ts b/cypress/staging/t9n.test.ts index d59fd7ec7d..16dbc1da76 100644 --- a/cypress/staging/t9n.test.ts +++ b/cypress/staging/t9n.test.ts @@ -12,7 +12,7 @@ describe('translations', () => { cy.get(getTestSelector('web3-status-connected')).click() cy.get(getTestSelector('wallet-settings')).click() cy.get(getTestSelector('wallet-language-item')).contains('français').click({ force: true }) - cy.location('search').should('match', /\?lng=fr-FR$/) + cy.location('hash').should('match', /\?lng=fr-FR$/) cy.contains('Échanger') cy.contains('Uniswap disponible en : English') }) diff --git a/package.json b/package.json index da4241d1fc..cc24a06232 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6", "@types/react-redux": "^7.1.24", + "@types/react-router-dom": "^5.3.3", "@types/react-table": "^7.7.12", "@types/react-virtualized-auto-sizer": "^1.0.0", "@types/react-window": "^1.8.2", diff --git a/src/components/FiatOnrampModal/index.tsx b/src/components/FiatOnrampModal/index.tsx index 73081fc7b5..e40d61f3f2 100644 --- a/src/components/FiatOnrampModal/index.tsx +++ b/src/components/FiatOnrampModal/index.tsx @@ -1,7 +1,6 @@ import { Trans } from '@lingui/macro' import { useWeb3React } from '@web3-react/core' import { useCallback, useEffect, useState } from 'react' -import { useHref } from 'react-router-dom' import { useCloseModal, useModalIsOpen } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' import styled, { useTheme } from 'styled-components' @@ -80,8 +79,6 @@ export default function FiatOnrampModal() { const [error, setError] = useState(null) const [loading, setLoading] = useState(false) - const swapUrl = useHref('/swap') - const fetchSignedIframeUrl = useCallback(async () => { if (!account) { setError('Please connect an account before making a purchase.') @@ -101,7 +98,7 @@ export default function FiatOnrampModal() { theme: isDarkMode ? 'dark' : 'light', colorCode: theme.accentAction, defaultCurrencyCode: 'eth', - redirectUrl: swapUrl, + redirectUrl: 'https://app.uniswap.org/#/swap', walletAddresses: JSON.stringify( MOONPAY_SUPPORTED_CURRENCY_CODES.reduce( (acc, currencyCode) => ({ @@ -121,7 +118,7 @@ export default function FiatOnrampModal() { } finally { setLoading(false) } - }, [account, isDarkMode, swapUrl, theme.accentAction]) + }, [account, isDarkMode, theme.accentAction]) useEffect(() => { fetchSignedIframeUrl() diff --git a/src/components/Tokens/TokenTable/__snapshots__/TokenRow.test.tsx.snap b/src/components/Tokens/TokenTable/__snapshots__/TokenRow.test.tsx.snap index aaafeca785..8bcfd07831 100644 --- a/src/components/Tokens/TokenTable/__snapshots__/TokenRow.test.tsx.snap +++ b/src/components/Tokens/TokenTable/__snapshots__/TokenRow.test.tsx.snap @@ -343,7 +343,7 @@ exports[`LoadedRow.tsx renders a row 1`] = ` >
- + @@ -73,7 +70,7 @@ createRoot(container).render( - + diff --git a/src/nft/components/card/containers.tsx b/src/nft/components/card/containers.tsx index a97db697d1..6db8870a8e 100644 --- a/src/nft/components/card/containers.tsx +++ b/src/nft/components/card/containers.tsx @@ -95,7 +95,7 @@ const ActionButton = ({ (isDisabled ? undefined : clickActionButton(e))} + onClick={(e: React.MouseEvent) => (isDisabled ? undefined : clickActionButton(e))} > {children} diff --git a/src/nft/components/collection/Activity.css.ts b/src/nft/components/collection/Activity.css.ts index d405f380ef..64d9161659 100644 --- a/src/nft/components/collection/Activity.css.ts +++ b/src/nft/components/collection/Activity.css.ts @@ -38,7 +38,6 @@ export const eventRow = style([ borderBottomColor: 'backgroundOutline', }), { - textDecoration: 'none', height: '84px', ':hover': { background: themeVars.colors.backgroundSurface, diff --git a/src/nft/components/collection/Activity.tsx b/src/nft/components/collection/Activity.tsx index dcbff204e3..e99a043b47 100644 --- a/src/nft/components/collection/Activity.tsx +++ b/src/nft/components/collection/Activity.tsx @@ -5,11 +5,10 @@ import { Box } from 'nft/components/Box' import { Column, Row } from 'nft/components/Flex' import { themeVars, vars } from 'nft/css/sprinkles.css' import { useBag, useIsMobile } from 'nft/hooks' -import { ActivityEventType } from 'nft/types' +import { ActivityEvent, ActivityEventType } from 'nft/types' import { fetchPrice } from 'nft/utils/fetchPrice' import { useCallback, useEffect, useReducer, useState } from 'react' import InfiniteScroll from 'react-infinite-scroll-component' -import { Link } from 'react-router-dom' import styled from 'styled-components' import { useIsDarkMode } from 'theme/components/ThemeToggle' @@ -61,6 +60,8 @@ export const reduceFilters = (state: typeof initialFilterState, action: { eventT 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) => { const [activeFilters, filtersDispatch] = useReducer(reduceFilters, initialFilterState) @@ -137,11 +138,9 @@ export const Activity = ({ contractAddress, rarityVerified, collectionName, chai (event, i) => event.eventType && ( diff --git a/src/nft/components/collection/__snapshots__/CollectionAsset.test.tsx.snap b/src/nft/components/collection/__snapshots__/CollectionAsset.test.tsx.snap index 5c75dd2383..0a8359d14e 100644 --- a/src/nft/components/collection/__snapshots__/CollectionAsset.test.tsx.snap +++ b/src/nft/components/collection/__snapshots__/CollectionAsset.test.tsx.snap @@ -309,7 +309,7 @@ exports[`NftCard renders correctly 1`] = ` >
( ) -const RedirectHashToPath = ({ children }: { children: JSX.Element }) => { - const { hash } = useLocation() - if (hash) { - return - } - return children -} - export default function App() { const isLoaded = useFeatureFlagsIsLoaded() const [shouldDisableNFTRoutes, setShouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom) @@ -217,16 +209,7 @@ export default function App() { }> {isLoaded ? ( - - - - } - /> + } /> }> diff --git a/src/pages/Landing/__snapshots__/index.test.tsx.snap b/src/pages/Landing/__snapshots__/index.test.tsx.snap index a3508ea4c4..0327668195 100644 --- a/src/pages/Landing/__snapshots__/index.test.tsx.snap +++ b/src/pages/Landing/__snapshots__/index.test.tsx.snap @@ -1741,7 +1741,7 @@ exports[`disable nft on landing page does not render nft information and card 1` >

Swap Tokens Pools @@ -4315,7 +4315,7 @@ exports[`disable nft on landing page renders nft information and card 1`] = ` >

Swap Tokens NFTs Pools diff --git a/src/pages/Pool/PositionPage.tsx b/src/pages/Pool/PositionPage.tsx index 9cd36d2022..959ccf29c4 100644 --- a/src/pages/Pool/PositionPage.tsx +++ b/src/pages/Pool/PositionPage.tsx @@ -2,7 +2,7 @@ import { BigNumber } from '@ethersproject/bignumber' import type { TransactionResponse } from '@ethersproject/providers' import { Trans } from '@lingui/macro' import { InterfacePageName } from '@uniswap/analytics-events' -import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core' +import { ChainId, Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core' import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk' import { useWeb3React } from '@web3-react/core' import { Trace } from 'analytics' @@ -29,12 +29,12 @@ import { useV3PositionFees } from 'hooks/useV3PositionFees' import { useV3PositionFromTokenId } from 'hooks/useV3Positions' import { useSingleCallResult } from 'lib/hooks/multicall' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { PropsWithChildren, useCallback, useMemo, useRef, useState } from 'react' +import { useCallback, useMemo, useRef, useState } from 'react' import { Link, useParams } from 'react-router-dom' import { Bound } from 'state/mint/v3/actions' import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks' import styled, { useTheme } from 'styled-components' -import { ExternalLink, HideExtraSmall, HideSmall, StyledRouterLink, ThemedText } from 'theme' +import { ExternalLink, HideExtraSmall, HideSmall, ThemedText } from 'theme' import { currencyId } from 'utils/currencyId' import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' import { formatPrice, NumberType } from 'utils/formatNumbers' @@ -52,6 +52,15 @@ import { calculateGasMargin } from '../../utils/calculateGasMargin' import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink' import { LoadingRows } from './styled' +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)` width: 228px; height: 40px; @@ -201,31 +210,17 @@ 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 {children} -} - -const ExternalTokenLink = ({ children, chainId, address }: PropsWithChildren<{ chainId: number; address: string }>) => { - return {children} -} - function LinkedCurrency({ chainId, currency }: { chainId?: number; currency?: Currency }) { const address = (currency as Token)?.address if (typeof chainId === 'number' && address) { - const Link = isGqlSupportedChain(chainId) ? TokenLink : ExternalTokenLink return ( - + {currency?.symbol} ↗ - + ) } diff --git a/src/serviceWorker/document.test.ts b/src/serviceWorker/document.test.ts index 49d7636589..9d3f42e67b 100644 --- a/src/serviceWorker/document.test.ts +++ b/src/serviceWorker/document.test.ts @@ -17,15 +17,15 @@ describe('document', () => { [{ request: { mode: 'navigate' }, url: { hostname: 'example.com', 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: '/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: {}, 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: '/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: {}, url: { hostname: 'localhost', pathname: '' } }, false], [{ 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], ] as [RouteMatchCallbackOptions, boolean][] diff --git a/src/test-utils/render.tsx b/src/test-utils/render.tsx index 58feb5f976..dfa3265519 100644 --- a/src/test-utils/render.tsx +++ b/src/test-utils/render.tsx @@ -10,7 +10,7 @@ import { en } from 'make-plural/plurals' import { ReactElement, ReactNode } from 'react' import { QueryClient, QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' -import { BrowserRouter } from 'react-router-dom' +import { HashRouter } from 'react-router-dom' import store from 'state' import ThemeProvider from 'theme' @@ -30,7 +30,7 @@ const WithProviders = ({ children }: { children?: ReactNode }) => { - + {/* * Web3Provider is mocked through setupTests.ts * To test behavior that depends on Web3Provider, use jest.unmock('@web3-react/core') @@ -40,7 +40,7 @@ const WithProviders = ({ children }: { children?: ReactNode }) => { {children} - + diff --git a/src/tracing/trace.test.ts b/src/tracing/trace.test.ts index ffda5c5599..2d6da02e4a 100644 --- a/src/tracing/trace.test.ts +++ b/src/tracing/trace.test.ts @@ -103,7 +103,7 @@ describe('trace', () => { const errorEvent: ErrorEvent = { type: undefined, request: { - url: 'https://app.uniswap.org/pools', + url: 'https://app.uniswap.org/#/pools', }, } const eventHint: EventHint = {} @@ -114,7 +114,7 @@ describe('trace', () => { const errorEvent: ErrorEvent = { type: undefined, request: { - url: 'https://app.uniswap.org/', + url: 'https://app.uniswap.org/#', }, } const eventHint: EventHint = {} diff --git a/src/utils/env.ts b/src/utils/env.ts index 7c1fc20c29..c982606692 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -23,25 +23,6 @@ export function isAppUniswapStagingOrg({ hostname }: { hostname: string }): bool 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 { // Disable in e2e test environments if (isStagingEnv() && !isAppUniswapStagingOrg(window.location)) return false diff --git a/yarn.lock b/yarn.lock index 9744686e74..ebd07db900 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5635,6 +5635,11 @@ dependencies: "@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": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -5837,6 +5842,23 @@ hoist-non-react-statics "^3.3.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": version "7.7.12" resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-7.7.12.tgz#628011d3cb695b07c678704a61f2f1d5b8e567fd"