Commit 4ba9d98e authored by Jordan Frankfurt's avatar Jordan Frankfurt Committed by GitHub

fix(L2): polish (#1988)

* polish

move getINfoLinkByChainId to chain constants

pr review - translations

optimism token list, typo, text color for L1 switch

use <Trans /> instead of t

undo unintentional tokenlist order change

use {'Optimism'} instead of {name}

switch deadline implementation

remove unused TYPE import

switch to generalized CHAIN_INFO instead of L2_INFO so we don't have to check in components

add target chain id param to optimism bridge

fix a minor breakpoint issue

reduce sigfigs for header balance

update network card dropdown text for optimism

remove list code

refactor SupportedChainId

* SupportedL1ChainId | SupportedL2ChainId -> SupportedChainId
parent 52790ac9
......@@ -9,10 +9,10 @@ import { useModalOpen, useToggleModal } from 'state/application/hooks'
import styled, { css } from 'styled-components/macro'
import { ExternalLink, MEDIA_WIDTHS } from 'theme'
import { switchToNetwork } from 'utils/switchToNetwork'
import { L2_CHAIN_IDS, L2_INFO, NETWORK_LABELS, SupportedChainId } from '../../constants/chains'
import { CHAIN_INFO, L2_CHAIN_IDS, NETWORK_LABELS, SupportedChainId, SupportedL2ChainId } from '../../constants/chains'
const StopOverflowQuery = `@media screen and (min-width: ${MEDIA_WIDTHS.upToMedium}px) and (max-width: ${
MEDIA_WIDTHS.upToMedium + 400
const StopOverflowQuery = `@media screen and (min-width: ${MEDIA_WIDTHS.upToMedium + 1}px) and (max-width: ${
MEDIA_WIDTHS.upToMedium + 500
}px)`
const BaseWrapper = css`
......@@ -81,7 +81,7 @@ const L1Tag = styled.div`
color: #c4d9f8;
opacity: 40%;
`
const L2Tag = styled.div<{ chainId: SupportedChainId }>`
const L2Tag = styled.div<{ chainId: SupportedL2ChainId }>`
background-color: ${({ chainId }) => (chainId === SupportedChainId.ARBITRUM_ONE ? '#28A0F0' : '#FF0420')};
border-radius: 6px;
color: white;
......@@ -131,8 +131,10 @@ const MenuItem = styled(ExternalLink)`
const ButtonMenuItem = styled.button`
${BaseMenuItem}
border: none;
outline: none;
box-shadow: none;
color: ${({ theme }) => theme.text2};
outline: none;
padding-left: 0;
`
const NetworkInfo = styled.button`
align-items: center;
......@@ -143,11 +145,12 @@ const NetworkInfo = styled.button`
display: flex;
flex-direction: row;
font-weight: 500;
font-size: 12px;
height: 100%;
justify-content: space-between;
margin: 0;
padding: 8px;
width: 172px;
width: 188px;
:hover,
:focus {
......@@ -156,6 +159,9 @@ const NetworkInfo = styled.button`
background-color: ${({ theme }) => theme.bg3};
}
`
const NetworkLabel = styled.span`
flex: 1 1 auto;
`
export default function NetworkCard() {
const { chainId, library } = useActiveWeb3React()
......@@ -182,26 +188,23 @@ export default function NetworkCard() {
}
if (L2_CHAIN_IDS.includes(chainId)) {
const info = L2_INFO[chainId]
const info = CHAIN_INFO[chainId as SupportedL2ChainId]
const isArbitrum = [SupportedChainId.ARBITRUM_ONE, SupportedChainId.ARBITRUM_RINKEBY].includes(chainId)
return (
<L2Wrapper ref={node}>
<NetworkInfo onClick={toggle}>
<Icon src={info.logoUrl} />
<span>{NETWORK_LABELS[chainId]}</span>
<L2Tag chainId={chainId}>L2 Alpha</L2Tag>
<NetworkLabel>{info.label}</NetworkLabel>
<L2Tag chainId={chainId}>L2</L2Tag>
</NetworkInfo>
{open && (
<MenuFlyout>
<MenuItem href={info.bridge}>
<div>
<Trans>{NETWORK_LABELS[chainId]} Bridge</Trans>
</div>
<div>{isArbitrum ? <Trans>{info.label} Bridge</Trans> : <Trans>Optimism Gateway</Trans>}</div>
<LinkOutCircle />
</MenuItem>
<MenuItem href={info.explorer}>
<div>
<Trans>{NETWORK_LABELS[chainId]} Explorer</Trans>
</div>
{isArbitrum ? <Trans>{info.label} Explorer</Trans> : <Trans>Etherscan</Trans>}
<LinkOutCircle />
</MenuItem>
<MenuItem href={info.docs}>
......
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { useMemo } from 'react'
import { X } from 'react-feather'
import styled from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { UNI } from '../../constants/tokens'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks/web3'
import { useMerkleDistributorContract } from '../../hooks/useContract'
import useCurrentBlockTimestamp from '../../hooks/useCurrentBlockTimestamp'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import useUSDCPrice from '../../hooks/useUSDCPrice'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTotalUniEarned } from '../../state/stake/hooks'
import { useAggregateUniBalance, useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, StyledInternalLink, TYPE, UniTokenAnimated } from '../../theme'
import { computeUniCirculation } from '../../utils/computeUniCirculation'
import useUSDCPrice from '../../hooks/useUSDCPrice'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
import { Break, CardBGImage, CardNoise, CardSection, DataCard } from '../earn/styled'
import { Trans } from '@lingui/macro'
import { RowBetween } from '../Row'
const ContentWrapper = styled(AutoColumn)`
width: 100%;
......@@ -59,6 +60,8 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
[blockTimestamp, chainId, totalSupply, unclaimedUni, uni]
)
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (
<ContentWrapper gap="lg">
<ModalUpper>
......@@ -128,7 +131,7 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
<TYPE.white color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
{uni && uni.chainId === 1 ? (
<ExternalLink href={`https://info.uniswap.org/token/${uni.address}`}>
<ExternalLink href={`${infoLink}/token/${uni.address}`}>
<Trans>View UNI Analytics</Trans>
</ExternalLink>
) : null}
......
import { Trans } from '@lingui/macro'
import useScrollPosition from '@react-hook/window-scroll'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { darken } from 'polished'
import { useState } from 'react'
import { Moon, Sun } from 'react-feather'
......@@ -285,7 +286,7 @@ const StyledMenuButton = styled.button`
`
export default function Header() {
const { account } = useActiveWeb3React()
const { account, chainId } = useActiveWeb3React()
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
// const [isDark] = useDarkModeManager()
......@@ -302,6 +303,7 @@ export default function Header() {
const scrollY = useScrollPosition()
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (
<HeaderFrame showBackground={scrollY > 45}>
<ClaimModal />
......@@ -335,7 +337,7 @@ export default function Header() {
<StyledNavLink id={`stake-nav-link`} to={'/vote'}>
<Trans>Vote</Trans>
</StyledNavLink>
<StyledExternalLink id={`stake-nav-link`} href={'https://info.uniswap.org'}>
<StyledExternalLink id={`stake-nav-link`} href={infoLink}>
<Trans>Charts</Trans>
<sup></sup>
</StyledExternalLink>
......@@ -364,7 +366,7 @@ export default function Header() {
<AccountElement active={!!account} style={{ pointerEvents: 'auto' }}>
{account && userEthBalance ? (
<BalanceText style={{ flexShrink: 0 }} pl="0.75rem" pr="0.5rem" fontWeight={500}>
<Trans>{userEthBalance?.toSignificant(4)} ETH</Trans>
<Trans>{userEthBalance?.toSignificant(3)} ETH</Trans>
</BalanceText>
) : null}
<Web3Status />
......
......@@ -10,7 +10,7 @@ import { useModalOpen, useToggleModal } from '../../state/application/hooks'
import { Trans } from '@lingui/macro'
import { ExternalLink } from '../../theme'
import { ButtonPrimary } from '../Button'
import { L2_CHAIN_IDS } from 'constants/chains'
import { L2_CHAIN_IDS, CHAIN_INFO, SupportedChainId } from 'constants/chains'
export enum FlyoutAlignment {
LEFT = 'LEFT',
......@@ -133,7 +133,7 @@ export default function Menu() {
useOnClickOutside(node, open ? toggle : undefined)
const openClaimModal = useToggleModal(ApplicationModal.ADDRESS_CLAIM)
const showUNIClaimOption = Boolean(!!account && !!chainId && !L2_CHAIN_IDS.includes(chainId))
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451
<StyledMenu ref={node as any}>
......@@ -167,7 +167,7 @@ export default function Menu() {
<Trans>Discord</Trans>
</div>
</MenuItem>
<MenuItem href="https://info.uniswap.org/">
<MenuItem href={infoLink}>
<PieChart size={14} />
<div>
<Trans>Analytics</Trans>
......
......@@ -5,7 +5,7 @@ import {
OptimismWrapperBackgroundDarkMode,
OptimismWrapperBackgroundLightMode,
} from 'components/NetworkAlert/NetworkAlert'
import { L2_CHAIN_IDS, L2_INFO, NETWORK_LABELS, SupportedChainId } from 'constants/chains'
import { CHAIN_INFO, L2_CHAIN_IDS, NETWORK_LABELS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { ArrowDownCircle } from 'react-feather'
import { useArbitrumAlphaAlert, useDarkModeManager } from 'state/user/hooks'
......@@ -27,9 +27,9 @@ const DesktopTextBreak = styled.div`
display: block;
}
`
const Wrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean; logoUrl: string }>`
const Wrapper = styled.div<{ chainId: SupportedL2ChainId; darkMode: boolean; logoUrl: string }>`
${({ chainId, darkMode }) =>
chainId === SupportedChainId.OPTIMISM
[SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
? darkMode
? OptimismWrapperBackgroundDarkMode
: OptimismWrapperBackgroundLightMode
......@@ -62,18 +62,19 @@ const Wrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean; logoU
}
`
const Body = styled.div`
font-size: 12px;
line-height: 143%;
margin: 12px;
@media screen and (min-width: ${MEDIA_WIDTHS.upToSmall}px) {
margin: 16px 20px 31px;
flex: 1 1 auto;
margin: 0;
margin: auto 0;
}
`
const LinkOutCircle = styled(ArrowDownCircle)`
transform: rotate(230deg);
width: 20px;
height: 20px;
margin-left: 12px;
`
const LinkOutToBridge = styled.a`
align-items: center;
......@@ -81,10 +82,11 @@ const LinkOutToBridge = styled.a`
border-radius: 16px;
color: white;
display: flex;
font-size: 14px;
justify-content: space-between;
margin: 0;
max-height: 47px;
padding: 14px;
padding: 16px 8px;
text-decoration: none;
width: auto;
:hover,
......@@ -106,15 +108,18 @@ export function MinimalNetworkAlert() {
if (!chainId || !L2_CHAIN_IDS.includes(chainId) || arbitrumAlphaAcknowledged) {
return null
}
const info = L2_INFO[chainId]
const info = CHAIN_INFO[chainId as SupportedL2ChainId]
const depositUrl = [SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
? `${info.bridge}?chainId=1`
: info.bridge
return (
<Wrapper darkMode={darkMode} chainId={chainId} logoUrl={info.logoUrl}>
<L2Icon src={info.logoUrl} />
<Body>
<Trans>This is an alpha release of Uniswap on the {NETWORK_LABELS[chainId]} network.</Trans>
<DesktopTextBreak /> <Trans>You must bridge L1 assets to the network to swap them.</Trans>
<DesktopTextBreak /> <Trans>You must bridge L1 assets to the network to use them.</Trans>
</Body>
<LinkOutToBridge href={info.bridge} target="_blank" rel="noopener noreferrer">
<LinkOutToBridge href={depositUrl} target="_blank" rel="noopener noreferrer">
<Trans>Deposit to {NETWORK_LABELS[chainId]}</Trans>
<LinkOutCircle />
</LinkOutToBridge>
......
import { Trans } from '@lingui/macro'
import { L2_CHAIN_IDS, NETWORK_LABELS, SupportedChainId } from 'constants/chains'
import { L2_CHAIN_IDS, NETWORK_LABELS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { useCallback, useState } from 'react'
import { ArrowDownCircle, X } from 'react-feather'
import { useArbitrumAlphaAlert, useDarkModeManager } from 'state/user/hooks'
import { useETHBalances } from 'state/wallet/hooks'
import styled, { css } from 'styled-components/macro'
import { MEDIA_WIDTHS, TYPE } from 'theme'
import { L2_INFO } from '../../constants/chains'
import { MEDIA_WIDTHS } from 'theme'
import { CHAIN_INFO } from '../../constants/chains'
const L2Icon = styled.img`
width: 40px;
......@@ -48,9 +48,9 @@ export const OptimismWrapperBackgroundLightMode = css`
background: 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.5);
`
const RootWrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean; logoUrl: string }>`
const RootWrapper = styled.div<{ chainId: number; darkMode: boolean; logoUrl: string }>`
${({ chainId, darkMode }) =>
chainId === SupportedChainId.OPTIMISM
[SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
? darkMode
? OptimismWrapperBackgroundDarkMode
: OptimismWrapperBackgroundLightMode
......@@ -61,7 +61,7 @@ const RootWrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean; l
display: flex;
flex-direction: column;
max-width: 480px;
min-height: 218px;
min-height: 174px;
overflow: hidden;
position: relative;
width: 100%;
......@@ -79,11 +79,14 @@ const RootWrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean; l
z-index: -1;
}
`
const Header = styled(TYPE.largeHeader)`
const Header = styled.h2`
font-weight: 600;
font-size: 20px;
margin: 0;
padding-right: 30px;
`
const Body = styled.p`
font-size: 12px;
grid-column: 1 / 3;
line-height: 143%;
margin: 0;
......@@ -102,9 +105,11 @@ const LinkOutToBridge = styled.a`
border-radius: 16px;
color: white;
display: flex;
font-size: 16px;
height: 44px;
justify-content: space-between;
margin: 0 18px 18px 18px;
padding: 14px 24px;
margin: 0 20px 20px 20px;
padding: 12px 16px;
text-decoration: none;
width: auto;
:hover,
......@@ -130,7 +135,10 @@ export function NetworkAlert() {
if (!chainId || !L2_CHAIN_IDS.includes(chainId) || arbitrumAlphaAcknowledged || locallyDismissed) {
return null
}
const info = L2_INFO[chainId]
const info = CHAIN_INFO[chainId as SupportedL2ChainId]
const depositUrl = [SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
? `${info.bridge}?chainId=1`
: info.bridge
return (
<RootWrapper chainId={chainId} darkMode={darkMode} logoUrl={info.logoUrl}>
<CloseIcon onClick={dismiss} />
......@@ -146,7 +154,7 @@ export function NetworkAlert() {
</Trans>
</Body>
</ContentWrapper>
<LinkOutToBridge href={info.bridge} target="_blank" rel="noopener noreferrer">
<LinkOutToBridge href={depositUrl} target="_blank" rel="noopener noreferrer">
<Trans>Deposit to {NETWORK_LABELS[chainId]}</Trans>
<LinkOutCircle />
</LinkOutToBridge>
......
import { Trans } from '@lingui/macro'
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { AlertOctagon } from 'react-feather'
import styled from 'styled-components/macro'
const Root = styled.div`
background-color: ${({ theme }) => theme.yellow3};
border-radius: 18px;
color: black;
margin-top: 16px;
max-width: 480px;
padding: 16px;
width: 100%;
`
const WarningIcon = styled(AlertOctagon)`
margin: 0 8px 0 0;
`
const TitleRow = styled.div`
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
margin: 0;
font-size: 20px;
font-weight: 600;
line-height: 25px;
`
const Body = styled.div`
font-size: 12px;
line-height: 15px;
margin: 8px 0 0 0;
`
const LinkOutToNotion = styled.a`
color: black;
`
export default function OptimismDowntimeWarning() {
const { chainId } = useActiveWeb3React()
if (!chainId || ![SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)) {
return null
}
return (
<Root>
<TitleRow>
<WarningIcon />
<Trans>{'Optimism'} Scheduled Downtimes</Trans>
</TitleRow>
<Body>
<Trans>
{'Optimism'} expects some scheduled downtime in the near future.&nbsp;
<LinkOutToNotion
href={`https://www.notion.so/Optimism-Regenesis-Schedule-8d14a34902ca4f5a8910762b3ec4b8da`}
target="_blank"
rel="noopener noreferrer"
>
Read more.
</LinkOutToNotion>
</Trans>
</Body>
</Root>
)
}
import { Web3Provider } from '@ethersproject/providers'
import { InjectedConnector } from '@web3-react/injected-connector'
import { PortisConnector } from '@web3-react/portis-connector'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { WalletLinkConnector } from '@web3-react/walletlink-connector'
import { PortisConnector } from '@web3-react/portis-connector'
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
import { SupportedChainId } from '../constants/chains'
import getLibrary from '../utils/getLibrary'
import { FortmaticConnector } from './Fortmatic'
import { NetworkConnector } from './NetworkConnector'
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
const FORMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY
......@@ -19,9 +18,7 @@ if (typeof INFURA_KEY === 'undefined') {
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
}
const NETWORK_URLS: {
[chainId in SupportedChainId]: string
} = {
const NETWORK_URLS = {
[SupportedChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.RINKEBY]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ROPSTEN]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
......@@ -33,7 +30,7 @@ const NETWORK_URLS: {
[SupportedChainId.ARBITRUM_RINKEBY]: `https://rinkeby.arbitrum.io/rpc`,
}
const SUPPORTED_CHAIN_IDS: SupportedChainId[] = [
const SUPPORTED_CHAIN_IDS = [
SupportedChainId.MAINNET,
SupportedChainId.KOVAN,
SupportedChainId.GOERLI,
......@@ -81,7 +78,7 @@ export const portis = new PortisConnector({
// mainnet only
export const walletlink = new WalletLinkConnector({
url: NETWORK_URLS[1],
url: NETWORK_URLS[SupportedChainId.MAINNET],
appName: 'Uniswap',
appLogoUrl: UNISWAP_LOGO_URL,
})
......@@ -7,28 +7,25 @@ export enum SupportedChainId {
RINKEBY = 4,
GOERLI = 5,
KOVAN = 42,
ARBITRUM_ONE = 42161,
ARBITRUM_RINKEBY = 421611,
OPTIMISM = 10,
OPTIMISTIC_KOVAN = 69,
}
export const L2_CHAIN_IDS = [SupportedChainId.ARBITRUM_ONE, SupportedChainId.OPTIMISM]
export type SupportedL2ChainId =
| SupportedChainId.ARBITRUM_ONE
| SupportedChainId.ARBITRUM_RINKEBY
| SupportedChainId.OPTIMISM
| SupportedChainId.OPTIMISTIC_KOVAN
export const L2_INFO: Record<number, { bridge: string; docs: string; explorer: string; logoUrl: string }> = {
[SupportedChainId.OPTIMISM]: {
bridge: 'https://gateway.optimism.io/',
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
logoUrl: optimismLogoUrl,
},
[SupportedChainId.ARBITRUM_ONE]: {
bridge: 'https://bridge.arbitrum.io/',
explorer: 'https://explorer.arbitrum.io/',
docs: 'https://offchainlabs.com/',
logoUrl: arbitrumLogoUrl,
},
}
export type SupportedL1ChainId =
| SupportedChainId.MAINNET
| SupportedChainId.ROPSTEN
| SupportedChainId.RINKEBY
| SupportedChainId.GOERLI
| SupportedChainId.KOVAN
export const NETWORK_LABELS: { [chainId in SupportedChainId | number]: string } = {
[SupportedChainId.MAINNET]: 'Mainnet',
......@@ -37,7 +34,100 @@ export const NETWORK_LABELS: { [chainId in SupportedChainId | number]: string }
[SupportedChainId.GOERLI]: 'Görli',
[SupportedChainId.KOVAN]: 'Kovan',
[SupportedChainId.ARBITRUM_ONE]: 'Arbitrum',
[SupportedChainId.ARBITRUM_RINKEBY]: 'Arbitrum Testnet',
[SupportedChainId.OPTIMISM]: 'Optimism',
[SupportedChainId.OPTIMISTIC_KOVAN]: 'Optimism Testnet',
[SupportedChainId.ARBITRUM_RINKEBY]: 'Arbitrum Rinkeby',
[SupportedChainId.OPTIMISM]: 'Optimistic Ethereum',
[SupportedChainId.OPTIMISTIC_KOVAN]: 'Optimistic Kovan',
} as const
export const L1_CHAIN_IDS = [
SupportedChainId.MAINNET,
SupportedChainId.ROPSTEN,
SupportedChainId.RINKEBY,
SupportedChainId.GOERLI,
SupportedChainId.KOVAN,
]
export const L2_CHAIN_IDS = [
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
]
interface L1ChainInfo {
docs: string
explorer: string
infoLink: string
label: string
}
interface L2ChainInfo extends L1ChainInfo {
bridge: string
logoUrl: string
}
type ChainInfo = { [chainId in SupportedL2ChainId]: L2ChainInfo } &
{ [chainId in SupportedL1ChainId]: L1ChainInfo } & { [chainId: number]: L1ChainInfo | L2ChainInfo }
export const CHAIN_INFO: ChainInfo = {
[SupportedChainId.ARBITRUM_ONE]: {
bridge: 'https://bridge.arbitrum.io/',
docs: 'https://offchainlabs.com/',
explorer: 'https://explorer.arbitrum.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum',
label: NETWORK_LABELS[SupportedChainId.ARBITRUM_ONE],
logoUrl: arbitrumLogoUrl,
},
[SupportedChainId.ARBITRUM_RINKEBY]: {
bridge: 'https://bridge.arbitrum.io/',
docs: 'https://offchainlabs.com/',
explorer: 'https://explorer.arbitrum.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum',
label: NETWORK_LABELS[SupportedChainId.ARBITRUM_RINKEBY],
logoUrl: arbitrumLogoUrl,
},
[SupportedChainId.MAINNET]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: NETWORK_LABELS[SupportedChainId.MAINNET],
},
[SupportedChainId.RINKEBY]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://rinkeby.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: NETWORK_LABELS[SupportedChainId.RINKEBY],
},
[SupportedChainId.ROPSTEN]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://ropsten.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: NETWORK_LABELS[SupportedChainId.ROPSTEN],
},
[SupportedChainId.KOVAN]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://kovan.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: NETWORK_LABELS[SupportedChainId.KOVAN],
},
[SupportedChainId.GOERLI]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://goerli.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: NETWORK_LABELS[SupportedChainId.GOERLI],
},
[SupportedChainId.OPTIMISM]: {
bridge: 'https://gateway.optimism.io/',
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism',
label: NETWORK_LABELS[SupportedChainId.OPTIMISM],
logoUrl: optimismLogoUrl,
},
[SupportedChainId.OPTIMISTIC_KOVAN]: {
bridge: 'https://gateway.optimism.io/',
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism',
label: NETWORK_LABELS[SupportedChainId.OPTIMISTIC_KOVAN],
logoUrl: optimismLogoUrl,
},
}
// used to mark unsupported tokens, these are hosted lists of unsupported tokens
const COMPOUND_LIST = 'https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json'
const UMA_LIST = 'https://umaproject.org/uma.tokenlist.json'
const AAVE_LIST = 'tokenlist.aave.eth'
const WRAPPED_LIST = 'wrapped.tokensoft.eth'
const SET_LIST = 'https://raw.githubusercontent.com/SetProtocol/uniswap-tokenlist/main/set.tokenlist.json'
const ROLL_LIST = 'https://app.tryroll.com/tokens.json'
const COINGECKO_LIST = 'https://tokens.coingecko.com/uniswap/all.json'
const BA_LIST = 'https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json'
const CMC_ALL_LIST = 'defi.cmc.eth'
const CMC_STABLECOIN = 'stablecoin.cmc.eth'
const KLEROS_LIST = 't2crtokens.eth'
const COINGECKO_LIST = 'https://tokens.coingecko.com/uniswap/all.json'
const COMPOUND_LIST = 'https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json'
const GEMINI_LIST = 'https://www.gemini.com/uniswap/manifest.json'
const BA_LIST = 'https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json'
const KLEROS_LIST = 't2crtokens.eth'
export const OPTIMISM_LIST = 'https://static.optimism.io/optimism.tokenlist.json'
const ROLL_LIST = 'https://app.tryroll.com/tokens.json'
const SET_LIST = 'https://raw.githubusercontent.com/SetProtocol/uniswap-tokenlist/main/set.tokenlist.json'
const UMA_LIST = 'https://umaproject.org/uma.tokenlist.json'
const WRAPPED_LIST = 'wrapped.tokensoft.eth'
// used to mark unsupported tokens, these are hosted lists of unsupported tokens
export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST]
// lower index == higher priority for token import
export const DEFAULT_LIST_OF_LISTS: string[] = [
COMPOUND_LIST,
AAVE_LIST,
OPTIMISM_LIST,
UMA_LIST,
WRAPPED_LIST,
SET_LIST,
......
......@@ -7,6 +7,7 @@ export const NetworkContextName = 'NETWORK'
// 30 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 30
export const L2_DEADLINE_FROM_NOW = 60 * 5
// used for rewards deadlines
export const BIG_INT_SECONDS_IN_WEEK = JSBI.BigInt(60 * 60 * 24 * 7)
......
import { L2_CHAIN_IDS } from 'constants/chains'
import { L2_DEADLINE_FROM_NOW } from 'constants/misc'
import { BigNumber } from 'ethers'
import { useMemo } from 'react'
import { useAppSelector } from 'state/hooks'
import useCurrentBlockTimestamp from './useCurrentBlockTimestamp'
import { useActiveWeb3React } from './web3'
// combines the block timestamp with the user setting to give the deadline that should be used for any submitted transaction
export default function useTransactionDeadline(): BigNumber | undefined {
const { chainId } = useActiveWeb3React()
const ttl = useAppSelector((state) => state.user.userDeadline)
const blockTimestamp = useCurrentBlockTimestamp()
return useMemo(() => {
if (blockTimestamp && chainId && L2_CHAIN_IDS.includes(chainId)) return blockTimestamp.add(L2_DEADLINE_FROM_NOW)
if (blockTimestamp && ttl) return blockTimestamp.add(ttl)
return undefined
}, [blockTimestamp, ttl])
}, [blockTimestamp, chainId, ttl])
}
......@@ -71,6 +71,7 @@ import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
import PresetsButtons from 'components/RangeSelector/PresetsButtons'
import LiquidityChartRangeInput from 'components/LiquidityChartRangeInput'
import { SupportedChainId } from 'constants/chains'
import OptimismDowntimeWarning from 'components/OptimismDowntimeWarning'
const DEFAULT_ADD_IN_RANGE_SLIPPAGE_TOLERANCE = new Percent(50, 10_000)
......@@ -541,6 +542,7 @@ export default function AddLiquidity({
<>
<ScrollablePage>
<NetworkAlert />
<OptimismDowntimeWarning />
<TransactionConfirmationModal
isOpen={showConfirm}
onDismiss={handleDismissConfirmation}
......
......@@ -2,6 +2,8 @@ import { Trans } from '@lingui/macro'
import { AutoColumn } from 'components/Column'
import { MinimalNetworkAlert } from 'components/NetworkAlert/MinimalNetworkAlert'
import { RowBetween } from 'components/Row'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import Texture from '../../assets/images/sandtexture.webp'
......@@ -119,6 +121,8 @@ const StyledImage = styled.img`
`
export default function CTACards() {
const { chainId } = useActiveWeb3React()
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (
<div>
<MinimalNetworkAlert />
......@@ -137,7 +141,7 @@ export default function CTACards() {
</RowBetween>
</ResponsiveColumn>
</CTA1>
<CTA2 href={'https://info.uniswap.org/#/pools'}>
<CTA2 href={infoLink + '/pools'}>
<ResponsiveColumn>
<HeaderText style={{ alignSelf: 'flex-start' }}>
<Trans>Top pools</Trans>
......
......@@ -44,6 +44,7 @@ import Toggle from 'components/Toggle'
import { Bound } from 'state/mint/v3/actions'
import useIsTickAtLimit from 'hooks/useIsTickAtLimit'
import { formatTickPrice } from 'utils/formatTickPrice'
import { SupportedChainId } from 'constants/chains'
const PageWrapper = styled.div`
min-width: 800px;
......@@ -372,11 +373,6 @@ export function PositionPage({
const currencyQuote = inverted ? currency0 : currency1
const currencyBase = inverted ? currency1 : currency0
// check if price is within range
const below = pool && typeof tickLower === 'number' ? pool.tickCurrent < tickLower : undefined
const above = pool && typeof tickUpper === 'number' ? pool.tickCurrent >= tickUpper : undefined
const inRange: boolean = typeof below === 'boolean' && typeof above === 'boolean' ? !below && !above : false
const ratio = useMemo(() => {
return priceLower && pool && priceUpper
? getRatio(
......@@ -479,6 +475,11 @@ export function PositionPage({
const feeValueUpper = inverted ? feeValue0 : feeValue1
const feeValueLower = inverted ? feeValue1 : feeValue0
// check if price is within range
const below = pool && typeof tickLower === 'number' ? pool.tickCurrent < tickLower : undefined
const above = pool && typeof tickUpper === 'number' ? pool.tickCurrent >= tickUpper : undefined
const inRange: boolean = typeof below === 'boolean' && typeof above === 'boolean' ? !below && !above : false
function modalHeader() {
return (
<AutoColumn gap={'md'} style={{ marginTop: '20px' }}>
......@@ -510,13 +511,15 @@ export function PositionPage({
)
}
const onOptimisticChain = chainId && [SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
const showCollectAsWeth = Boolean(
ownsNFT &&
(feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0)) &&
currency0 &&
currency1 &&
(currency0.isNative || currency1.isNative) &&
!collectMigrationHash
!collectMigrationHash &&
!onOptimisticChain
)
return loading || poolState === PoolState.LOADING || !feeAmount ? (
......
......@@ -148,6 +148,16 @@ export default function Pool() {
link: '/migrate/v2',
external: false,
},
{
content: (
<MenuItem>
<Layers size={16} style={{ marginRight: '12px' }} />
<Trans>V2 liquidity</Trans>
</MenuItem>
),
link: '/pool/v2',
external: false,
},
{
content: (
<MenuItem>
......@@ -160,19 +170,6 @@ export default function Pool() {
},
]
if (showV2Features) {
menuItems.splice(2, 0, {
content: (
<MenuItem>
<Layers size={16} style={{ marginRight: '12px' }} />
<Trans>V2 liquidity</Trans>
</MenuItem>
),
link: '/pool/v2',
external: false,
})
}
return (
<>
<PageWrapper>
......@@ -186,6 +183,7 @@ export default function Pool() {
</TYPE.mediumHeader>
</HideSmall>
<ButtonRow>
{showV2Features && (
<Menu
menuItems={menuItems}
flyoutAlignment={FlyoutAlignment.LEFT}
......@@ -198,6 +196,7 @@ export default function Pool() {
</MoreOptionsButton>
)}
/>
)}
<ResponsiveButtonPrimary id="join-pool-button" as={Link} to="/add/ETH">
+ <Trans>New Position</Trans>
</ResponsiveButtonPrimary>
......
......@@ -35,6 +35,7 @@ import { AddRemoveTabs } from 'components/NavigationTabs'
import RangeBadge from 'components/Badge/RangeBadge'
import Toggle from 'components/Toggle'
import { t, Trans } from '@lingui/macro'
import { SupportedChainId } from 'constants/chains'
const DEFAULT_REMOVE_V3_LIQUIDITY_SLIPPAGE_TOLERANCE = new Percent(5, 100)
......@@ -251,6 +252,16 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
)
}
const onOptimisticChain = chainId && [SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
const showCollectAsWeth = Boolean(
!onOptimisticChain &&
liquidityValue0?.currency &&
liquidityValue1?.currency &&
(liquidityValue0.currency.isNative ||
liquidityValue1.currency.isNative ||
liquidityValue0.currency.wrapped.equals(WETH9_EXTENDED[liquidityValue0.currency.chainId]) ||
liquidityValue1.currency.wrapped.equals(WETH9_EXTENDED[liquidityValue1.currency.chainId]))
)
return (
<AutoColumn>
<TransactionConfirmationModal
......@@ -373,12 +384,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</AutoColumn>
</LightCard>
{liquidityValue0?.currency &&
liquidityValue1?.currency &&
(liquidityValue0.currency.isNative ||
liquidityValue1.currency.isNative ||
liquidityValue0.currency.wrapped.equals(WETH9_EXTENDED[liquidityValue0.currency.chainId]) ||
liquidityValue1.currency.wrapped.equals(WETH9_EXTENDED[liquidityValue1.currency.chainId])) ? (
{showCollectAsWeth && (
<RowBetween>
<TYPE.main>
<Trans>Collect as WETH</Trans>
......@@ -389,7 +395,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
toggle={() => setReceiveWETH((receiveWETH) => !receiveWETH)}
/>
</RowBetween>
) : null}
)}
<div style={{ display: 'flex' }}>
<AutoColumn gap="12px" style={{ flex: '1' }}>
......
import { useEffect } from 'react'
import { useAppDispatch } from 'state/hooks'
import { updateMatchesDarkMode } from './actions'
export default function Updater(): null {
......
......@@ -34,12 +34,14 @@ export default function RadialGradientByChainUpdater(): null {
switch (chainId) {
case SupportedChainId.ARBITRUM_ONE:
case SupportedChainId.ARBITRUM_RINKEBY:
setBackground(backgroundResetStyles)
const arbitrumLightGradient = 'radial-gradient(150% 100% at 50% 0%, #CDE8FB 0%, #FCF3F9 50%, #FFFFFF 100%)'
const arbitrumDarkGradient = 'radial-gradient(150% 100% at 50% 0%, #0A294B 0%, #221E30 50%, #1F2128 100%)'
backgroundRadialGradientElement.style.background = darkMode ? arbitrumDarkGradient : arbitrumLightGradient
break
case SupportedChainId.OPTIMISM:
case SupportedChainId.OPTIMISTIC_KOVAN:
setBackground(backgroundResetStyles)
const optimismLightGradient = 'radial-gradient(150% 100% at 50% 0%, #FFFBF2 2%, #FFF4F9 53%, #FFFFFF 100%)'
const optimismDarkGradient = 'radial-gradient(150% 100% at 50% 0%, #3E2E38 2%, #2C1F2D 53%, #1F2128 100%)'
......
import { SupportedChainId } from '../constants/chains'
const MAINNET_AND_TESTNETS = [
SupportedChainId.MAINNET,
SupportedChainId.ROPSTEN,
SupportedChainId.RINKEBY,
SupportedChainId.GOERLI,
SupportedChainId.KOVAN,
]
import { L1_CHAIN_IDS, SupportedChainId } from '../constants/chains'
export function constructSameAddressMap<T extends string>(
address: T,
additionalNetworks: SupportedChainId[] = []
): { [chainId: number]: T } {
return MAINNET_AND_TESTNETS.concat(additionalNetworks).reduce<{ [chainId: number]: T }>((memo, chainId) => {
return L1_CHAIN_IDS.concat(additionalNetworks).reduce<{ [chainId: number]: T }>((memo, chainId) => {
memo[chainId] = address
return memo
}, {})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment