feat: add sitemap for app.uniswap.org (#7408)
* feat: add sitemap for app.uniswap.org * feat: script to update lastmod * fix: deps and snapshots * fix: use xml2js * fix: improve test and sitemap
This commit is contained in:
parent
bab8506919
commit
3ced65b8a4
@ -13,10 +13,11 @@
|
||||
"graphql:generate:thegraph": "graphql-codegen --config graphql.thegraph.codegen.config.ts",
|
||||
"graphql:generate": "yarn graphql:generate:data && yarn graphql:generate:thegraph",
|
||||
"graphql": "yarn graphql:fetch && yarn graphql:generate",
|
||||
"sitemap:generate": "node scripts/generate-sitemap.js",
|
||||
"i18n:extract": "lingui extract --locale en-US",
|
||||
"i18n:compile": "lingui compile",
|
||||
"i18n": "yarn i18n:extract --clean && yarn i18n:compile",
|
||||
"prepare": "concurrently \"npm:ajv\" \"npm:contracts\" \"npm:graphql\" \"npm:i18n\"",
|
||||
"prepare": "concurrently \"npm:ajv\" \"npm:contracts\" \"npm:graphql\" \"npm:i18n\" \"npm:sitemap:generate\"",
|
||||
"start": "craco start",
|
||||
"start:cloud": "NODE_OPTIONS=--dns-result-order=ipv4first PORT=3001 npx wrangler pages dev --compatibility-flags=nodejs_compat --compatibility-date=2023-08-01 --proxy=3001 --port=3000 -- yarn start",
|
||||
"build": "craco build",
|
||||
@ -114,6 +115,7 @@
|
||||
"@types/ua-parser-js": "^0.7.36",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/wcag-contrast": "^3.0.0",
|
||||
"@types/xml2js": "^0.4.12",
|
||||
"@uniswap/default-token-list": "^11.2.0",
|
||||
"@uniswap/eslint-config": "^1.2.0",
|
||||
"@vanilla-extract/jest-transform": "^1.1.1",
|
||||
@ -293,6 +295,7 @@
|
||||
"workbox-navigation-preload": "^6.1.0",
|
||||
"workbox-precaching": "^6.1.0",
|
||||
"workbox-routing": "^6.1.0",
|
||||
"xml2js": "^0.6.2",
|
||||
"zustand": "^4.3.6"
|
||||
},
|
||||
"engines": {
|
||||
|
19
public/sitemap.xml
Normal file
19
public/sitemap.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
<url loc="https://app.uniswap.org/" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="1"/>
|
||||
<url loc="https://app.uniswap.org/tokens" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.8"/>
|
||||
<url loc="https://app.uniswap.org/send" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/swap" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.9"/>
|
||||
<url loc="https://app.uniswap.org/pool/v2/find" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/pool/v2" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/pool" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/pools/v2/find" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/pools/v2" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/pools" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.7"/>
|
||||
<url loc="https://app.uniswap.org/add/v2" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/add" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/increase" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/migrate/v2" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/nfts" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
<url loc="https://app.uniswap.org/nfts/profile" lastmod="2023-10-05T17:48:32.538Z" changefreq="weekly" priority="0.6"/>
|
||||
</urlset>
|
25
scripts/generate-sitemap.js
Normal file
25
scripts/generate-sitemap.js
Normal file
@ -0,0 +1,25 @@
|
||||
/* eslint-env node */
|
||||
|
||||
const fs = require('fs')
|
||||
const { parseStringPromise, Builder } = require('xml2js')
|
||||
|
||||
fs.readFile('./public/sitemap.xml', 'utf8', async (err, data) => {
|
||||
try {
|
||||
const sitemap = await parseStringPromise(data)
|
||||
|
||||
const lastmodDate = new Date().toISOString()
|
||||
if (sitemap.urlset.url) {
|
||||
sitemap.urlset.url.forEach((url) => {
|
||||
url['$'].lastmod = lastmodDate
|
||||
})
|
||||
}
|
||||
const builder = new Builder()
|
||||
const xml = builder.buildObject(sitemap)
|
||||
fs.writeFile('./public/sitemap.xml', xml, (error) => {
|
||||
if (error) throw error
|
||||
console.log('Sitemap updated')
|
||||
})
|
||||
} catch {
|
||||
throw new Error('Error parsing sitemap.xml')
|
||||
}
|
||||
})
|
@ -5,51 +5,27 @@ import ErrorBoundary from 'components/ErrorBoundary'
|
||||
import Loader from 'components/Icons/LoadingSpinner'
|
||||
import NavBar, { PageTabs } from 'components/NavBar'
|
||||
import { useFeatureFlagsIsLoaded } from 'featureFlags'
|
||||
import { useInfoPoolPageEnabled } from 'featureFlags/flags/infoPoolPage'
|
||||
import { useAtom } from 'jotai'
|
||||
import { useBag } from 'nft/hooks/useBag'
|
||||
import { lazy, Suspense, useEffect, useLayoutEffect, useMemo, useState } from 'react'
|
||||
import { Navigate, Route, Routes, useLocation, useSearchParams } from 'react-router-dom'
|
||||
import { Route, Routes, useLocation, useSearchParams } from 'react-router-dom'
|
||||
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
|
||||
import { useRouterPreference } from 'state/user/hooks'
|
||||
import { StatsigProvider, StatsigUser } from 'statsig-react'
|
||||
import styled from 'styled-components'
|
||||
import { SpinnerSVG } from 'theme/components'
|
||||
import DarkModeQueryParamReader from 'theme/components/DarkModeQueryParamReader'
|
||||
import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
||||
import { flexRowNoWrap } from 'theme/styles'
|
||||
import { Z_INDEX } from 'theme/zIndex'
|
||||
import { STATSIG_DUMMY_KEY } from 'tracing'
|
||||
import { getEnvName, isBrowserRouterEnabled } from 'utils/env'
|
||||
import { getEnvName } from 'utils/env'
|
||||
import { getDownloadAppLink } from 'utils/openDownloadApp'
|
||||
import { getCurrentPageFromLocation } from 'utils/urlRoutes'
|
||||
import { getCLS, getFCP, getFID, getLCP, Metric } from 'web-vitals'
|
||||
|
||||
// High-traffic pages (index and /swap) should not be lazy-loaded.
|
||||
import Landing from './Landing'
|
||||
import Swap from './Swap'
|
||||
import { RouteDefinition, routes, useRouterConfig } from './RouteDefinitions'
|
||||
|
||||
const AppChrome = lazy(() => import('./AppChrome'))
|
||||
const NftExplore = lazy(() => import('nft/pages/explore'))
|
||||
const Collection = lazy(() => import('nft/pages/collection'))
|
||||
const Profile = lazy(() => import('nft/pages/profile'))
|
||||
const Asset = lazy(() => import('nft/pages/asset/Asset'))
|
||||
const AddLiquidity = lazy(() => import('pages/AddLiquidity'))
|
||||
const RedirectDuplicateTokenIds = lazy(() => import('pages/AddLiquidity/redirects'))
|
||||
const RedirectDuplicateTokenIdsV2 = lazy(() => import('pages/AddLiquidityV2/redirects'))
|
||||
const MigrateV2 = lazy(() => import('pages/MigrateV2'))
|
||||
const MigrateV2Pair = lazy(() => import('pages/MigrateV2/MigrateV2Pair'))
|
||||
const NotFound = lazy(() => import('pages/NotFound'))
|
||||
const Pool = lazy(() => import('pages/Pool'))
|
||||
const PositionPage = lazy(() => import('pages/Pool/PositionPage'))
|
||||
const PoolV2 = lazy(() => import('pages/Pool/v2'))
|
||||
const PoolDetails = lazy(() => import('pages/PoolDetails'))
|
||||
const PoolFinder = lazy(() => import('pages/PoolFinder'))
|
||||
const RemoveLiquidity = lazy(() => import('pages/RemoveLiquidity'))
|
||||
const RemoveLiquidityV3 = lazy(() => import('pages/RemoveLiquidity/V3'))
|
||||
const TokenDetails = lazy(() => import('pages/TokenDetails'))
|
||||
const Tokens = lazy(() => import('pages/Tokens'))
|
||||
const Vote = lazy(() => import('pages/Vote'))
|
||||
|
||||
const BodyWrapper = styled.div`
|
||||
display: flex;
|
||||
@ -93,32 +69,18 @@ const HeaderWrapper = styled.div<{ transparent?: boolean }>`
|
||||
z-index: ${Z_INDEX.dropdown};
|
||||
`
|
||||
|
||||
// this is the same svg defined in assets/images/blue-loader.svg
|
||||
// it is defined here because the remote asset may not have had time to load when this file is executing
|
||||
const LazyLoadSpinner = () => (
|
||||
<SpinnerSVG width="94" height="94" viewBox="0 0 94 94" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M92 47C92 22.1472 71.8528 2 47 2C22.1472 2 2 22.1472 2 47C2 71.8528 22.1472 92 47 92"
|
||||
stroke="#2172E5"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</SpinnerSVG>
|
||||
)
|
||||
|
||||
export default function App() {
|
||||
const isLoaded = useFeatureFlagsIsLoaded()
|
||||
const [shouldDisableNFTRoutes, setShouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom)
|
||||
const [, setShouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom)
|
||||
|
||||
const browserRouterEnabled = isBrowserRouterEnabled()
|
||||
const location = useLocation()
|
||||
const { hash, pathname } = location
|
||||
const { pathname } = location
|
||||
const currentPage = getCurrentPageFromLocation(pathname)
|
||||
const isDarkMode = useIsDarkMode()
|
||||
const [routerPreference] = useRouterPreference()
|
||||
const [scrolledState, setScrolledState] = useState(false)
|
||||
const infoPoolPageEnabled = useInfoPoolPageEnabled()
|
||||
|
||||
const routerConfig = useRouterConfig()
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0)
|
||||
@ -224,116 +186,15 @@ export default function App() {
|
||||
<Suspense fallback={<Loader />}>
|
||||
{isLoaded ? (
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
// If we match "/" and # is defined, we are using BrowserRouter and need to redirect.
|
||||
browserRouterEnabled && hash ? <Navigate to={hash.replace('#', '')} replace /> : <Landing />
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="tokens" element={<Tokens />}>
|
||||
<Route path=":chainName" />
|
||||
{routes.map((route: RouteDefinition) =>
|
||||
route.enabled(routerConfig) ? (
|
||||
<Route key={route.path} path={route.path} element={route.getElement(routerConfig)}>
|
||||
{route.nestedPaths.map((nestedPath) => (
|
||||
<Route path={nestedPath} key={`${route.path}/${nestedPath}`} />
|
||||
))}
|
||||
</Route>
|
||||
<Route path="tokens/:chainName/:tokenAddress" element={<TokenDetails />} />
|
||||
{infoPoolPageEnabled && <Route path="pools/:chainName/:poolAddress" element={<PoolDetails />} />}
|
||||
<Route
|
||||
path="vote/*"
|
||||
element={
|
||||
<Suspense fallback={<LazyLoadSpinner />}>
|
||||
<Vote />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route path="create-proposal" element={<Navigate to="/vote/create-proposal" replace />} />
|
||||
<Route path="send" element={<Navigate to={{ ...location, pathname: '/swap' }} replace />} />
|
||||
<Route path="swap" element={<Swap />} />
|
||||
|
||||
<Route path="pool/v2/find" element={<PoolFinder />} />
|
||||
<Route path="pool/v2" element={<PoolV2 />} />
|
||||
<Route path="pool" element={<Pool />} />
|
||||
<Route path="pool/:tokenId" element={<PositionPage />} />
|
||||
|
||||
<Route path="pools/v2/find" element={<PoolFinder />} />
|
||||
<Route path="pools/v2" element={<PoolV2 />} />
|
||||
<Route path="pools" element={<Pool />} />
|
||||
<Route path="pools/:tokenId" element={<PositionPage />} />
|
||||
|
||||
<Route path="add/v2" element={<RedirectDuplicateTokenIdsV2 />}>
|
||||
<Route path=":currencyIdA" />
|
||||
<Route path=":currencyIdA/:currencyIdB" />
|
||||
</Route>
|
||||
<Route path="add" element={<RedirectDuplicateTokenIds />}>
|
||||
{/* this is workaround since react-router-dom v6 doesn't support optional parameters any more */}
|
||||
<Route path=":currencyIdA" />
|
||||
<Route path=":currencyIdA/:currencyIdB" />
|
||||
<Route path=":currencyIdA/:currencyIdB/:feeAmount" />
|
||||
</Route>
|
||||
|
||||
<Route path="increase" element={<AddLiquidity />}>
|
||||
<Route path=":currencyIdA" />
|
||||
<Route path=":currencyIdA/:currencyIdB" />
|
||||
<Route path=":currencyIdA/:currencyIdB/:feeAmount" />
|
||||
<Route path=":currencyIdA/:currencyIdB/:feeAmount/:tokenId" />
|
||||
</Route>
|
||||
|
||||
<Route path="remove/v2/:currencyIdA/:currencyIdB" element={<RemoveLiquidity />} />
|
||||
<Route path="remove/:tokenId" element={<RemoveLiquidityV3 />} />
|
||||
|
||||
<Route path="migrate/v2" element={<MigrateV2 />} />
|
||||
<Route path="migrate/v2/:address" element={<MigrateV2Pair />} />
|
||||
|
||||
{!shouldDisableNFTRoutes && (
|
||||
<>
|
||||
<Route
|
||||
path="/nfts"
|
||||
element={
|
||||
<Suspense fallback={null}>
|
||||
<NftExplore />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/nfts/asset/:contractAddress/:tokenId"
|
||||
element={
|
||||
<Suspense fallback={null}>
|
||||
<Asset />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/nfts/profile"
|
||||
element={
|
||||
<Suspense fallback={null}>
|
||||
<Profile />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/nfts/collection/:contractAddress"
|
||||
element={
|
||||
<Suspense fallback={null}>
|
||||
<Collection />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/nfts/collection/:contractAddress/activity"
|
||||
element={
|
||||
<Suspense fallback={null}>
|
||||
<Collection />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
) : null
|
||||
)}
|
||||
|
||||
<Route path="*" element={<Navigate to="/not-found" replace />} />
|
||||
<Route path="/not-found" element={<NotFound />} />
|
||||
</Routes>
|
||||
) : (
|
||||
<Loader />
|
||||
|
208
src/pages/RouteDefinitions.tsx
Normal file
208
src/pages/RouteDefinitions.tsx
Normal file
@ -0,0 +1,208 @@
|
||||
import { useInfoPoolPageEnabled } from 'featureFlags/flags/infoPoolPage'
|
||||
import { useAtom } from 'jotai'
|
||||
import { lazy, ReactNode, Suspense, useMemo } from 'react'
|
||||
import { Navigate, useLocation } from 'react-router-dom'
|
||||
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
|
||||
import { SpinnerSVG } from 'theme/components'
|
||||
import { isBrowserRouterEnabled } from 'utils/env'
|
||||
|
||||
// High-traffic pages (index and /swap) should not be lazy-loaded.
|
||||
import Landing from './Landing'
|
||||
import Swap from './Swap'
|
||||
|
||||
const NftExplore = lazy(() => import('nft/pages/explore'))
|
||||
const Collection = lazy(() => import('nft/pages/collection'))
|
||||
const Profile = lazy(() => import('nft/pages/profile'))
|
||||
const Asset = lazy(() => import('nft/pages/asset/Asset'))
|
||||
const AddLiquidity = lazy(() => import('pages/AddLiquidity'))
|
||||
const RedirectDuplicateTokenIds = lazy(() => import('pages/AddLiquidity/redirects'))
|
||||
const RedirectDuplicateTokenIdsV2 = lazy(() => import('pages/AddLiquidityV2/redirects'))
|
||||
const MigrateV2 = lazy(() => import('pages/MigrateV2'))
|
||||
const MigrateV2Pair = lazy(() => import('pages/MigrateV2/MigrateV2Pair'))
|
||||
const NotFound = lazy(() => import('pages/NotFound'))
|
||||
const Pool = lazy(() => import('pages/Pool'))
|
||||
const PositionPage = lazy(() => import('pages/Pool/PositionPage'))
|
||||
const PoolV2 = lazy(() => import('pages/Pool/v2'))
|
||||
const PoolDetails = lazy(() => import('pages/PoolDetails'))
|
||||
const PoolFinder = lazy(() => import('pages/PoolFinder'))
|
||||
const RemoveLiquidity = lazy(() => import('pages/RemoveLiquidity'))
|
||||
const RemoveLiquidityV3 = lazy(() => import('pages/RemoveLiquidity/V3'))
|
||||
const TokenDetails = lazy(() => import('pages/TokenDetails'))
|
||||
const Tokens = lazy(() => import('pages/Tokens'))
|
||||
const Vote = lazy(() => import('pages/Vote'))
|
||||
|
||||
// this is the same svg defined in assets/images/blue-loader.svg
|
||||
// it is defined here because the remote asset may not have had time to load when this file is executing
|
||||
const LazyLoadSpinner = () => (
|
||||
<SpinnerSVG width="94" height="94" viewBox="0 0 94 94" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M92 47C92 22.1472 71.8528 2 47 2C22.1472 2 2 22.1472 2 47C2 71.8528 22.1472 92 47 92"
|
||||
stroke="#2172E5"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</SpinnerSVG>
|
||||
)
|
||||
|
||||
interface RouterConfig {
|
||||
browserRouterEnabled?: boolean
|
||||
hash?: string
|
||||
infoPoolPageEnabled?: boolean
|
||||
shouldDisableNFTRoutes?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience hook which organizes the router configuration into a single object.
|
||||
*/
|
||||
export function useRouterConfig(): RouterConfig {
|
||||
const browserRouterEnabled = isBrowserRouterEnabled()
|
||||
const { hash } = useLocation()
|
||||
const infoPoolPageEnabled = useInfoPoolPageEnabled()
|
||||
const [shouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom)
|
||||
return useMemo(
|
||||
() => ({
|
||||
browserRouterEnabled,
|
||||
hash,
|
||||
infoPoolPageEnabled,
|
||||
shouldDisableNFTRoutes: Boolean(shouldDisableNFTRoutes),
|
||||
}),
|
||||
[browserRouterEnabled, hash, infoPoolPageEnabled, shouldDisableNFTRoutes]
|
||||
)
|
||||
}
|
||||
|
||||
export interface RouteDefinition {
|
||||
path: string
|
||||
nestedPaths: string[]
|
||||
enabled: (args: RouterConfig) => boolean
|
||||
getElement: (args: RouterConfig) => ReactNode
|
||||
}
|
||||
|
||||
// Assigns the defaults to the route definition.
|
||||
function createRouteDefinition(route: Partial<RouteDefinition>): RouteDefinition {
|
||||
return {
|
||||
getElement: () => null,
|
||||
enabled: () => true,
|
||||
path: '/',
|
||||
nestedPaths: [],
|
||||
// overwrite the defaults
|
||||
...route,
|
||||
}
|
||||
}
|
||||
|
||||
export const routes: RouteDefinition[] = [
|
||||
createRouteDefinition({
|
||||
path: '/',
|
||||
getElement: (args) => {
|
||||
return args.browserRouterEnabled && args.hash ? <Navigate to={args.hash.replace('#', '')} replace /> : <Landing />
|
||||
},
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/tokens',
|
||||
nestedPaths: [':chainName'],
|
||||
getElement: () => <Tokens />,
|
||||
}),
|
||||
createRouteDefinition({ path: '/tokens/:chainName/:tokenAddress', getElement: () => <TokenDetails /> }),
|
||||
createRouteDefinition({
|
||||
path: '/pools/:chainName/:poolAddress',
|
||||
getElement: () => <PoolDetails />,
|
||||
enabled: (args) => Boolean(args.infoPoolPageEnabled),
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/vote/*',
|
||||
getElement: () => (
|
||||
<Suspense fallback={<LazyLoadSpinner />}>
|
||||
<Vote />
|
||||
</Suspense>
|
||||
),
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/create-proposal',
|
||||
getElement: () => <Navigate to="/vote/create-proposal" replace />,
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/send',
|
||||
getElement: () => <Navigate to={{ ...location, pathname: '/swap' }} replace />,
|
||||
}),
|
||||
createRouteDefinition({ path: '/swap', getElement: () => <Swap /> }),
|
||||
createRouteDefinition({ path: '/pool/v2/find', getElement: () => <PoolFinder /> }),
|
||||
createRouteDefinition({ path: '/pool/v2', getElement: () => <PoolV2 /> }),
|
||||
createRouteDefinition({ path: '/pool', getElement: () => <Pool /> }),
|
||||
createRouteDefinition({ path: '/pool/:tokenId', getElement: () => <PositionPage /> }),
|
||||
createRouteDefinition({ path: '/pools/v2/find', getElement: () => <PoolFinder /> }),
|
||||
createRouteDefinition({ path: '/pools/v2', getElement: () => <PoolV2 /> }),
|
||||
createRouteDefinition({ path: '/pools', getElement: () => <Pool /> }),
|
||||
createRouteDefinition({ path: '/pools/:tokenId', getElement: () => <PositionPage /> }),
|
||||
createRouteDefinition({
|
||||
path: '/add/v2',
|
||||
nestedPaths: [':currencyIdA', ':currencyIdA/:currencyIdB'],
|
||||
getElement: () => <RedirectDuplicateTokenIdsV2 />,
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/add',
|
||||
nestedPaths: [':currencyIdA', ':currencyIdA/:currencyIdB', ':currencyIdA/:currencyIdB/:feeAmount'],
|
||||
getElement: () => <RedirectDuplicateTokenIds />,
|
||||
}),
|
||||
|
||||
createRouteDefinition({
|
||||
path: '/increase',
|
||||
nestedPaths: [
|
||||
':currencyIdA',
|
||||
':currencyIdA/:currencyIdB',
|
||||
':currencyIdA/:currencyIdB/:feeAmount',
|
||||
':currencyIdA/:currencyIdB/:feeAmount/:tokenId',
|
||||
],
|
||||
getElement: () => <AddLiquidity />,
|
||||
}),
|
||||
createRouteDefinition({ path: '/remove/v2/:currencyIdA/:currencyIdB', getElement: () => <RemoveLiquidity /> }),
|
||||
createRouteDefinition({ path: '/remove/:tokenId', getElement: () => <RemoveLiquidityV3 /> }),
|
||||
createRouteDefinition({ path: '/migrate/v2', getElement: () => <MigrateV2 /> }),
|
||||
createRouteDefinition({ path: '/migrate/v2/:address', getElement: () => <MigrateV2Pair /> }),
|
||||
createRouteDefinition({
|
||||
path: '/nfts',
|
||||
getElement: () => (
|
||||
<Suspense fallback={null}>
|
||||
<NftExplore />
|
||||
</Suspense>
|
||||
),
|
||||
enabled: (args) => !args.shouldDisableNFTRoutes,
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/nfts/asset/:contractAddress/:tokenId',
|
||||
getElement: () => (
|
||||
<Suspense fallback={null}>
|
||||
<Asset />
|
||||
</Suspense>
|
||||
),
|
||||
enabled: (args) => !args.shouldDisableNFTRoutes,
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/nfts/profile',
|
||||
getElement: () => (
|
||||
<Suspense fallback={null}>
|
||||
<Profile />
|
||||
</Suspense>
|
||||
),
|
||||
enabled: (args) => !args.shouldDisableNFTRoutes,
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/nfts/collection/:contractAddress',
|
||||
getElement: () => (
|
||||
<Suspense fallback={null}>
|
||||
<Collection />
|
||||
</Suspense>
|
||||
),
|
||||
enabled: (args) => !args.shouldDisableNFTRoutes,
|
||||
}),
|
||||
createRouteDefinition({
|
||||
path: '/nfts/collection/:contractAddress/activity',
|
||||
getElement: () => (
|
||||
<Suspense fallback={null}>
|
||||
<Collection />
|
||||
</Suspense>
|
||||
),
|
||||
enabled: (args) => !args.shouldDisableNFTRoutes,
|
||||
}),
|
||||
createRouteDefinition({ path: '*', getElement: () => <Navigate to="/not-found" replace /> }),
|
||||
createRouteDefinition({ path: '/not-found', getElement: () => <NotFound /> }),
|
||||
]
|
200
src/pages/__snapshots__/routes.test.ts.snap
Normal file
200
src/pages/__snapshots__/routes.test.ts.snap
Normal file
@ -0,0 +1,200 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Routes router definition should match snapshot 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [
|
||||
":chainName",
|
||||
],
|
||||
"path": "/tokens",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/tokens/:chainName/:tokenAddress",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pools/:chainName/:poolAddress",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/vote/*",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/create-proposal",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/send",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/swap",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pool/v2/find",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pool/v2",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pool",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pool/:tokenId",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pools/v2/find",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pools/v2",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pools",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/pools/:tokenId",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [
|
||||
":currencyIdA",
|
||||
":currencyIdA/:currencyIdB",
|
||||
],
|
||||
"path": "/add/v2",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [
|
||||
":currencyIdA",
|
||||
":currencyIdA/:currencyIdB",
|
||||
":currencyIdA/:currencyIdB/:feeAmount",
|
||||
],
|
||||
"path": "/add",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [
|
||||
":currencyIdA",
|
||||
":currencyIdA/:currencyIdB",
|
||||
":currencyIdA/:currencyIdB/:feeAmount",
|
||||
":currencyIdA/:currencyIdB/:feeAmount/:tokenId",
|
||||
],
|
||||
"path": "/increase",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/remove/v2/:currencyIdA/:currencyIdB",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/remove/:tokenId",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/migrate/v2",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/migrate/v2/:address",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/nfts",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/nfts/asset/:contractAddress/:tokenId",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/nfts/profile",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/nfts/collection/:contractAddress",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/nfts/collection/:contractAddress/activity",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "*",
|
||||
},
|
||||
Object {
|
||||
"enabled": [Function],
|
||||
"getElement": [Function],
|
||||
"nestedPaths": Array [],
|
||||
"path": "/not-found",
|
||||
},
|
||||
]
|
||||
`;
|
26
src/pages/routes.test.ts
Normal file
26
src/pages/routes.test.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import fs from 'fs'
|
||||
import { parseStringPromise } from 'xml2js'
|
||||
|
||||
import { routes } from './RouteDefinitions'
|
||||
|
||||
describe('Routes', () => {
|
||||
it('sitemap URLs should exist as Router paths', async () => {
|
||||
const pathNames: string[] = routes.map((routeDef) => routeDef.path)
|
||||
const contents = fs.readFileSync('./public/sitemap.xml', 'utf8')
|
||||
const sitemap = await parseStringPromise(contents)
|
||||
|
||||
const sitemapPaths = sitemap.urlset.url.map((url: any) => new URL(url['$'].loc).pathname)
|
||||
|
||||
sitemapPaths.forEach((path: string) => {
|
||||
expect(pathNames).toContain(path)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* If you are updating the app routes, consider if you need to make a
|
||||
* corresponding update to the sitemap.xml file.
|
||||
*/
|
||||
it('router definition should match snapshot', () => {
|
||||
expect(routes).toMatchSnapshot()
|
||||
})
|
||||
})
|
27
yarn.lock
27
yarn.lock
@ -5921,6 +5921,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/xml2js@^0.4.12":
|
||||
version "0.4.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.12.tgz#d9aae03295476fd5cbc74e0b572816208dbec6d1"
|
||||
integrity sha512-CZPpQKBZ8db66EP5hCjwvYrLThgZvnyZrPXK2W+UI1oOaWezGt34iOaUCX4Jah2X8+rQqjvl9VKEIT8TR1I0rA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "20.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
|
||||
@ -15542,9 +15549,9 @@ mz@^2.7.0:
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nan@^2.14.0:
|
||||
version "2.14.2"
|
||||
resolved "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz"
|
||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554"
|
||||
integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==
|
||||
|
||||
nano-time@1.0.0:
|
||||
version "1.0.0"
|
||||
@ -17227,9 +17234,9 @@ punycode@1.3.2, punycode@^1.3.2:
|
||||
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
||||
|
||||
punycode@^2.1.0, punycode@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
|
||||
|
||||
pure-rand@^6.0.0:
|
||||
version "6.0.2"
|
||||
@ -21101,6 +21108,14 @@ xml2js@^0.4.5:
|
||||
sax ">=0.6.0"
|
||||
xmlbuilder "~11.0.0"
|
||||
|
||||
xml2js@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499"
|
||||
integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
|
||||
dependencies:
|
||||
sax ">=0.6.0"
|
||||
xmlbuilder "~11.0.0"
|
||||
|
||||
xmlbuilder@~11.0.0:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user