feat: base network (#6997)
* feat: initial support for base goerli * wip: update dependencies * chore: yarn deduplicate * feat: mainnet wip support * feat: mainnet wip support * fix: radial gradient * fix: logo update * fix: ur address * fix: add weth to common bases * fix: updates * fix: yarn dedup * fix: correct rpc url * fix: correct explorer url * feat: add USDbC to common bases * fix lint warnings * bump SOR version * fix: fallback URLs * feat: statsig flag for base support (#7079) * feat: put base support behind statsig flag * fix: null checks * fix: hide pool page * fix: baseEnabledChains * feat: update sor --------- Co-authored-by: Jordan Frankfurt <jordan@uniswap.org>
This commit is contained in:
parent
f845695f6e
commit
fa4e75b777
2
.env
2
.env
@ -4,6 +4,8 @@ REACT_APP_AMPLITUDE_PROXY_URL="https://api.uniswap.org/v1/amplitude-proxy"
|
|||||||
REACT_APP_AWS_API_REGION="us-east-2"
|
REACT_APP_AWS_API_REGION="us-east-2"
|
||||||
REACT_APP_AWS_API_ENDPOINT="https://beta.api.uniswap.org/v1/graphql"
|
REACT_APP_AWS_API_ENDPOINT="https://beta.api.uniswap.org/v1/graphql"
|
||||||
REACT_APP_BNB_RPC_URL="https://rough-sleek-hill.bsc.quiknode.pro/413cc98cbc776cda8fdf1d0f47003583ff73d9bf"
|
REACT_APP_BNB_RPC_URL="https://rough-sleek-hill.bsc.quiknode.pro/413cc98cbc776cda8fdf1d0f47003583ff73d9bf"
|
||||||
|
REACT_APP_BASE_GOERLI_RPC_URL="https://wiser-compatible-mansion.base-goerli.quiknode.pro/5874f36248e17020a1006149e7f68c63967e1f45/"
|
||||||
|
REACT_APP_BASE_MAINNET_RPC_URL="https://cool-white-diagram.base-mainnet.quiknode.pro/d8f036f35dfab2c68f32dfa822cd971e7a25a117/"
|
||||||
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
|
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
|
||||||
REACT_APP_MOONPAY_API="https://api.moonpay.com"
|
REACT_APP_MOONPAY_API="https://api.moonpay.com"
|
||||||
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkV2?platform=web&env=staging"
|
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkV2?platform=web&env=staging"
|
||||||
|
@ -181,7 +181,7 @@
|
|||||||
"@uniswap/redux-multicall": "^1.1.8",
|
"@uniswap/redux-multicall": "^1.1.8",
|
||||||
"@uniswap/router-sdk": "^1.6.0",
|
"@uniswap/router-sdk": "^1.6.0",
|
||||||
"@uniswap/sdk-core": "^4.0.3",
|
"@uniswap/sdk-core": "^4.0.3",
|
||||||
"@uniswap/smart-order-router": "^3.13.7",
|
"@uniswap/smart-order-router": "^3.15.0",
|
||||||
"@uniswap/token-lists": "^1.0.0-beta.33",
|
"@uniswap/token-lists": "^1.0.0-beta.33",
|
||||||
"@uniswap/uniswapx-sdk": "^1.1.0",
|
"@uniswap/uniswapx-sdk": "^1.1.0",
|
||||||
"@uniswap/universal-router-sdk": "^1.5.6",
|
"@uniswap/universal-router-sdk": "^1.5.6",
|
||||||
|
11
src/assets/svg/base_logo.svg
Normal file
11
src/assets/svg/base_logo.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 14C0 6.26801 6.26801 0 14 0V0C21.732 0 28 6.26801 28 14V14C28 21.732 21.732 28 14 28V28C6.26801 28 0 21.732 0 14V14Z" fill="#0052FF"/>
|
||||||
|
<g clip-path="url(#clip0_13924_33076)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.3332 14.0003C23.3332 19.155 19.1472 23.3337 13.9836 23.3337C9.08459 23.3337 5.06565 19.5724 4.6665 14.7849H17.0245V13.2158H4.6665C5.06565 8.42825 9.08459 4.66699 13.9836 4.66699C19.1472 4.66699 23.3332 8.84566 23.3332 14.0003Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_13924_33076">
|
||||||
|
<rect width="18.6667" height="18.6667" fill="white" transform="translate(4.66675 4.66699)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 745 B |
11
src/assets/svg/base_square_logo.svg
Normal file
11
src/assets/svg/base_square_logo.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="28" height="28" rx="8" fill="#0052FF"/>
|
||||||
|
<g clip-path="url(#clip0_13921_13252)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.3332 14.0003C23.3332 19.155 19.1472 23.3337 13.9836 23.3337C9.08459 23.3337 5.06565 19.5724 4.6665 14.7849H17.0245V13.2158H4.6665C5.06565 8.42825 9.08459 4.66699 13.9836 4.66699C19.1472 4.66699 23.3332 8.84566 23.3332 14.0003Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_13921_13252">
|
||||||
|
<rect width="18.6667" height="18.6667" fill="white" transform="translate(4.66675 4.66699)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 651 B |
@ -11,6 +11,7 @@ import { useWeb3React } from '@web3-react/core'
|
|||||||
import { isSupportedChain } from 'constants/chains'
|
import { isSupportedChain } from 'constants/chains'
|
||||||
import { RPC_PROVIDERS } from 'constants/providers'
|
import { RPC_PROVIDERS } from 'constants/providers'
|
||||||
import { BaseContract } from 'ethers/lib/ethers'
|
import { BaseContract } from 'ethers/lib/ethers'
|
||||||
|
import { useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import { ContractInput, useUniswapPricesQuery } from 'graphql/data/__generated__/types-and-hooks'
|
import { ContractInput, useUniswapPricesQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||||
import { toContractInput } from 'graphql/data/util'
|
import { toContractInput } from 'graphql/data/util'
|
||||||
import useStablecoinPrice from 'hooks/useStablecoinPrice'
|
import useStablecoinPrice from 'hooks/useStablecoinPrice'
|
||||||
@ -30,13 +31,14 @@ function useContractMultichain<T extends BaseContract>(
|
|||||||
chainIds?: ChainId[]
|
chainIds?: ChainId[]
|
||||||
): ContractMap<T> {
|
): ContractMap<T> {
|
||||||
const { chainId: walletChainId, provider: walletProvider } = useWeb3React()
|
const { chainId: walletChainId, provider: walletProvider } = useWeb3React()
|
||||||
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const relevantChains =
|
const relevantChains =
|
||||||
chainIds ??
|
chainIds ??
|
||||||
Object.keys(addressMap)
|
Object.keys(addressMap)
|
||||||
.map((chainId) => parseInt(chainId))
|
.map((chainId) => parseInt(chainId))
|
||||||
.filter(isSupportedChain)
|
.filter((chainId) => isSupportedChain(chainId, baseEnabledChains))
|
||||||
|
|
||||||
return relevantChains.reduce((acc: ContractMap<T>, chainId) => {
|
return relevantChains.reduce((acc: ContractMap<T>, chainId) => {
|
||||||
const provider =
|
const provider =
|
||||||
@ -50,7 +52,7 @@ function useContractMultichain<T extends BaseContract>(
|
|||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
}, [ABI, addressMap, chainIds, walletChainId, walletProvider])
|
}, [ABI, addressMap, baseEnabledChains, chainIds, walletChainId, walletProvider])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useV3ManagerContracts(chainIds: ChainId[]): ContractMap<NonfungiblePositionManager> {
|
export function useV3ManagerContracts(chainIds: ChainId[]): ContractMap<NonfungiblePositionManager> {
|
||||||
|
@ -47,6 +47,7 @@ const DEFAULT_CHAINS = [
|
|||||||
ChainId.CELO,
|
ChainId.CELO,
|
||||||
ChainId.BNB,
|
ChainId.BNB,
|
||||||
ChainId.AVALANCHE,
|
ChainId.AVALANCHE,
|
||||||
|
ChainId.BASE,
|
||||||
]
|
]
|
||||||
|
|
||||||
type UseMultiChainPositionsData = { positions?: PositionInfo[]; loading: boolean }
|
type UseMultiChainPositionsData = { positions?: PositionInfo[]; loading: boolean }
|
||||||
|
@ -5,6 +5,7 @@ import { MissingImageLogo } from 'components/Logo/AssetLogo'
|
|||||||
import CurrencyLogo from 'components/Logo/CurrencyLogo'
|
import CurrencyLogo from 'components/Logo/CurrencyLogo'
|
||||||
import { Unicon } from 'components/Unicon'
|
import { Unicon } from 'components/Unicon'
|
||||||
import { getChainInfo } from 'constants/chainInfo'
|
import { getChainInfo } from 'constants/chainInfo'
|
||||||
|
import { useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import useTokenLogoSource from 'hooks/useAssetLogoSource'
|
import useTokenLogoSource from 'hooks/useAssetLogoSource'
|
||||||
import useENSAvatar from 'hooks/useENSAvatar'
|
import useENSAvatar from 'hooks/useENSAvatar'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@ -98,7 +99,10 @@ export function PortfolioLogo({
|
|||||||
size = '40px',
|
size = '40px',
|
||||||
style,
|
style,
|
||||||
}: MultiLogoProps) {
|
}: MultiLogoProps) {
|
||||||
const { squareLogoUrl, logoUrl } = getChainInfo(chainId)
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
const chainInfo = getChainInfo(chainId, baseEnabledChains)
|
||||||
|
const squareLogoUrl = chainInfo?.squareLogoUrl
|
||||||
|
const logoUrl = chainInfo?.logoUrl
|
||||||
const chainLogo = squareLogoUrl ?? logoUrl
|
const chainLogo = squareLogoUrl ?? logoUrl
|
||||||
const { avatar, loading } = useENSAvatar(accountAddress, false)
|
const { avatar, loading } = useENSAvatar(accountAddress, false)
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
@ -213,14 +213,14 @@ function AccountDrawer() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// reset the yPosition when the user stops dragging
|
// reset the yPosition when the user stops dragging
|
||||||
onDragEnd: (state) => {
|
onDragEnd: () => {
|
||||||
setYPosition(0)
|
setYPosition(0)
|
||||||
if (scrollRef.current) {
|
if (scrollRef.current) {
|
||||||
scrollRef.current.style.overflowY = 'auto'
|
scrollRef.current.style.overflowY = 'auto'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// set dragStartTop to true if the user starts dragging from the top of the drawer
|
// set dragStartTop to true if the user starts dragging from the top of the drawer
|
||||||
onDragStart: (state) => {
|
onDragStart: () => {
|
||||||
if (!scrollRef.current?.scrollTop || scrollRef.current?.scrollTop < 30) {
|
if (!scrollRef.current?.scrollTop || scrollRef.current?.scrollTop < 30) {
|
||||||
setDragStartTop(true)
|
setDragStartTop(true)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { BaseVariant, FeatureFlag, featureFlagSettings, useUpdateFlag } from 'featureFlags'
|
import { BaseVariant, FeatureFlag, featureFlagSettings, useUpdateFlag } from 'featureFlags'
|
||||||
|
import { useBaseEnabledFlag } from 'featureFlags/flags/baseEnabled'
|
||||||
import { useForceUniswapXOnFlag } from 'featureFlags/flags/forceUniswapXOn'
|
import { useForceUniswapXOnFlag } from 'featureFlags/flags/forceUniswapXOn'
|
||||||
import { DetailsV2Variant, useDetailsV2Flag } from 'featureFlags/flags/nftDetails'
|
import { DetailsV2Variant, useDetailsV2Flag } from 'featureFlags/flags/nftDetails'
|
||||||
import { useRoutingAPIForPriceFlag } from 'featureFlags/flags/priceRoutingApi'
|
import { useRoutingAPIForPriceFlag } from 'featureFlags/flags/priceRoutingApi'
|
||||||
@ -235,6 +236,12 @@ export default function FeatureFlagModal() {
|
|||||||
featureFlag={FeatureFlag.routingAPIPrice}
|
featureFlag={FeatureFlag.routingAPIPrice}
|
||||||
label="Use the routing-api v2 for price fetches"
|
label="Use the routing-api v2 for price fetches"
|
||||||
/>
|
/>
|
||||||
|
<FeatureFlagOption
|
||||||
|
variant={BaseVariant}
|
||||||
|
value={useBaseEnabledFlag()}
|
||||||
|
featureFlag={FeatureFlag.baseEnabled}
|
||||||
|
label="Enable Base"
|
||||||
|
/>
|
||||||
<FeatureFlagGroup name="Debug">
|
<FeatureFlagGroup name="Debug">
|
||||||
<FeatureFlagOption
|
<FeatureFlagOption
|
||||||
variant={TraceJsonRpcVariant}
|
variant={TraceJsonRpcVariant}
|
||||||
|
@ -20,6 +20,8 @@ export const FEE_AMOUNT_DETAIL: Record<
|
|||||||
ChainId.POLYGON,
|
ChainId.POLYGON,
|
||||||
ChainId.POLYGON_MUMBAI,
|
ChainId.POLYGON_MUMBAI,
|
||||||
ChainId.AVALANCHE,
|
ChainId.AVALANCHE,
|
||||||
|
ChainId.BASE,
|
||||||
|
ChainId.BASE_GOERLI,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
[FeeAmount.LOW]: {
|
[FeeAmount.LOW]: {
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
TESTNET_CHAIN_IDS,
|
TESTNET_CHAIN_IDS,
|
||||||
UniWalletSupportedChains,
|
UniWalletSupportedChains,
|
||||||
} from 'constants/chains'
|
} from 'constants/chains'
|
||||||
|
import { useBaseEnabled, useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||||
import useSelectChain from 'hooks/useSelectChain'
|
import useSelectChain from 'hooks/useSelectChain'
|
||||||
import useSyncChainQuery from 'hooks/useSyncChainQuery'
|
import useSyncChainQuery from 'hooks/useSyncChainQuery'
|
||||||
@ -59,13 +60,20 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
|||||||
|
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
|
const baseEnabled = useBaseEnabled()
|
||||||
const showTestnets = useAtomValue(showTestnetsAtom)
|
const showTestnets = useAtomValue(showTestnetsAtom)
|
||||||
const walletSupportsChain = useWalletSupportedChains()
|
const walletSupportsChain = useWalletSupportedChains()
|
||||||
|
|
||||||
const [supportedChains, unsupportedChains] = useMemo(() => {
|
const [supportedChains, unsupportedChains] = useMemo(() => {
|
||||||
const { supported, unsupported } = NETWORK_SELECTOR_CHAINS.filter(
|
const { supported, unsupported } = NETWORK_SELECTOR_CHAINS.filter((chain: number) => {
|
||||||
(chain: number) => showTestnets || !TESTNET_CHAIN_IDS.includes(chain)
|
if (chain === ChainId.BASE) {
|
||||||
)
|
return baseEnabled
|
||||||
|
}
|
||||||
|
if (chain === ChainId.BASE_GOERLI) {
|
||||||
|
return showTestnets && baseEnabled
|
||||||
|
}
|
||||||
|
return showTestnets || !TESTNET_CHAIN_IDS.includes(chain)
|
||||||
|
})
|
||||||
.sort((a, b) => getChainPriority(a) - getChainPriority(b))
|
.sort((a, b) => getChainPriority(a) - getChainPriority(b))
|
||||||
.reduce(
|
.reduce(
|
||||||
(acc, chain) => {
|
(acc, chain) => {
|
||||||
@ -79,13 +87,14 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
|||||||
{ supported: [], unsupported: [] } as Record<string, ChainId[]>
|
{ supported: [], unsupported: [] } as Record<string, ChainId[]>
|
||||||
)
|
)
|
||||||
return [supported, unsupported]
|
return [supported, unsupported]
|
||||||
}, [showTestnets, walletSupportsChain])
|
}, [baseEnabled, showTestnets, walletSupportsChain])
|
||||||
|
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
const modalRef = useRef<HTMLDivElement>(null)
|
const modalRef = useRef<HTMLDivElement>(null)
|
||||||
useOnClickOutside(ref, () => setIsOpen(false), [modalRef])
|
useOnClickOutside(ref, () => setIsOpen(false), [modalRef])
|
||||||
|
|
||||||
const info = chainId ? getChainInfo(chainId) : undefined
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
const info = getChainInfo(chainId, baseEnabledChains)
|
||||||
|
|
||||||
const selectChain = useSelectChain()
|
const selectChain = useSelectChain()
|
||||||
useSyncChainQuery()
|
useSyncChainQuery()
|
||||||
|
@ -3,6 +3,7 @@ import { ChainId } from '@uniswap/sdk-core'
|
|||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
import Loader from 'components/Icons/LoadingSpinner'
|
import Loader from 'components/Icons/LoadingSpinner'
|
||||||
import { getChainInfo } from 'constants/chainInfo'
|
import { getChainInfo } from 'constants/chainInfo'
|
||||||
|
import { useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import { CheckMarkIcon } from 'nft/components/icons'
|
import { CheckMarkIcon } from 'nft/components/icons'
|
||||||
import styled, { useTheme } from 'styled-components/macro'
|
import styled, { useTheme } from 'styled-components/macro'
|
||||||
|
|
||||||
@ -70,7 +71,10 @@ interface ChainSelectorRowProps {
|
|||||||
export default function ChainSelectorRow({ disabled, targetChain, onSelectChain, isPending }: ChainSelectorRowProps) {
|
export default function ChainSelectorRow({ disabled, targetChain, onSelectChain, isPending }: ChainSelectorRowProps) {
|
||||||
const { chainId } = useWeb3React()
|
const { chainId } = useWeb3React()
|
||||||
const active = chainId === targetChain
|
const active = chainId === targetChain
|
||||||
const { label, logoUrl } = getChainInfo(targetChain)
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
const chainInfo = getChainInfo(targetChain, baseEnabledChains)
|
||||||
|
const label = chainInfo?.label
|
||||||
|
const logoUrl = chainInfo?.logoUrl
|
||||||
|
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
@ -81,8 +85,8 @@ export default function ChainSelectorRow({ disabled, targetChain, onSelectChain,
|
|||||||
if (!disabled) onSelectChain(targetChain)
|
if (!disabled) onSelectChain(targetChain)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Logo src={logoUrl} alt={label} />
|
{logoUrl && <Logo src={logoUrl} alt={label} />}
|
||||||
<Label>{label}</Label>
|
{label && <Label>{label}</Label>}
|
||||||
{disabled && (
|
{disabled && (
|
||||||
<CaptionText>
|
<CaptionText>
|
||||||
<Trans>Unsupported by your wallet</Trans>
|
<Trans>Unsupported by your wallet</Trans>
|
||||||
|
@ -362,6 +362,9 @@ function ComingSoonText({ chainId }: { chainId: ChainId }) {
|
|||||||
return <Trans>Coming soon: search and explore tokens on BNB Chain</Trans>
|
return <Trans>Coming soon: search and explore tokens on BNB Chain</Trans>
|
||||||
case ChainId.AVALANCHE:
|
case ChainId.AVALANCHE:
|
||||||
return <Trans>Coming soon: search and explore tokens on Avalanche Chain</Trans>
|
return <Trans>Coming soon: search and explore tokens on Avalanche Chain</Trans>
|
||||||
|
case ChainId.BASE:
|
||||||
|
case ChainId.BASE_GOERLI:
|
||||||
|
return <Trans>Coming soon: search and explore tokens on Base</Trans>
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro'
|
|||||||
import { ChainId } from '@uniswap/sdk-core'
|
import { ChainId } from '@uniswap/sdk-core'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
import { getChainInfo } from 'constants/chainInfo'
|
import { getChainInfo } from 'constants/chainInfo'
|
||||||
|
import { useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import { ArrowUpRight } from 'react-feather'
|
import { ArrowUpRight } from 'react-feather'
|
||||||
import styled from 'styled-components/macro'
|
import styled from 'styled-components/macro'
|
||||||
import { ExternalLink, HideSmall } from 'theme'
|
import { ExternalLink, HideSmall } from 'theme'
|
||||||
@ -39,6 +40,8 @@ const SHOULD_SHOW_ALERT = {
|
|||||||
[ChainId.CELO_ALFAJORES]: true,
|
[ChainId.CELO_ALFAJORES]: true,
|
||||||
[ChainId.BNB]: true,
|
[ChainId.BNB]: true,
|
||||||
[ChainId.AVALANCHE]: true,
|
[ChainId.AVALANCHE]: true,
|
||||||
|
[ChainId.BASE]: true,
|
||||||
|
[ChainId.BASE_GOERLI]: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkAlertChains = keyof typeof SHOULD_SHOW_ALERT
|
type NetworkAlertChains = keyof typeof SHOULD_SHOW_ALERT
|
||||||
@ -67,6 +70,10 @@ const BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID: {
|
|||||||
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.05) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.05) 0%, rgba(33, 114, 229, 0.1) 100%), hsla(0, 0%, 100%, 0.05)',
|
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.05) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.05) 0%, rgba(33, 114, 229, 0.1) 100%), hsla(0, 0%, 100%, 0.05)',
|
||||||
[ChainId.AVALANCHE]:
|
[ChainId.AVALANCHE]:
|
||||||
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)',
|
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)',
|
||||||
|
[ChainId.BASE]:
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(10, 41, 75, 0.7) 0%, rgba(0, 82, 255, .1) 40%, rgba(0, 82, 255, 0) 100%), rgb(13, 14, 14);',
|
||||||
|
[ChainId.BASE_GOERLI]:
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(10, 41, 75, 0.7) 0%, rgba(0, 82, 255, .1) 40%, rgba(0, 82, 255, 0) 100%), rgb(13, 14, 14);',
|
||||||
},
|
},
|
||||||
light: {
|
light: {
|
||||||
[ChainId.POLYGON]:
|
[ChainId.POLYGON]:
|
||||||
@ -89,6 +96,10 @@ const BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID: {
|
|||||||
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1)',
|
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1)',
|
||||||
[ChainId.AVALANCHE]:
|
[ChainId.AVALANCHE]:
|
||||||
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
|
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
|
||||||
|
[ChainId.BASE]:
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(0, 82, 255, 0.20) 0%, rgba(0, 82, 255, 0.08) 40.0%, rgba(252, 255, 82, 0.00) 100%), rgb(255, 255, 255)',
|
||||||
|
[ChainId.BASE_GOERLI]:
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(0, 82, 255, 0.20) 0%, rgba(0, 82, 255, 0.08) 40.0%, rgba(252, 255, 82, 0.00) 100%), rgb(255, 255, 255)',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +160,8 @@ const TEXT_COLORS: { [chainId in NetworkAlertChains]: string } = {
|
|||||||
[ChainId.BNB]: colors.gold400,
|
[ChainId.BNB]: colors.gold400,
|
||||||
[ChainId.ARBITRUM_GOERLI]: '#0490ed',
|
[ChainId.ARBITRUM_GOERLI]: '#0490ed',
|
||||||
[ChainId.AVALANCHE]: '#ff3856',
|
[ChainId.AVALANCHE]: '#ff3856',
|
||||||
|
[ChainId.BASE]: colors.networkBase,
|
||||||
|
[ChainId.BASE_GOERLI]: colors.networkBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowAlert(chainId: number | undefined): chainId is NetworkAlertChains {
|
function shouldShowAlert(chainId: number | undefined): chainId is NetworkAlertChains {
|
||||||
@ -158,12 +171,14 @@ function shouldShowAlert(chainId: number | undefined): chainId is NetworkAlertCh
|
|||||||
export function NetworkAlert() {
|
export function NetworkAlert() {
|
||||||
const { chainId } = useWeb3React()
|
const { chainId } = useWeb3React()
|
||||||
const [darkMode] = useDarkModeManager()
|
const [darkMode] = useDarkModeManager()
|
||||||
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
|
||||||
if (!shouldShowAlert(chainId)) {
|
if (!shouldShowAlert(chainId)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const chainInfo = getChainInfo(chainId)
|
const chainInfo = getChainInfo(chainId, baseEnabledChains)
|
||||||
|
|
||||||
if (!chainInfo) return null
|
if (!chainInfo) return null
|
||||||
|
|
||||||
const { label, logoUrl, bridge } = chainInfo
|
const { label, logoUrl, bridge } = chainInfo
|
||||||
|
@ -53,6 +53,8 @@ export default function InvalidTokenDetails({
|
|||||||
// if the token's address is valid and the chains match, it's a non-existant token
|
// if the token's address is valid and the chains match, it's a non-existant token
|
||||||
const isNonExistantToken = !isInvalidAddress && pageChainId === chainId
|
const isNonExistantToken = !isInvalidAddress && pageChainId === chainId
|
||||||
|
|
||||||
|
const connectedChainLabel = chainId ? getChainInfo(chainId)?.label : undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvalidDetailsContainer>
|
<InvalidDetailsContainer>
|
||||||
<EyeIcon />
|
<EyeIcon />
|
||||||
@ -69,9 +71,11 @@ export default function InvalidTokenDetails({
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
{connectedChainLabel && (
|
||||||
<InvalidDetailsText>
|
<InvalidDetailsText>
|
||||||
<Trans>This token doesn't exist on {getChainInfo(chainId)?.label}</Trans>
|
<Trans>This token doesn't exist on {connectedChainLabel}</Trans>
|
||||||
</InvalidDetailsText>
|
</InvalidDetailsText>
|
||||||
|
)}
|
||||||
<TokenExploreButton onClick={() => selectChain(pageChainId)}>
|
<TokenExploreButton onClick={() => selectChain(pageChainId)}>
|
||||||
<ThemedText.SubHeader>
|
<ThemedText.SubHeader>
|
||||||
<Trans>Switch to {getChainInfo(pageChainId).label}</Trans>
|
<Trans>Switch to {getChainInfo(pageChainId).label}</Trans>
|
||||||
|
@ -8,4 +8,4 @@ export const SMALL_MEDIA_BREAKPOINT = '540px'
|
|||||||
export const MOBILE_MEDIA_BREAKPOINT = '420px'
|
export const MOBILE_MEDIA_BREAKPOINT = '420px'
|
||||||
|
|
||||||
// includes chains that the backend does not current source off-chain metadata for
|
// includes chains that the backend does not current source off-chain metadata for
|
||||||
export const UNSUPPORTED_METADATA_CHAINS = [ChainId.BNB, ChainId.AVALANCHE]
|
export const UNSUPPORTED_METADATA_CHAINS = [ChainId.BNB, ChainId.AVALANCHE, ChainId.BASE_GOERLI, ChainId.BASE]
|
||||||
|
@ -21,7 +21,6 @@ import { colors } from 'theme/colors'
|
|||||||
import { flexRowNoWrap } from 'theme/styles'
|
import { flexRowNoWrap } from 'theme/styles'
|
||||||
import { shortenAddress } from 'utils'
|
import { shortenAddress } from 'utils'
|
||||||
|
|
||||||
import { TransactionDetails } from '../../state/transactions/types'
|
|
||||||
import { ButtonSecondary } from '../Button'
|
import { ButtonSecondary } from '../Button'
|
||||||
import StatusIcon from '../Identicon/StatusIcon'
|
import StatusIcon from '../Identicon/StatusIcon'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
@ -115,11 +114,6 @@ const Text = styled.p`
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
`
|
`
|
||||||
|
|
||||||
// we want the latest one to come first, so return negative if a is after b
|
|
||||||
function newTransactionsFirst(a: TransactionDetails, b: TransactionDetails) {
|
|
||||||
return b.addedTime - a.addedTime
|
|
||||||
}
|
|
||||||
|
|
||||||
const StyledConnectButton = styled.button`
|
const StyledConnectButton = styled.button`
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -5,6 +5,8 @@ import polygonCircleLogoUrl from 'assets/images/polygonCircle.png'
|
|||||||
import { default as arbitrumCircleLogoUrl, default as arbitrumLogoUrl } from 'assets/svg/arbitrum_logo.svg'
|
import { default as arbitrumCircleLogoUrl, default as arbitrumLogoUrl } from 'assets/svg/arbitrum_logo.svg'
|
||||||
import avaxLogo from 'assets/svg/avax_logo.svg'
|
import avaxLogo from 'assets/svg/avax_logo.svg'
|
||||||
import avaxSquareLogo from 'assets/svg/avax_square_logo.svg'
|
import avaxSquareLogo from 'assets/svg/avax_square_logo.svg'
|
||||||
|
import baseLogo from 'assets/svg/base_logo.svg'
|
||||||
|
import baseSquareLogo from 'assets/svg/base_square_logo.svg'
|
||||||
import bnbSquareLogoUrl from 'assets/svg/bnb_square_logo.svg'
|
import bnbSquareLogoUrl from 'assets/svg/bnb_square_logo.svg'
|
||||||
import bnbLogo from 'assets/svg/bnb-logo.svg'
|
import bnbLogo from 'assets/svg/bnb-logo.svg'
|
||||||
import celoLogo from 'assets/svg/celo_logo.svg'
|
import celoLogo from 'assets/svg/celo_logo.svg'
|
||||||
@ -17,7 +19,7 @@ import ms from 'ms.macro'
|
|||||||
import { darkTheme } from 'theme/colors'
|
import { darkTheme } from 'theme/colors'
|
||||||
|
|
||||||
import { SupportedL1ChainId, SupportedL2ChainId } from './chains'
|
import { SupportedL1ChainId, SupportedL2ChainId } from './chains'
|
||||||
import { ARBITRUM_LIST, AVALANCHE_LIST, CELO_LIST, OPTIMISM_LIST, PLASMA_BNB_LIST } from './lists'
|
import { ARBITRUM_LIST, AVALANCHE_LIST, BASE_LIST, CELO_LIST, OPTIMISM_LIST, PLASMA_BNB_LIST } from './lists'
|
||||||
|
|
||||||
export const AVERAGE_L1_BLOCK_TIME = ms`12s`
|
export const AVERAGE_L1_BLOCK_TIME = ms`12s`
|
||||||
|
|
||||||
@ -241,13 +243,55 @@ const CHAIN_INFO: ChainInfoMap = {
|
|||||||
color: darkTheme.chain_43114,
|
color: darkTheme.chain_43114,
|
||||||
backgroundColor: darkTheme.chain_43114_background,
|
backgroundColor: darkTheme.chain_43114_background,
|
||||||
},
|
},
|
||||||
|
[ChainId.BASE]: {
|
||||||
|
networkType: NetworkType.L2,
|
||||||
|
blockWaitMsBeforeWarning: ms`25m`,
|
||||||
|
bridge: 'https://bridge.base.org/deposit',
|
||||||
|
defaultListUrl: BASE_LIST,
|
||||||
|
docs: 'https://docs.base.org',
|
||||||
|
explorer: 'https://basescan.org/',
|
||||||
|
infoLink: 'https://info.uniswap.org/#/base/',
|
||||||
|
label: 'Base',
|
||||||
|
logoUrl: baseLogo,
|
||||||
|
statusPage: 'https://status.base.org/',
|
||||||
|
circleLogoUrl: baseLogo,
|
||||||
|
squareLogoUrl: baseSquareLogo,
|
||||||
|
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
|
||||||
|
color: darkTheme.chain_84531,
|
||||||
|
},
|
||||||
|
[ChainId.BASE_GOERLI]: {
|
||||||
|
networkType: NetworkType.L2,
|
||||||
|
blockWaitMsBeforeWarning: ms`25m`,
|
||||||
|
bridge: 'https://goerli-bridge.base.org/deposit',
|
||||||
|
defaultListUrl: BASE_LIST,
|
||||||
|
docs: 'https://docs.base.org',
|
||||||
|
explorer: 'https://goerli.basescan.org/',
|
||||||
|
infoLink: 'https://info.uniswap.org/#/base/', // base testnet not supported
|
||||||
|
label: 'Base Goerli',
|
||||||
|
logoUrl: baseLogo,
|
||||||
|
statusPage: 'https://status.base.org/',
|
||||||
|
circleLogoUrl: baseLogo,
|
||||||
|
squareLogoUrl: baseSquareLogo,
|
||||||
|
nativeCurrency: { name: 'Base Goerli Ether', symbol: 'ETH', decimals: 18 },
|
||||||
|
color: darkTheme.chain_84531,
|
||||||
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export function getChainInfo(chainId: SupportedL1ChainId): L1ChainInfo
|
|
||||||
export function getChainInfo(chainId: SupportedL2ChainId): L2ChainInfo
|
|
||||||
export function getChainInfo(chainId: ChainId): L1ChainInfo | L2ChainInfo
|
|
||||||
export function getChainInfo(
|
export function getChainInfo(
|
||||||
chainId: ChainId | SupportedL1ChainId | SupportedL2ChainId | number | undefined
|
chainId: SupportedL1ChainId,
|
||||||
|
featureFlags?: Record<ChainId | SupportedL1ChainId | SupportedL2ChainId | number, boolean>
|
||||||
|
): L1ChainInfo
|
||||||
|
export function getChainInfo(
|
||||||
|
chainId: SupportedL2ChainId,
|
||||||
|
featureFlags?: Record<ChainId | SupportedL1ChainId | SupportedL2ChainId | number, boolean>
|
||||||
|
): L2ChainInfo
|
||||||
|
export function getChainInfo(
|
||||||
|
chainId: ChainId,
|
||||||
|
featureFlags?: Record<ChainId | SupportedL1ChainId | SupportedL2ChainId | number, boolean>
|
||||||
|
): L1ChainInfo | L2ChainInfo
|
||||||
|
export function getChainInfo(
|
||||||
|
chainId: ChainId | SupportedL1ChainId | SupportedL2ChainId | number | undefined,
|
||||||
|
featureFlags?: Record<ChainId | SupportedL1ChainId | SupportedL2ChainId | number, boolean>
|
||||||
): L1ChainInfo | L2ChainInfo | undefined
|
): L1ChainInfo | L2ChainInfo | undefined
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,7 +302,13 @@ export function getChainInfo(
|
|||||||
* SupportedL1ChainId -> returns L1ChainInfo
|
* SupportedL1ChainId -> returns L1ChainInfo
|
||||||
* SupportedL2ChainId -> returns L2ChainInfo
|
* SupportedL2ChainId -> returns L2ChainInfo
|
||||||
*/
|
*/
|
||||||
export function getChainInfo(chainId: any): any {
|
export function getChainInfo(
|
||||||
|
chainId: any,
|
||||||
|
featureFlags?: Record<ChainId | SupportedL1ChainId | SupportedL2ChainId | number, boolean>
|
||||||
|
): any {
|
||||||
|
if (featureFlags && chainId in featureFlags) {
|
||||||
|
return featureFlags[chainId] ? CHAIN_INFO[chainId] : undefined
|
||||||
|
}
|
||||||
if (chainId) {
|
if (chainId) {
|
||||||
return CHAIN_INFO[chainId] ?? undefined
|
return CHAIN_INFO[chainId] ?? undefined
|
||||||
}
|
}
|
||||||
@ -266,6 +316,6 @@ export function getChainInfo(chainId: any): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MAINNET_INFO = CHAIN_INFO[ChainId.MAINNET]
|
const MAINNET_INFO = CHAIN_INFO[ChainId.MAINNET]
|
||||||
export function getChainInfoOrDefault(chainId: number | undefined) {
|
export function getChainInfoOrDefault(chainId: number | undefined, featureFlags?: Record<number, boolean>) {
|
||||||
return getChainInfo(chainId) ?? MAINNET_INFO
|
return getChainInfo(chainId, featureFlags) ?? MAINNET_INFO
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,27 @@ export const CHAIN_IDS_TO_NAMES = {
|
|||||||
[ChainId.BASE_GOERLI]: 'base_goerli',
|
[ChainId.BASE_GOERLI]: 'base_goerli',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const NOT_YET_UX_SUPPORTED_CHAIN_IDS = [ChainId.BASE, ChainId.BASE_GOERLI] as const
|
// Include ChainIds in this array if they are not supported by the UX yet, but are already in the SDK.
|
||||||
|
const NOT_YET_UX_SUPPORTED_CHAIN_IDS: number[] = []
|
||||||
|
|
||||||
export function isSupportedChain(chainId: number | null | undefined | ChainId): chainId is SupportedChainsType {
|
export function isSupportedChain(
|
||||||
|
chainId: number | null | undefined | ChainId,
|
||||||
|
featureFlags?: Record<number, boolean>
|
||||||
|
): chainId is SupportedChainsType {
|
||||||
|
if (featureFlags && chainId && chainId in featureFlags) {
|
||||||
|
return featureFlags[chainId]
|
||||||
|
}
|
||||||
return !!chainId && SUPPORTED_CHAINS.indexOf(chainId) !== -1 && NOT_YET_UX_SUPPORTED_CHAIN_IDS.indexOf(chainId) === -1
|
return !!chainId && SUPPORTED_CHAINS.indexOf(chainId) !== -1 && NOT_YET_UX_SUPPORTED_CHAIN_IDS.indexOf(chainId) === -1
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asSupportedChain(chainId: number | null | undefined | ChainId): SupportedChainsType | undefined {
|
export function asSupportedChain(
|
||||||
|
chainId: number | null | undefined | ChainId,
|
||||||
|
featureFlags?: Record<number, boolean>
|
||||||
|
): SupportedChainsType | undefined {
|
||||||
|
if (!chainId) return undefined
|
||||||
|
if (featureFlags && chainId in featureFlags && !featureFlags[chainId]) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
return isSupportedChain(chainId) ? chainId : undefined
|
return isSupportedChain(chainId) ? chainId : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +52,7 @@ export const SUPPORTED_GAS_ESTIMATE_CHAIN_IDS = [
|
|||||||
ChainId.ARBITRUM_ONE,
|
ChainId.ARBITRUM_ONE,
|
||||||
ChainId.BNB,
|
ChainId.BNB,
|
||||||
ChainId.AVALANCHE,
|
ChainId.AVALANCHE,
|
||||||
|
ChainId.BASE,
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,6 +67,7 @@ export const TESTNET_CHAIN_IDS = [
|
|||||||
ChainId.ARBITRUM_GOERLI,
|
ChainId.ARBITRUM_GOERLI,
|
||||||
ChainId.OPTIMISM_GOERLI,
|
ChainId.OPTIMISM_GOERLI,
|
||||||
ChainId.CELO_ALFAJORES,
|
ChainId.CELO_ALFAJORES,
|
||||||
|
ChainId.BASE_GOERLI,
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,6 +96,8 @@ export const L2_CHAIN_IDS = [
|
|||||||
ChainId.ARBITRUM_GOERLI,
|
ChainId.ARBITRUM_GOERLI,
|
||||||
ChainId.OPTIMISM,
|
ChainId.OPTIMISM,
|
||||||
ChainId.OPTIMISM_GOERLI,
|
ChainId.OPTIMISM_GOERLI,
|
||||||
|
ChainId.BASE,
|
||||||
|
ChainId.BASE_GOERLI,
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
export type SupportedL2ChainId = (typeof L2_CHAIN_IDS)[number]
|
export type SupportedL2ChainId = (typeof L2_CHAIN_IDS)[number]
|
||||||
|
@ -24,6 +24,8 @@ export const CELO_LIST = 'https://celo-org.github.io/celo-token-list/celo.tokenl
|
|||||||
export const PLASMA_BNB_LIST = 'https://raw.githubusercontent.com/plasmadlt/plasma-finance-token-list/master/bnb.json'
|
export const PLASMA_BNB_LIST = 'https://raw.githubusercontent.com/plasmadlt/plasma-finance-token-list/master/bnb.json'
|
||||||
export const AVALANCHE_LIST =
|
export const AVALANCHE_LIST =
|
||||||
'https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/token_list.json'
|
'https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/token_list.json'
|
||||||
|
export const BASE_LIST =
|
||||||
|
'https://raw.githubusercontent.com/ethereum-optimism/ethereum-optimism.github.io/master/optimism.tokenlist.json'
|
||||||
|
|
||||||
export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST, UNI_UNSUPPORTED_LIST]
|
export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST, UNI_UNSUPPORTED_LIST]
|
||||||
|
|
||||||
@ -50,6 +52,7 @@ export const DEFAULT_INACTIVE_LIST_URLS: string[] = [
|
|||||||
CELO_LIST,
|
CELO_LIST,
|
||||||
PLASMA_BNB_LIST,
|
PLASMA_BNB_LIST,
|
||||||
AVALANCHE_LIST,
|
AVALANCHE_LIST,
|
||||||
|
BASE_LIST,
|
||||||
...UNSUPPORTED_LIST_URLS,
|
...UNSUPPORTED_LIST_URLS,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -4,10 +4,18 @@ const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
|
|||||||
if (typeof INFURA_KEY === 'undefined') {
|
if (typeof INFURA_KEY === 'undefined') {
|
||||||
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
|
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
|
||||||
}
|
}
|
||||||
const QUICKNODE_RPC_URL = process.env.REACT_APP_BNB_RPC_URL
|
const QUICKNODE_BNB_RPC_URL = process.env.REACT_APP_BNB_RPC_URL
|
||||||
if (typeof QUICKNODE_RPC_URL === 'undefined') {
|
if (typeof QUICKNODE_BNB_RPC_URL === 'undefined') {
|
||||||
throw new Error(`REACT_APP_BNB_RPC_URL must be a defined environment variable`)
|
throw new Error(`REACT_APP_BNB_RPC_URL must be a defined environment variable`)
|
||||||
}
|
}
|
||||||
|
const QUICKNODE_BASE_GOERLI_RPC_URL = process.env.REACT_APP_BASE_GOERLI_RPC_URL
|
||||||
|
if (typeof QUICKNODE_BASE_GOERLI_RPC_URL === 'undefined') {
|
||||||
|
throw new Error(`REACT_APP_BASE_GOERLI_RPC_URL must be a defined environment variable`)
|
||||||
|
}
|
||||||
|
const QUICKNODE_BASE_RPC_URL = process.env.REACT_APP_BASE_MAINNET_RPC_URL
|
||||||
|
if (typeof QUICKNODE_BASE_RPC_URL === 'undefined') {
|
||||||
|
throw new Error(`REACT_APP_BASE_MAINNET_RPC_URL must be a defined environment variable`)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fallback JSON-RPC endpoints.
|
* Fallback JSON-RPC endpoints.
|
||||||
@ -107,11 +115,19 @@ export const FALLBACK_URLS = {
|
|||||||
],
|
],
|
||||||
[ChainId.BASE]: [
|
[ChainId.BASE]: [
|
||||||
// "Safe" URLs
|
// "Safe" URLs
|
||||||
'https://developer-access-mainnet.base.org',
|
'https://mainnet.base.org',
|
||||||
|
// "Unsafe" URLs
|
||||||
|
QUICKNODE_BASE_RPC_URL,
|
||||||
|
'https://base-mainnet.blastapi.io/b5a802d8-151d-4443-90a7-699108dc4e01',
|
||||||
|
'https://svc.blockdaemon.com/base/mainnet/native?apiKey=zpka_1334e7c450464d06b6e33a972a7a4e57_75320f43',
|
||||||
],
|
],
|
||||||
[ChainId.BASE_GOERLI]: [
|
[ChainId.BASE_GOERLI]: [
|
||||||
// "Safe" URLs
|
// "Safe" URLs
|
||||||
'https://goerli.base.org',
|
'https://goerli.base.org',
|
||||||
|
// "Unsafe" URLs
|
||||||
|
QUICKNODE_BASE_GOERLI_RPC_URL,
|
||||||
|
'https://base-goerli.blastapi.io/b5a802d8-151d-4443-90a7-699108dc4e01',
|
||||||
|
'https://svc.blockdaemon.com/base/testnet/native?apiKey=zpka_1334e7c450464d06b6e33a972a7a4e57_75320f43',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +159,7 @@ export const RPC_URLS = {
|
|||||||
],
|
],
|
||||||
[ChainId.CELO]: FALLBACK_URLS[ChainId.CELO],
|
[ChainId.CELO]: FALLBACK_URLS[ChainId.CELO],
|
||||||
[ChainId.CELO_ALFAJORES]: FALLBACK_URLS[ChainId.CELO_ALFAJORES],
|
[ChainId.CELO_ALFAJORES]: FALLBACK_URLS[ChainId.CELO_ALFAJORES],
|
||||||
[ChainId.BNB]: [QUICKNODE_RPC_URL, ...FALLBACK_URLS[ChainId.BNB]],
|
[ChainId.BNB]: [QUICKNODE_BNB_RPC_URL, ...FALLBACK_URLS[ChainId.BNB]],
|
||||||
[ChainId.AVALANCHE]: [`https://avalanche-mainnet.infura.io/v3/${INFURA_KEY}`, ...FALLBACK_URLS[ChainId.AVALANCHE]],
|
[ChainId.AVALANCHE]: [`https://avalanche-mainnet.infura.io/v3/${INFURA_KEY}`, ...FALLBACK_URLS[ChainId.AVALANCHE]],
|
||||||
[ChainId.BASE]: [`https://base-mainnet.infura.io/v3/${INFURA_KEY}`, ...FALLBACK_URLS[ChainId.BASE]],
|
[ChainId.BASE]: [`https://base-mainnet.infura.io/v3/${INFURA_KEY}`, ...FALLBACK_URLS[ChainId.BASE]],
|
||||||
[ChainId.BASE_GOERLI]: [`https://base-goerli.infura.io/v3/${INFURA_KEY}`, ...FALLBACK_URLS[ChainId.BASE_GOERLI]],
|
[ChainId.BASE_GOERLI]: [`https://base-goerli.infura.io/v3/${INFURA_KEY}`, ...FALLBACK_URLS[ChainId.BASE_GOERLI]],
|
||||||
|
@ -37,6 +37,7 @@ import {
|
|||||||
USDC_ARBITRUM,
|
USDC_ARBITRUM,
|
||||||
USDC_ARBITRUM_GOERLI,
|
USDC_ARBITRUM_GOERLI,
|
||||||
USDC_AVALANCHE,
|
USDC_AVALANCHE,
|
||||||
|
USDC_BASE,
|
||||||
USDC_BSC,
|
USDC_BSC,
|
||||||
USDC_MAINNET,
|
USDC_MAINNET,
|
||||||
USDC_OPTIMISM,
|
USDC_OPTIMISM,
|
||||||
@ -161,6 +162,8 @@ export const COMMON_BASES: ChainCurrencyList = {
|
|||||||
],
|
],
|
||||||
[ChainId.OPTIMISM]: [nativeOnChain(ChainId.OPTIMISM), OP, DAI_OPTIMISM, USDC_OPTIMISM, USDT_OPTIMISM, WBTC_OPTIMISM],
|
[ChainId.OPTIMISM]: [nativeOnChain(ChainId.OPTIMISM), OP, DAI_OPTIMISM, USDC_OPTIMISM, USDT_OPTIMISM, WBTC_OPTIMISM],
|
||||||
[ChainId.OPTIMISM_GOERLI]: [nativeOnChain(ChainId.OPTIMISM_GOERLI)],
|
[ChainId.OPTIMISM_GOERLI]: [nativeOnChain(ChainId.OPTIMISM_GOERLI)],
|
||||||
|
[ChainId.BASE]: [nativeOnChain(ChainId.BASE), WRAPPED_NATIVE_CURRENCY[ChainId.BASE] as Token, USDC_BASE],
|
||||||
|
[ChainId.BASE_GOERLI]: [nativeOnChain(ChainId.BASE_GOERLI), WRAPPED_NATIVE_CURRENCY[ChainId.BASE_GOERLI] as Token],
|
||||||
[ChainId.POLYGON]: [
|
[ChainId.POLYGON]: [
|
||||||
nativeOnChain(ChainId.POLYGON),
|
nativeOnChain(ChainId.POLYGON),
|
||||||
WETH_POLYGON,
|
WETH_POLYGON,
|
||||||
|
@ -73,6 +73,13 @@ export const PORTAL_USDC_CELO = new Token(
|
|||||||
'USDCet',
|
'USDCet',
|
||||||
'USDC (Portal from Ethereum)'
|
'USDC (Portal from Ethereum)'
|
||||||
)
|
)
|
||||||
|
export const USDC_BASE = new Token(
|
||||||
|
ChainId.BASE,
|
||||||
|
'0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA',
|
||||||
|
6,
|
||||||
|
'USD Base Coin',
|
||||||
|
'USDbC'
|
||||||
|
)
|
||||||
export const AMPL = new Token(ChainId.MAINNET, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
export const AMPL = new Token(ChainId.MAINNET, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
||||||
export const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
export const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
||||||
export const DAI_ARBITRUM_ONE = new Token(
|
export const DAI_ARBITRUM_ONE = new Token(
|
||||||
@ -298,6 +305,14 @@ export const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token | undefined } =
|
|||||||
'WETH',
|
'WETH',
|
||||||
'Wrapped Ether'
|
'Wrapped Ether'
|
||||||
),
|
),
|
||||||
|
[ChainId.BASE]: new Token(ChainId.BASE, '0x4200000000000000000000000000000000000006', 18, 'WETH', 'Wrapped Ether'),
|
||||||
|
[ChainId.BASE_GOERLI]: new Token(
|
||||||
|
ChainId.BASE_GOERLI,
|
||||||
|
'0x4200000000000000000000000000000000000006',
|
||||||
|
18,
|
||||||
|
'WETH',
|
||||||
|
'Wrapped Ether'
|
||||||
|
),
|
||||||
[ChainId.ARBITRUM_ONE]: new Token(
|
[ChainId.ARBITRUM_ONE]: new Token(
|
||||||
ChainId.ARBITRUM_ONE,
|
ChainId.ARBITRUM_ONE,
|
||||||
'0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
|
'0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
|
||||||
|
19
src/featureFlags/flags/baseEnabled.ts
Normal file
19
src/featureFlags/flags/baseEnabled.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { ChainId } from '@uniswap/sdk-core'
|
||||||
|
|
||||||
|
import { BaseVariant, FeatureFlag, useBaseFlag } from '../index'
|
||||||
|
|
||||||
|
export function useBaseEnabledFlag(): BaseVariant {
|
||||||
|
return useBaseFlag(FeatureFlag.baseEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useBaseEnabled(): boolean {
|
||||||
|
return useBaseEnabledFlag() === BaseVariant.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useBaseEnabledChains(): Record<number, boolean> {
|
||||||
|
const baseEnabled = useBaseEnabled()
|
||||||
|
return {
|
||||||
|
[ChainId.BASE]: baseEnabled,
|
||||||
|
[ChainId.BASE_GOERLI]: baseEnabled,
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ export enum FeatureFlag {
|
|||||||
uniswapXSyntheticQuote = 'uniswapx_synthetic_quote',
|
uniswapXSyntheticQuote = 'uniswapx_synthetic_quote',
|
||||||
routingAPIPrice = 'routing_api_price',
|
routingAPIPrice = 'routing_api_price',
|
||||||
forceUniswapXOn = 'uniswapx_force_on', // forces routing-api's feature flag for uniswapx to turn on as well
|
forceUniswapXOn = 'uniswapx_force_on', // forces routing-api's feature flag for uniswapx to turn on as well
|
||||||
|
baseEnabled = 'base_enabled',
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FeatureFlagsContextType {
|
interface FeatureFlagsContextType {
|
||||||
|
@ -184,7 +184,7 @@ export const BACKEND_SUPPORTED_CHAINS = [
|
|||||||
Chain.Optimism,
|
Chain.Optimism,
|
||||||
Chain.Celo,
|
Chain.Celo,
|
||||||
] as const
|
] as const
|
||||||
export const BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS = [ChainId.BNB, ChainId.AVALANCHE] as const
|
export const BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS = [ChainId.BNB, ChainId.AVALANCHE, ChainId.BASE] as const
|
||||||
|
|
||||||
export function getTokenDetailsURL({
|
export function getTokenDetailsURL({
|
||||||
address,
|
address,
|
||||||
|
@ -10,6 +10,7 @@ import PositionList from 'components/PositionList'
|
|||||||
import { RowBetween, RowFixed } from 'components/Row'
|
import { RowBetween, RowFixed } from 'components/Row'
|
||||||
import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
|
import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
|
||||||
import { isSupportedChain } from 'constants/chains'
|
import { isSupportedChain } from 'constants/chains'
|
||||||
|
import { useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import { useFilterPossiblyMaliciousPositions } from 'hooks/useFilterPossiblyMaliciousPositions'
|
import { useFilterPossiblyMaliciousPositions } from 'hooks/useFilterPossiblyMaliciousPositions'
|
||||||
import { useNetworkSupportsV2 } from 'hooks/useNetworkSupportsV2'
|
import { useNetworkSupportsV2 } from 'hooks/useNetworkSupportsV2'
|
||||||
import { useV3Positions } from 'hooks/useV3Positions'
|
import { useV3Positions } from 'hooks/useV3Positions'
|
||||||
@ -212,8 +213,9 @@ export default function Pool() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const filteredPositions = useFilterPossiblyMaliciousPositions(userSelectedPositionSet)
|
const filteredPositions = useFilterPossiblyMaliciousPositions(userSelectedPositionSet)
|
||||||
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
|
||||||
if (!isSupportedChain(chainId)) {
|
if (!isSupportedChain(chainId, baseEnabledChains)) {
|
||||||
return <WrongNetworkCard />
|
return <WrongNetworkCard />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal'
|
|||||||
import { getChainInfo } from 'constants/chainInfo'
|
import { getChainInfo } from 'constants/chainInfo'
|
||||||
import { asSupportedChain, isSupportedChain } from 'constants/chains'
|
import { asSupportedChain, isSupportedChain } from 'constants/chains'
|
||||||
import { getSwapCurrencyId, TOKEN_SHORTHANDS } from 'constants/tokens'
|
import { getSwapCurrencyId, TOKEN_SHORTHANDS } from 'constants/tokens'
|
||||||
|
import { useBaseEnabledChains } from 'featureFlags/flags/baseEnabled'
|
||||||
import { useCurrency, useDefaultActiveTokens } from 'hooks/Tokens'
|
import { useCurrency, useDefaultActiveTokens } from 'hooks/Tokens'
|
||||||
import { useIsSwapUnsupported } from 'hooks/useIsSwapUnsupported'
|
import { useIsSwapUnsupported } from 'hooks/useIsSwapUnsupported'
|
||||||
import { useMaxAmountIn } from 'hooks/useMaxAmountIn'
|
import { useMaxAmountIn } from 'hooks/useMaxAmountIn'
|
||||||
@ -135,19 +136,23 @@ function largerPercentValue(a?: Percent, b?: Percent) {
|
|||||||
export default function SwapPage({ className }: { className?: string }) {
|
export default function SwapPage({ className }: { className?: string }) {
|
||||||
const { chainId: connectedChainId } = useWeb3React()
|
const { chainId: connectedChainId } = useWeb3React()
|
||||||
const loadedUrlParams = useDefaultsFromURLSearch()
|
const loadedUrlParams = useDefaultsFromURLSearch()
|
||||||
|
const baseEnabledChains = useBaseEnabledChains()
|
||||||
|
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
const supportedChainId = asSupportedChain(connectedChainId, baseEnabledChains)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Trace page={InterfacePageName.SWAP_PAGE} shouldLogImpression>
|
<Trace page={InterfacePageName.SWAP_PAGE} shouldLogImpression>
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<Swap
|
<Swap
|
||||||
className={className}
|
className={className}
|
||||||
chainId={connectedChainId}
|
chainId={supportedChainId ?? ChainId.MAINNET}
|
||||||
prefilledState={{
|
prefilledState={{
|
||||||
[Field.INPUT]: { currencyId: loadedUrlParams?.[Field.INPUT]?.currencyId },
|
[Field.INPUT]: { currencyId: loadedUrlParams?.[Field.INPUT]?.currencyId },
|
||||||
[Field.OUTPUT]: { currencyId: loadedUrlParams?.[Field.OUTPUT]?.currencyId },
|
[Field.OUTPUT]: { currencyId: loadedUrlParams?.[Field.OUTPUT]?.currencyId },
|
||||||
}}
|
}}
|
||||||
|
disableTokenInputs={supportedChainId === undefined}
|
||||||
/>
|
/>
|
||||||
<NetworkAlert />
|
<NetworkAlert />
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
|
@ -97,6 +97,7 @@ export const colors = {
|
|||||||
networkBsc: '#F0B90B',
|
networkBsc: '#F0B90B',
|
||||||
networkPolygonSoft: 'rgba(164, 87, 255, 0.16)',
|
networkPolygonSoft: 'rgba(164, 87, 255, 0.16)',
|
||||||
networkEthereumSoft: 'rgba(98, 126, 234, 0.16)',
|
networkEthereumSoft: 'rgba(98, 126, 234, 0.16)',
|
||||||
|
networkBase: '#0052FF',
|
||||||
}
|
}
|
||||||
|
|
||||||
type Theme = typeof darkTheme
|
type Theme = typeof darkTheme
|
||||||
@ -122,6 +123,7 @@ const commonTheme = {
|
|||||||
chain_10_background: colors.red900,
|
chain_10_background: colors.red900,
|
||||||
chain_43114_background: colors.red900,
|
chain_43114_background: colors.red900,
|
||||||
chain_42161_background: colors.blue900,
|
chain_42161_background: colors.blue900,
|
||||||
|
chain_84531: colors.networkBase,
|
||||||
chain_56_background: colors.networkBsc,
|
chain_56_background: colors.networkBsc,
|
||||||
promotional: colors.magenta300,
|
promotional: colors.magenta300,
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ChainId } from '@uniswap/sdk-core'
|
import { ChainId } from '@uniswap/sdk-core'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { useBaseEnabled } from 'featureFlags/flags/baseEnabled'
|
||||||
import { useIsNftPage } from 'hooks/useIsNftPage'
|
import { useIsNftPage } from 'hooks/useIsNftPage'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useDarkModeManager } from 'theme/components/ThemeToggle'
|
import { useDarkModeManager } from 'theme/components/ThemeToggle'
|
||||||
@ -27,10 +28,19 @@ const setBackground = (newValues: TargetBackgroundStyles) =>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function setDefaultBackground(backgroundRadialGradientElement: HTMLElement, darkMode?: boolean) {
|
||||||
|
setBackground(initialStyles)
|
||||||
|
const defaultLightGradient =
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(255, 184, 226, 0.51) 0%, rgba(255, 255, 255, 0) 100%), #FFFFFF'
|
||||||
|
const defaultDarkGradient = 'linear-gradient(180deg, #202738 0%, #070816 100%)'
|
||||||
|
backgroundRadialGradientElement.style.background = darkMode ? defaultDarkGradient : defaultLightGradient
|
||||||
|
}
|
||||||
|
|
||||||
export default function RadialGradientByChainUpdater(): null {
|
export default function RadialGradientByChainUpdater(): null {
|
||||||
const { chainId } = useWeb3React()
|
const { chainId } = useWeb3React()
|
||||||
const [darkMode] = useDarkModeManager()
|
const [darkMode] = useDarkModeManager()
|
||||||
const isNftPage = useIsNftPage()
|
const isNftPage = useIsNftPage()
|
||||||
|
const baseEnabled = useBaseEnabled()
|
||||||
|
|
||||||
// manage background color
|
// manage background color
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -105,14 +115,24 @@ export default function RadialGradientByChainUpdater(): null {
|
|||||||
backgroundRadialGradientElement.style.background = darkMode ? avaxDarkGradient : avaxLightGradient
|
backgroundRadialGradientElement.style.background = darkMode ? avaxDarkGradient : avaxLightGradient
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case ChainId.BASE:
|
||||||
|
case ChainId.BASE_GOERLI: {
|
||||||
|
if (!baseEnabled) {
|
||||||
|
setDefaultBackground(backgroundRadialGradientElement, darkMode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setBackground(backgroundResetStyles)
|
||||||
|
const baseLightGradient =
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(0, 82, 255, 0.20) 0%, rgba(0, 82, 255, 0.08) 40.0%, rgba(252, 255, 82, 0.00) 100%), rgb(255, 255, 255)'
|
||||||
|
const baseDarkGradient =
|
||||||
|
'radial-gradient(100% 100% at 50% 0%, rgba(10, 41, 75, 0.7) 0%, rgba(0, 82, 255, .1) 40%, rgba(0, 82, 255, 0) 100%), rgb(13, 14, 14)'
|
||||||
|
backgroundRadialGradientElement.style.background = darkMode ? baseDarkGradient : baseLightGradient
|
||||||
|
break
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
setBackground(initialStyles)
|
setDefaultBackground(backgroundRadialGradientElement, darkMode)
|
||||||
const defaultLightGradient =
|
|
||||||
'radial-gradient(100% 100% at 50% 0%, rgba(255, 184, 226, 0.51) 0%, rgba(255, 255, 255, 0) 100%), #FFFFFF'
|
|
||||||
const defaultDarkGradient = 'linear-gradient(180deg, #202738 0%, #070816 100%)'
|
|
||||||
backgroundRadialGradientElement.style.background = darkMode ? defaultDarkGradient : defaultLightGradient
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [darkMode, chainId, isNftPage])
|
}, [darkMode, chainId, isNftPage, baseEnabled])
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,12 @@ describe('#getExplorerLink', () => {
|
|||||||
'https://snowtrace.io/address/abc'
|
'https://snowtrace.io/address/abc'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
it('base', () => {
|
||||||
|
expect(getExplorerLink(ChainId.BASE, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://basescan.org/address/abc')
|
||||||
|
})
|
||||||
|
it('base goerli', () => {
|
||||||
|
expect(getExplorerLink(ChainId.BASE_GOERLI, 'abc', ExplorerDataType.ADDRESS)).toEqual(
|
||||||
|
'https://goerli.basescan.org/address/abc'
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -12,6 +12,8 @@ const BLOCK_EXPLORER_PREFIXES: { [chainId: number]: string } = {
|
|||||||
[ChainId.CELO_ALFAJORES]: 'https://alfajores-blockscout.celo-testnet.org',
|
[ChainId.CELO_ALFAJORES]: 'https://alfajores-blockscout.celo-testnet.org',
|
||||||
[ChainId.BNB]: 'https://bscscan.com',
|
[ChainId.BNB]: 'https://bscscan.com',
|
||||||
[ChainId.AVALANCHE]: 'https://snowtrace.io',
|
[ChainId.AVALANCHE]: 'https://snowtrace.io',
|
||||||
|
[ChainId.BASE]: 'https://basescan.org',
|
||||||
|
[ChainId.BASE_GOERLI]: 'https://goerli.basescan.org',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ExplorerDataType {
|
export enum ExplorerDataType {
|
||||||
|
11
yarn.lock
11
yarn.lock
@ -6307,7 +6307,7 @@
|
|||||||
"@uniswap/v2-sdk" "^3.2.0"
|
"@uniswap/v2-sdk" "^3.2.0"
|
||||||
"@uniswap/v3-sdk" "^3.10.0"
|
"@uniswap/v3-sdk" "^3.10.0"
|
||||||
|
|
||||||
"@uniswap/sdk-core@>= 3", "@uniswap/sdk-core@^4", "@uniswap/sdk-core@^4.0.0", "@uniswap/sdk-core@^4.0.2", "@uniswap/sdk-core@^4.0.3":
|
"@uniswap/sdk-core@>= 3", "@uniswap/sdk-core@^4", "@uniswap/sdk-core@^4.0.0", "@uniswap/sdk-core@^4.0.2", "@uniswap/sdk-core@^4.0.3", "@uniswap/sdk-core@^4.0.6":
|
||||||
version "4.0.6"
|
version "4.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-4.0.6.tgz#7b6d562f54293bbe0a9d101fb84e619db325f7b6"
|
resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-4.0.6.tgz#7b6d562f54293bbe0a9d101fb84e619db325f7b6"
|
||||||
integrity sha512-6GzCVfnOiJtvo91zlF/VjnC2OEbBRThVclzrh7+Zmo8dBovXwSlXwqn3RkSWACn/XEOzAKH70TficfOWm6mWJA==
|
integrity sha512-6GzCVfnOiJtvo91zlF/VjnC2OEbBRThVclzrh7+Zmo8dBovXwSlXwqn3RkSWACn/XEOzAKH70TficfOWm6mWJA==
|
||||||
@ -6319,14 +6319,15 @@
|
|||||||
tiny-invariant "^1.1.0"
|
tiny-invariant "^1.1.0"
|
||||||
toformat "^2.0.0"
|
toformat "^2.0.0"
|
||||||
|
|
||||||
"@uniswap/smart-order-router@^3.13.7":
|
"@uniswap/smart-order-router@^3.15.0":
|
||||||
version "3.13.7"
|
version "3.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/@uniswap/smart-order-router/-/smart-order-router-3.13.7.tgz#0355402b4459a3a8e78a2dc68c1c6aa7d4386b5c"
|
resolved "https://registry.yarnpkg.com/@uniswap/smart-order-router/-/smart-order-router-3.15.0.tgz#f9e1f7ecdf48b9bae7c182acb99289e3ee1acce3"
|
||||||
integrity sha512-fJDyUngHWw2lH0qIkDzeUqHgP2VLAq33o5O9yM75nQi6LrD8fEIgsfdzFbF8c+F7enAFtA6Xl4lf5AlHKNaXSg==
|
integrity sha512-H2IY4U+gQQ9E5mqYbv6uJWpTBGMkQ/tLKCdwfyL875bhTrGXunur0/7HurCW0BFIN3aEz6PqzJG+6QKg3hVCAQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@uniswap/default-token-list" "^11.2.0"
|
"@uniswap/default-token-list" "^11.2.0"
|
||||||
"@uniswap/permit2-sdk" "^1.2.0"
|
"@uniswap/permit2-sdk" "^1.2.0"
|
||||||
"@uniswap/router-sdk" "^1.6.0"
|
"@uniswap/router-sdk" "^1.6.0"
|
||||||
|
"@uniswap/sdk-core" "^4.0.6"
|
||||||
"@uniswap/swap-router-contracts" "^1.3.0"
|
"@uniswap/swap-router-contracts" "^1.3.0"
|
||||||
"@uniswap/token-lists" "^1.0.0-beta.31"
|
"@uniswap/token-lists" "^1.0.0-beta.31"
|
||||||
"@uniswap/universal-router" "^1.0.1"
|
"@uniswap/universal-router" "^1.0.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user