Commit e81e8a8f authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: inadvertent merges/reverts (#2915)

* Revert "Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)"

This reverts commit 7d343dcf.

* Revert "deleted files"

This reverts commit 097b8361.
parent 7d343dcf
......@@ -8,13 +8,33 @@
"jsx": true
}
},
"ignorePatterns": ["node_modules/**/*"],
"settings": {
"react": {
"version": "detect"
}
},
"ignorePatterns": [
"src/types/v3",
"src/abis/types",
"src/locales/**/*.js",
"src/locales/**/en-US.po",
"src/state/data/generated.ts",
"node_modules",
"coverage",
"build",
"dist",
".DS_Store",
".env.local",
".env.development.local",
".env.test.local",
".env.production.local",
".idea/",
".vscode/",
"package-lock.json",
"yarn.lock"
],
"extends": [
"react-app",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
......
......@@ -11,7 +11,6 @@ on:
jobs:
run-linters:
name: Run linters
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.repository_owner }}
runs-on: ubuntu-latest
steps:
......@@ -39,10 +38,15 @@ jobs:
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run linters
- name: Run eslint w/ autofix
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.repository_owner }}
uses: wearerequired/lint-action@36c7e6689e80d785d27a22f71d970f3a3b4fcb70
with:
github_token: ${{ secrets.github_token }}
eslint: true
eslint_extensions: js,jsx,ts,tsx,json
eslint_args: "-c .eslintrc.json"
auto_fix: true
- name: Run eslint
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login != github.repository_owner }}
run: yarn eslint .
......@@ -74,6 +74,7 @@ class CustomizedBridge extends Eip1193Bridge {
}
// sets up the injected provider to be a mock ethereum provider with the given mnemonic/index
// eslint-disable-next-line no-undef
Cypress.Commands.overwrite('visit', (original, url, options) => {
return original(url.startsWith('/') && url.length > 2 && !url.startsWith('/#') ? `/#${url}` : url, {
...options,
......
export default {
const linguiConfig = {
catalogs: [
{
path: '<rootDir>/src/locales/{locale}',
......@@ -52,3 +52,5 @@ export default {
runtimeConfigModule: ['@lingui/core', 'i18n'],
sourceLocale: 'en-US',
}
export default linguiConfig
......@@ -152,12 +152,6 @@
"bundle": "microbundle --tsconfig tsconfig.lib.json src/lib/index.tsx --format esm,cjs",
"cosmos": "open http://localhost:5000 && cross-env FAST_REFRESH=false cosmos"
},
"eslintConfig": {
"extends": "react-app",
"ignorePatterns": [
"node_modules"
]
},
"browserslist": {
"production": [
">0.2%",
......
......@@ -80,7 +80,7 @@ function ClaimSummary({ info: { recipient, uniAmountRaw } }: { info: ClaimTransa
)
}
function SubmitProposalTransactionSummary({}: { info: SubmitProposalTransactionInfo }) {
function SubmitProposalTransactionSummary(_: { info: SubmitProposalTransactionInfo }) {
return <Trans>Submit new proposal</Trans>
}
......@@ -147,13 +147,13 @@ function WrapSummary({ info: { currencyAmountRaw, unwrapped } }: { info: WrapTra
}
}
function DepositLiquidityStakingSummary({}: { info: DepositLiquidityStakingTransactionInfo }) {
function DepositLiquidityStakingSummary(_: { info: DepositLiquidityStakingTransactionInfo }) {
// not worth rendering the tokens since you can should no longer deposit liquidity in the staking contracts
// todo: deprecate and delete the code paths that allow this, show user more information
return <Trans>Deposit liquidity</Trans>
}
function WithdrawLiquidityStakingSummary({}: { info: WithdrawLiquidityStakingTransactionInfo }) {
function WithdrawLiquidityStakingSummary(_: { info: WithdrawLiquidityStakingTransactionInfo }) {
return <Trans>Withdraw deposited liquidity</Trans>
}
......
......@@ -10,7 +10,7 @@ import { injected, portis, walletlink } from '../../connectors'
import { SUPPORTED_WALLETS } from '../../constants/wallet'
import { useActiveWeb3React } from '../../hooks/web3'
import { clearAllTransactions } from '../../state/transactions/actions'
import { ExternalLink, LinkStyledButton, TYPE } from '../../theme'
import { ExternalLink, LinkStyledButton, ThemedText } from '../../theme'
import { shortenAddress } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { ButtonSecondary } from '../Button'
......@@ -378,9 +378,9 @@ export default function AccountDetails({
{!!pendingTransactions.length || !!confirmedTransactions.length ? (
<LowerSection>
<AutoRow mb={'1rem'} style={{ justifyContent: 'space-between' }}>
<TYPE.body>
<ThemedText.Body>
<Trans>Recent Transactions</Trans>
</TYPE.body>
</ThemedText.Body>
<LinkStyledButton onClick={clearAllTransactionsCallback}>
<Trans>(clear all)</Trans>
</LinkStyledButton>
......@@ -390,9 +390,9 @@ export default function AccountDetails({
</LowerSection>
) : (
<LowerSection>
<TYPE.body color={theme.text1}>
<ThemedText.Body color={theme.text1}>
<Trans>Your transactions will appear here...</Trans>
</TYPE.body>
</ThemedText.Body>
</LowerSection>
)}
</>
......
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { t } from '@lingui/macro'
import { ReactNode, useCallback, useContext } from 'react'
import styled, { ThemeContext } from 'styled-components/macro'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
......@@ -107,9 +108,9 @@ export default function AddressInputPanel({
<InputContainer>
<AutoColumn gap="md">
<RowBetween>
<TYPE.black color={theme.text2} fontWeight={500} fontSize={14}>
<ThemedText.Black color={theme.text2} fontWeight={500} fontSize={14}>
{label ?? <Trans>Recipient</Trans>}
</TYPE.black>
</ThemedText.Black>
{address && chainId && (
<ExternalLink
href={getExplorerLink(chainId, name ?? address, ExplorerDataType.ADDRESS)}
......
......@@ -4,7 +4,7 @@ import HoverInlineText from 'components/HoverInlineText'
import { useMemo } from 'react'
import useTheme from '../../hooks/useTheme'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { warningSeverity } from '../../utils/prices'
export function FiatValue({
......@@ -25,7 +25,7 @@ export function FiatValue({
}, [priceImpact, theme.green1, theme.red1, theme.text3, theme.yellow1])
return (
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
<ThemedText.Body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
{fiatValue ? (
<Trans>
~$ <HoverInlineText text={fiatValue?.toSignificant(6, { groupSeparator: ',' })} />
......@@ -39,6 +39,6 @@ export function FiatValue({
(<Trans>{priceImpact.multiply(-1).toSignificant(3)}%</Trans>)
</span>
) : null}
</TYPE.body>
</ThemedText.Body>
)
}
......@@ -13,7 +13,7 @@ import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import useTheme from '../../hooks/useTheme'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { ButtonGray } from '../Button'
import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo'
......@@ -212,9 +212,9 @@ export default function CurrencyInputPanel({
<FixedContainer>
<AutoColumn gap="sm" justify="center">
<Lock />
<TYPE.label fontSize="12px" textAlign="center" padding="0 12px">
<ThemedText.Label fontSize="12px" textAlign="center" padding="0 12px">
<Trans>The market price is outside your specified price range. Single-asset deposit only.</Trans>
</TYPE.label>
</ThemedText.Label>
</AutoColumn>
</FixedContainer>
)}
......@@ -271,7 +271,7 @@ export default function CurrencyInputPanel({
<RowBetween>
{account ? (
<RowFixed style={{ height: '17px' }}>
<TYPE.body
<ThemedText.Body
onClick={onMax}
color={theme.text2}
fontWeight={400}
......@@ -287,7 +287,7 @@ export default function CurrencyInputPanel({
</Trans>
)
) : null}
</TYPE.body>
</ThemedText.Body>
{showMaxButton && selectedCurrencyBalance ? (
<StyledBalanceMax onClick={onMax}>
<Trans>(Max)</Trans>
......
......@@ -4,7 +4,7 @@ import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import store, { AppState } from '../../state'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { userAgent } from '../../utils/userAgent'
import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'
......@@ -47,6 +47,8 @@ type ErrorBoundaryState = {
error: Error | null
}
const IS_UNISWAP = window.location.hostname === 'app.uniswap.org'
export default class ErrorBoundary extends React.Component<unknown, ErrorBoundaryState> {
constructor(props: unknown) {
super(props)
......@@ -67,6 +69,7 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
render() {
const { error } = this.state
if (error !== null) {
const encodedBody = encodeURIComponent(issueBody(error))
return (
......@@ -74,39 +77,41 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
<BodyWrapper>
<AutoColumn gap={'md'}>
<SomethingWentWrongWrapper>
<TYPE.label fontSize={24} fontWeight={600}>
<ThemedText.Label fontSize={24} fontWeight={600}>
<Trans>Something went wrong</Trans>
</TYPE.label>
</ThemedText.Label>
</SomethingWentWrongWrapper>
<CodeBlockWrapper>
<code>
<TYPE.main fontSize={10}>{error.stack}</TYPE.main>
<ThemedText.Main fontSize={10}>{error.stack}</ThemedText.Main>
</code>
</CodeBlockWrapper>
<AutoRow>
<LinkWrapper>
<ExternalLink
id="create-github-issue-link"
href={`https://github.com/Uniswap/uniswap-interface/issues/new?assignees=&labels=bug&body=${encodedBody}&title=${encodeURIComponent(
`Crash report: \`${error.name}${error.message && `: ${error.message}`}\``
)}`}
target="_blank"
>
<TYPE.link fontSize={16}>
<Trans>Create an issue on GitHub</Trans>
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
<LinkWrapper>
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
<TYPE.link fontSize={16}>
<Trans>Get support on Discord</Trans>
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
</AutoRow>
{IS_UNISWAP ? (
<AutoRow>
<LinkWrapper>
<ExternalLink
id="create-github-issue-link"
href={`https://github.com/Uniswap/uniswap-interface/issues/new?assignees=&labels=bug&body=${encodedBody}&title=${encodeURIComponent(
`Crash report: \`${error.name}${error.message && `: ${error.message}`}\``
)}`}
target="_blank"
>
<ThemedText.Link fontSize={16}>
<Trans>Create an issue on GitHub</Trans>
<span></span>
</ThemedText.Link>
</ExternalLink>
</LinkWrapper>
<LinkWrapper>
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
<ThemedText.Link fontSize={16}>
<Trans>Get support on Discord</Trans>
<span></span>
</ThemedText.Link>
</ExternalLink>
</LinkWrapper>
</AutoRow>
) : null}
</AutoColumn>
</BodyWrapper>
</FallbackWrapper>
......@@ -121,7 +126,7 @@ function getRelevantState(): null | keyof AppState {
if (!path.startsWith('#/')) {
return null
}
const pieces = path.substring(2).split(/[\/\\?]/)
const pieces = path.substring(2).split(/[/\\?]/)
switch (pieces[0]) {
case 'swap':
return 'swap'
......
......@@ -6,12 +6,12 @@ import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState } from 'hooks/usePools'
import React from 'react'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { FeeTierPercentageBadge } from './FeeTierPercentageBadge'
import { FEE_AMOUNT_DETAIL } from './shared'
const ResponsiveText = styled(TYPE.label)`
const ResponsiveText = styled(ThemedText.Label)`
line-height: 16px;
font-size: 14px;
......@@ -37,9 +37,9 @@ export function FeeOption({ feeAmount, active, poolState, distributions, onClick
<ResponsiveText>
<Trans>{FEE_AMOUNT_DETAIL[feeAmount].label}%</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<ThemedText.Main fontWeight={400} fontSize="12px" textAlign="left">
{FEE_AMOUNT_DETAIL[feeAmount].description}
</TYPE.main>
</ThemedText.Main>
</AutoColumn>
{distributions && (
......
......@@ -4,7 +4,7 @@ import Badge from 'components/Badge'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState } from 'hooks/usePools'
import React from 'react'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
export function FeeTierPercentageBadge({
feeAmount,
......@@ -17,7 +17,7 @@ export function FeeTierPercentageBadge({
}) {
return (
<Badge>
<TYPE.label fontSize={10}>
<ThemedText.Label fontSize={10}>
{!distributions || poolState === PoolState.NOT_EXISTS || poolState === PoolState.INVALID ? (
<Trans>Not created</Trans>
) : distributions[feeAmount] !== undefined ? (
......@@ -25,7 +25,7 @@ export function FeeTierPercentageBadge({
) : (
<Trans>No data</Trans>
)}
</TYPE.label>
</ThemedText.Label>
</Badge>
)
}
......@@ -14,7 +14,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga'
import { Box } from 'rebass'
import styled, { keyframes } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { FeeOption } from './FeeOption'
import { FeeTierPercentageBadge } from './FeeTierPercentageBadge'
......@@ -149,18 +149,18 @@ export default function FeeSelector({
<AutoColumn id="add-liquidity-selected-fee">
{!feeAmount ? (
<>
<TYPE.label>
<ThemedText.Label>
<Trans>Fee tier</Trans>
</TYPE.label>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
</ThemedText.Label>
<ThemedText.Main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>The % you will earn in fees.</Trans>
</TYPE.main>
</ThemedText.Main>
</>
) : (
<>
<TYPE.label className="selected-fee-label">
<ThemedText.Label className="selected-fee-label">
<Trans>{FEE_AMOUNT_DETAIL[feeAmount].label}% fee tier</Trans>
</TYPE.label>
</ThemedText.Label>
<Box style={{ width: 'fit-content', marginTop: '8px' }} className="selected-fee-percentage">
{distributions && (
<FeeTierPercentageBadge
......
......@@ -6,7 +6,7 @@ import ms from 'ms.macro'
import { useEffect, useState } from 'react'
import { useBlockNumber } from 'state/application/hooks'
import styled, { keyframes } from 'styled-components/macro'
import { ExternalLink, TYPE } from 'theme'
import { ExternalLink, ThemedText } from 'theme'
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink'
import { ChainConnectivityWarning } from './ChainConnectivityWarning'
......@@ -25,7 +25,7 @@ const StyledPolling = styled.div<{ warning: boolean }>`
display: none;
`}
`
const StyledPollingNumber = styled(TYPE.small)<{ breathe: boolean; hovering: boolean }>`
const StyledPollingNumber = styled(ThemedText.Small)<{ breathe: boolean; hovering: boolean }>`
transition: opacity 0.25s ease;
opacity: ${({ breathe, hovering }) => (hovering ? 0.7 : breathe ? 1 : 0.5)};
:hover {
......
......@@ -14,7 +14,7 @@ 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 { ExternalLink, StyledInternalLink, ThemedText, UniTokenAnimated } from '../../theme'
import { computeUniCirculation } from '../../utils/computeUniCirculation'
import { AutoColumn } from '../Column'
import { Break, CardBGImage, CardNoise, CardSection, DataCard } from '../earn/styled'
......@@ -70,9 +70,9 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white color="white">
<ThemedText.White color="white">
<Trans>Your UNI Breakdown</Trans>
</TYPE.white>
</ThemedText.White>
<StyledClose stroke="white" onClick={() => setShowUniBalanceModal(false)} />
</RowBetween>
</CardSection>
......@@ -82,29 +82,29 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
<CardSection gap="sm">
<AutoColumn gap="md" justify="center">
<UniTokenAnimated width="48px" src={tokenLogo} />{' '}
<TYPE.white fontSize={48} fontWeight={600} color="white">
<ThemedText.White fontSize={48} fontWeight={600} color="white">
{total?.toFixed(2, { groupSeparator: ',' })}
</TYPE.white>
</ThemedText.White>
</AutoColumn>
<AutoColumn gap="md">
<RowBetween>
<TYPE.white color="white">
<ThemedText.White color="white">
<Trans>Balance:</Trans>
</TYPE.white>
<TYPE.white color="white">{uniBalance?.toFixed(2, { groupSeparator: ',' })}</TYPE.white>
</ThemedText.White>
<ThemedText.White color="white">{uniBalance?.toFixed(2, { groupSeparator: ',' })}</ThemedText.White>
</RowBetween>
<RowBetween>
<TYPE.white color="white">
<ThemedText.White color="white">
<Trans>Unclaimed:</Trans>
</TYPE.white>
<TYPE.white color="white">
</ThemedText.White>
<ThemedText.White color="white">
{uniToClaim?.toFixed(4, { groupSeparator: ',' })}{' '}
{uniToClaim && uniToClaim.greaterThan('0') && (
<StyledInternalLink onClick={() => setShowUniBalanceModal(false)} to="/uni">
<Trans>(claim)</Trans>
</StyledInternalLink>
)}
</TYPE.white>
</ThemedText.White>
</RowBetween>
</AutoColumn>
</CardSection>
......@@ -114,22 +114,22 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
<CardSection gap="sm">
<AutoColumn gap="md">
<RowBetween>
<TYPE.white color="white">
<ThemedText.White color="white">
<Trans>UNI price:</Trans>
</TYPE.white>
<TYPE.white color="white">${uniPrice?.toFixed(2) ?? '-'}</TYPE.white>
</ThemedText.White>
<ThemedText.White color="white">${uniPrice?.toFixed(2) ?? '-'}</ThemedText.White>
</RowBetween>
<RowBetween>
<TYPE.white color="white">
<ThemedText.White color="white">
<Trans>UNI in circulation:</Trans>
</TYPE.white>
<TYPE.white color="white">{circulation?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</ThemedText.White>
<ThemedText.White color="white">{circulation?.toFixed(0, { groupSeparator: ',' })}</ThemedText.White>
</RowBetween>
<RowBetween>
<TYPE.white color="white">
<ThemedText.White color="white">
<Trans>Total Supply</Trans>
</TYPE.white>
<TYPE.white color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</ThemedText.White>
<ThemedText.White color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</ThemedText.White>
</RowBetween>
{uni && uni.chainId === 1 ? (
<ExternalLink href={`${infoLink}/token/${uni.address}`}>
......
......@@ -15,7 +15,7 @@ import styled from 'styled-components/macro'
import { ReactComponent as Logo } from '../../assets/svg/logo.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import ClaimModal from '../claim/ClaimModal'
import { CardNoise } from '../earn/styled'
import Menu from '../Menu'
......@@ -309,7 +309,7 @@ export default function Header() {
{availableClaim && !showClaimPopup && (
<UNIWrapper onClick={toggleClaimModal}>
<UNIAmount active={!!account && !availableClaim} style={{ pointerEvents: 'auto' }}>
<TYPE.white padding="0 2px">
<ThemedText.White padding="0 2px">
{claimTxn && !claimTxn?.receipt ? (
<Dots>
<Trans>Claiming UNI</Trans>
......@@ -317,7 +317,7 @@ export default function Header() {
) : (
<Trans>Claim UNI</Trans>
)}
</TYPE.white>
</ThemedText.White>
</UNIAmount>
<CardNoise />
</UNIWrapper>
......
import jazzicon from '@metamask/jazzicon'
import useENSAvatar from 'hooks/useENSAvatar'
import { useEffect, useRef, useState } from 'react'
import { useLayoutEffect, useMemo, useRef, useState } from 'react'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
......@@ -20,27 +20,29 @@ const StyledAvatar = styled.img`
`
export default function Identicon() {
const ref = useRef<HTMLDivElement>(null)
const { account } = useActiveWeb3React()
const { avatar } = useENSAvatar(account ?? undefined)
const [fetchable, setFetchable] = useState(true)
useEffect(() => {
if ((!avatar || !fetchable) && account) {
const icon = jazzicon(16, parseInt(account?.slice(2, 10), 16))
const current = ref.current
const icon = useMemo(() => account && jazzicon(16, parseInt(account.slice(2, 10), 16)), [account])
const iconRef = useRef<HTMLDivElement>(null)
useLayoutEffect(() => {
const current = iconRef.current
if (icon) {
current?.appendChild(icon)
return () => {
current?.removeChild(icon)
}
}
return
}, [account, avatar, fetchable])
}, [icon, iconRef])
return (
<StyledIdenticon ref={ref}>
{avatar && fetchable && (
<StyledIdenticon>
{avatar && fetchable ? (
<StyledAvatar alt="avatar" src={avatar} onError={() => setFetchable(false)}></StyledAvatar>
) : (
<span ref={iconRef} />
)}
</StyledIdenticon>
)
......
......@@ -6,7 +6,7 @@ import { AutoColumn } from 'components/Column'
import { ReactNode, useCallback, useEffect, useState } from 'react'
import { Minus, Plus } from 'react-feather'
import styled, { keyframes } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { Input as NumericalInput } from '../NumericalInput'
......@@ -57,13 +57,13 @@ const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
`};
`
const InputTitle = styled(TYPE.small)`
const InputTitle = styled(ThemedText.Small)`
color: ${({ theme }) => theme.text2};
font-size: 12px;
font-weight: 500;
`
const ButtonLabel = styled(TYPE.white)<{ disabled: boolean }>`
const ButtonLabel = styled(ThemedText.White)<{ disabled: boolean }>`
color: ${({ theme, disabled }) => (disabled ? theme.text2 : theme.text1)} !important;
`
......
......@@ -37,7 +37,7 @@ export const Area = ({
.y0(yScale(0))(
series.filter((d) => {
const value = xScale(xValue(d))
return value > 0 && value <= innerWidth
return value > 0 && value <= window.innerWidth
}) as Iterable<[number, number]>
) ?? undefined
}
......
......@@ -14,7 +14,7 @@ import { batch } from 'react-redux'
import { Bound } from 'state/mint/v3/actions'
import styled from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { Chart } from './Chart'
import { useDensityChartData } from './hooks'
import { ZoomLevels } from './types'
......@@ -58,9 +58,9 @@ function InfoBox({ message, icon }: { message?: ReactNode; icon: ReactNode }) {
<ColumnCenter style={{ height: '100%', justifyContent: 'center' }}>
{icon}
{message && (
<TYPE.mediumHeader padding={10} marginTop="20px" textAlign="center">
<ThemedText.MediumHeader padding={10} marginTop="20px" textAlign="center">
{message}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
)}
</ColumnCenter>
)
......
......@@ -5,7 +5,7 @@ import styled, { ThemeContext } from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { CloseIcon, CustomLightSpinner, TYPE } from '../../theme'
import { CloseIcon, CustomLightSpinner, ThemedText } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn, ColumnCenter } from '../Column'
......@@ -32,9 +32,9 @@ export function LoadingView({ children, onDismiss }: { children: any; onDismiss:
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
{children}
<TYPE.subHeader>
<ThemedText.SubHeader>
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</AutoColumn>
</ConfirmOrLoadingWrapper>
)
......@@ -68,9 +68,9 @@ export function SubmittedView({
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
style={{ marginLeft: '4px' }}
>
<TYPE.subHeader>
<ThemedText.SubHeader>
<Trans>View transaction on Explorer</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</ExternalLink>
)}
</AutoColumn>
......
......@@ -10,7 +10,7 @@ import { useAppDispatch } from 'state/hooks'
import { resetMintState } from 'state/mint/actions'
import { resetMintState as resetMintV3State } from 'state/mint/v3/actions'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import Row, { RowBetween } from '../Row'
import SettingsTab from '../Settings'
......@@ -136,7 +136,7 @@ export function AddRemoveTabs({
>
<StyledArrowLeft stroke={theme.text2} />
</StyledHistoryLink>
<TYPE.mediumHeader
<ThemedText.MediumHeader
fontWeight={500}
fontSize={20}
style={{ flex: '1', margin: 'auto', textAlign: children ? 'start' : 'center' }}
......@@ -148,7 +148,7 @@ export function AddRemoveTabs({
) : (
<Trans>Remove Liquidity</Trans>
)}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<Box style={{ marginRight: '.5rem' }}>{children}</Box>
<SettingsTab placeholderSlippage={defaultSlippage} />
</RowBetween>
......
......@@ -6,7 +6,6 @@ import ReactGA from 'react-ga'
import styled, { keyframes } from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { ButtonPrimary } from '../../components/Button'
import { useActiveWeb3React } from '../../hooks/web3'
import {
useModalOpen,
......@@ -16,7 +15,8 @@ import {
} from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { ButtonPrimary } from '../Button'
import { AutoColumn } from '../Column'
import { CardBGImage, CardNoise } from '../earn/styled'
......@@ -98,10 +98,10 @@ export default function ClaimPopup() {
<StyledClose stroke="white" onClick={toggleShowClaimPopup} />
<AutoColumn style={{ padding: '2rem 0', zIndex: 10 }} justify="center">
<UniToken width="48px" src={tokenLogo} />{' '}
<TYPE.white style={{ marginTop: '1rem' }} fontSize={36} fontWeight={600}>
<ThemedText.White style={{ marginTop: '1rem' }} fontSize={36} fontWeight={600}>
{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
</TYPE.white>
<TYPE.white style={{ paddingTop: '1.25rem', textAlign: 'center' }} fontWeight={600} color="white">
</ThemedText.White>
<ThemedText.White style={{ paddingTop: '1.25rem', textAlign: 'center' }} fontWeight={600} color="white">
<span role="img" aria-label="party">
🎉
</span>{' '}
......@@ -109,12 +109,12 @@ export default function ClaimPopup() {
<span role="img" aria-label="party">
🎉
</span>
</TYPE.white>
<TYPE.subHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
</ThemedText.White>
<ThemedText.SubHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
<Trans>
Thanks for being part of the Uniswap community <Heart size={12} />
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</AutoColumn>
<AutoColumn style={{ zIndex: 10 }} justify="center">
<ButtonPrimary padding="8px" $borderRadius="8px" width={'fit-content'} onClick={handleToggleSelfClaimModal}>
......
......@@ -4,8 +4,8 @@ import styled, { ThemeContext } from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTransaction } from '../../state/transactions/hooks'
import { TYPE } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { ThemedText } from '../../theme'
import { ExternalLink } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { TransactionSummary } from '../AccountDetails/TransactionSummary'
import { AutoColumn } from '../Column'
......@@ -30,9 +30,9 @@ export default function TransactionPopup({ hash }: { hash: string }) {
{success ? <CheckCircle color={theme.green1} size={24} /> : <AlertCircle color={theme.red1} size={24} />}
</div>
<AutoColumn gap="8px">
<TYPE.body fontWeight={500}>
<ThemedText.Body fontWeight={500}>
<TransactionSummary info={tx.info} />
</TYPE.body>
</ThemedText.Body>
{chainId && (
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
View on Explorer
......
......@@ -14,7 +14,7 @@ import { useColor } from '../../hooks/useColor'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button'
......@@ -142,7 +142,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
</GreyCard>
) : (
<LightCard>
<TYPE.subHeader style={{ textAlign: 'center' }}>
<ThemedText.SubHeader style={{ textAlign: 'center' }}>
<span role="img" aria-label="wizard-icon">
⭐️
</span>{' '}
......@@ -150,7 +150,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
By adding liquidity you&apos;ll earn 0.3% of all trades on this pair proportional to your share of the
pool. Fees are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
</Trans>{' '}
</TYPE.subHeader>
</ThemedText.SubHeader>
</LightCard>
)}
</>
......
......@@ -13,7 +13,7 @@ import JSBI from 'jsbi'
import { ReactNode, useCallback, useContext, useState } from 'react'
import { Bound } from 'state/mint/v3/actions'
import { ThemeContext } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { formatTickPrice } from 'utils/formatTickPrice'
import { unwrappedToken } from 'utils/unwrappedToken'
......@@ -70,9 +70,9 @@ export const PositionPreview = ({
size={24}
margin={true}
/>
<TYPE.label ml="10px" fontSize="24px">
<ThemedText.Label ml="10px" fontSize="24px">
{currency0?.symbol} / {currency1?.symbol}
</TYPE.label>
</ThemedText.Label>
</RowFixed>
<RangeBadge removed={removed} inRange={inRange} />
</RowBetween>
......@@ -82,36 +82,36 @@ export const PositionPreview = ({
<RowBetween>
<RowFixed>
<CurrencyLogo currency={currency0} />
<TYPE.label ml="8px">{currency0?.symbol}</TYPE.label>
<ThemedText.Label ml="8px">{currency0?.symbol}</ThemedText.Label>
</RowFixed>
<RowFixed>
<TYPE.label mr="8px">{position.amount0.toSignificant(4)}</TYPE.label>
<ThemedText.Label mr="8px">{position.amount0.toSignificant(4)}</ThemedText.Label>
</RowFixed>
</RowBetween>
<RowBetween>
<RowFixed>
<CurrencyLogo currency={currency1} />
<TYPE.label ml="8px">{currency1?.symbol}</TYPE.label>
<ThemedText.Label ml="8px">{currency1?.symbol}</ThemedText.Label>
</RowFixed>
<RowFixed>
<TYPE.label mr="8px">{position.amount1.toSignificant(4)}</TYPE.label>
<ThemedText.Label mr="8px">{position.amount1.toSignificant(4)}</ThemedText.Label>
</RowFixed>
</RowBetween>
<Break />
<RowBetween>
<TYPE.label>
<ThemedText.Label>
<Trans>Fee Tier</Trans>
</TYPE.label>
<TYPE.label>
</ThemedText.Label>
<ThemedText.Label>
<Trans>{position?.pool?.fee / 10000}%</Trans>
</TYPE.label>
</ThemedText.Label>
</RowBetween>
</AutoColumn>
</LightCard>
<AutoColumn gap="md">
<RowBetween>
{title ? <TYPE.main>{title}</TYPE.main> : <div />}
{title ? <ThemedText.Main>{title}</ThemedText.Main> : <div />}
<RateToggle
currencyA={sorted ? currency0 : currency1}
currencyB={sorted ? currency1 : currency0}
......@@ -122,57 +122,57 @@ export const PositionPreview = ({
<RowBetween>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">
<ThemedText.Main fontSize="12px">
<Trans>Min Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${formatTickPrice(
</ThemedText.Main>
<ThemedText.MediumHeader textAlign="center">{`${formatTickPrice(
priceLower,
ticksAtLimit,
Bound.LOWER
)}`}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
)}`}</ThemedText.MediumHeader>
<ThemedText.Main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
</ThemedText.Main>
<ThemedText.Small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
<Trans>Your position will be 100% composed of {baseCurrency?.symbol} at this price</Trans>
</TYPE.small>
</ThemedText.Small>
</AutoColumn>
</LightCard>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">
<ThemedText.Main fontSize="12px">
<Trans>Max Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${formatTickPrice(
</ThemedText.Main>
<ThemedText.MediumHeader textAlign="center">{`${formatTickPrice(
priceUpper,
ticksAtLimit,
Bound.UPPER
)}`}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
)}`}</ThemedText.MediumHeader>
<ThemedText.Main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
</ThemedText.Main>
<ThemedText.Small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
<Trans>Your position will be 100% composed of {quoteCurrency?.symbol} at this price</Trans>
</TYPE.small>
</ThemedText.Small>
</AutoColumn>
</LightCard>
</RowBetween>
<LightCard padding="12px ">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">
<ThemedText.Main fontSize="12px">
<Trans>Current price</Trans>
</TYPE.main>
<TYPE.mediumHeader>{`${price.toSignificant(5)} `}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
</ThemedText.Main>
<ThemedText.MediumHeader>{`${price.toSignificant(5)} `}</ThemedText.MediumHeader>
<ThemedText.Main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoColumn>
</LightCard>
</AutoColumn>
......
......@@ -5,7 +5,7 @@ import { useEffect, useRef } from 'react'
import { ArrowDown, Info, X } from 'react-feather'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import { ExternalLink, TYPE } from 'theme'
import { ExternalLink, ThemedText } from 'theme'
import { isMobile } from 'utils/userAgent'
import { useModalOpen, useTogglePrivacyPolicy } from '../../state/application/hooks'
......@@ -91,9 +91,9 @@ export function PrivacyPolicyModal() {
<Modal isOpen={open} onDismiss={() => toggle()}>
<AutoColumn gap="12px" ref={node as any}>
<RowBetween padding="1rem 1rem 0.5rem 1rem">
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Legal & Privacy</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<HoverText onClick={() => toggle()}>
<X size={24} />
</HoverText>
......@@ -122,9 +122,9 @@ export function PrivacyPolicy() {
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<TYPE.main fontSize={14} color={'primaryText1'}>
<ThemedText.Main fontSize={14} color={'primaryText1'}>
<Trans>Uniswap Labs&apos; Terms of Service</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoRow>
<StyledLinkOut size={20} />
</RowBetween>
......@@ -135,29 +135,29 @@ export function PrivacyPolicy() {
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<TYPE.main fontSize={14} color={'primaryText1'}>
<ThemedText.Main fontSize={14} color={'primaryText1'}>
<Trans>Protocol Disclaimer</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoRow>
<StyledLinkOut size={20} />
</RowBetween>
</ExternalLink>
</StyledExternalCard>
</AutoColumn>
<TYPE.main fontSize={14}>
<ThemedText.Main fontSize={14}>
<Trans>This app uses the following third-party APIs:</Trans>
</TYPE.main>
</ThemedText.Main>
<AutoColumn gap="12px">
{EXTERNAL_APIS.map(({ name, description }, i) => (
<DarkGreyCard key={i}>
<AutoColumn gap="8px">
<AutoRow gap="4px">
<Info size={18} />
<TYPE.main fontSize={14} color={'text1'}>
<ThemedText.Main fontSize={14} color={'text1'}>
{name}
</TYPE.main>
</ThemedText.Main>
</AutoRow>
<TYPE.main fontSize={14}>{description}</TYPE.main>
<ThemedText.Main fontSize={14}>{description}</ThemedText.Main>
</AutoColumn>
</DarkGreyCard>
))}
......
......@@ -2,7 +2,7 @@ import { useContext } from 'react'
import styled from 'styled-components/macro'
import { ThemeContext } from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
const Wrapper = styled(AutoColumn)`
......@@ -65,7 +65,7 @@ export default function ProgressCircles({ steps, disabled = false, ...rest }: Pr
<Circle confirmed={step} disabled={disabled || (!steps[i - 1] && i !== 0)}>
{step ? '' : i + 1 + '.'}
</Circle>
<TYPE.main color={theme.text4}>|</TYPE.main>
<ThemedText.Main color={theme.text4}>|</ThemedText.Main>
</CircleRow>
)
})}
......
......@@ -4,7 +4,7 @@ import { AutoRow } from 'components/Row'
import React from 'react'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
const Button = styled(ButtonOutlined).attrs(() => ({
padding: '8px',
......@@ -26,9 +26,9 @@ export default function PresetsButtons({ setFullRange }: { setFullRange: () => v
})
}}
>
<TYPE.body fontSize={12}>
<ThemedText.Body fontSize={12}>
<Trans>Full Range</Trans>
</TYPE.body>
</ThemedText.Body>
</Button>
</AutoRow>
)
......
......@@ -7,7 +7,7 @@ import Row, { AutoRow } from 'components/Row'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
import { Box } from 'rebass'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { ReactComponent as DotLine } from '../../assets/svg/dot_line.svg'
......@@ -93,9 +93,9 @@ function Route({ percent, path }: { percent: RoutingDiagramEntry['percent']; pat
<DotColor />
</DottedLine>
<OpaqueBadge>
<TYPE.small fontSize={12} style={{ wordBreak: 'normal' }}>
<ThemedText.Small fontSize={12} style={{ wordBreak: 'normal' }}>
{percent.toSignificant(2)}%
</TYPE.small>
</ThemedText.Small>
</OpaqueBadge>
<AutoRow gap="1px" width="100%" style={{ justifyContent: 'space-evenly', zIndex: 2 }}>
......@@ -116,7 +116,7 @@ function Pool({ currency0, currency1, feeAmount }: { currency0: Currency; curren
<Box margin="0 5px 0 10px">
<DoubleCurrencyLogo currency0={tokenInfo1} currency1={tokenInfo0} size={20} />
</Box>
<TYPE.small fontSize={12}>{feeAmount / 10000}%</TYPE.small>
<ThemedText.Small fontSize={12}>{feeAmount / 10000}%</ThemedText.Small>
</PoolBadge>
)
}
......@@ -3,7 +3,7 @@ import { Token } from '@uniswap/sdk-core'
import { ButtonPrimary } from 'components/Button'
import { AlertCircle, ArrowLeft } from 'react-feather'
import styled from 'styled-components/macro'
import { CloseIcon, TYPE } from 'theme'
import { CloseIcon, ThemedText } from 'theme'
import TokenImportCard from './TokenImportCard'
......@@ -22,7 +22,7 @@ const Button = styled(ButtonPrimary)`
const Content = styled.div`
padding: 1em;
`
const Copy = styled(TYPE.body)`
const Copy = styled(ThemedText.Body)`
text-align: center;
margin: 0 2em 1em !important;
font-weight: 400;
......@@ -51,9 +51,9 @@ const BlockedToken = ({ onBack, onDismiss, blockedTokens }: BlockedTokenProps) =
<Wrapper>
<Header>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Token not supported</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
</Header>
<Icon />
......
......@@ -14,7 +14,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { useCombinedActiveList } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { isTokenOnList } from '../../utils'
import Column from '../Column'
import CurrencyLogo from '../CurrencyLogo'
......@@ -135,13 +135,13 @@ function CurrencyRow({
<Text title={currency.name} fontWeight={500}>
{currency.symbol}
</Text>
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
<ThemedText.DarkGray ml="0px" fontSize={'12px'} fontWeight={300}>
{!currency.isNative && !isOnSelectedList && customAdded ? (
<Trans>{currency.name} • Added by user</Trans>
) : (
currency.name
)}
</TYPE.darkGray>
</ThemedText.DarkGray>
</Column>
<TokenTags currency={currency} />
{showCurrencyAmount && (
......@@ -167,9 +167,9 @@ function BreakLineComponent({ style }: { style: CSSProperties }) {
<RowBetween>
<RowFixed>
<TokenListLogoWrapper src={TokenListLogo} />
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
<ThemedText.Main ml="6px" fontSize="12px" color={theme.text1}>
<Trans>Expanded results from inactive Token Lists</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
<QuestionHelper
text={
......
......@@ -16,7 +16,7 @@ import styled from 'styled-components/macro'
import { ExtendedEther } from '../../constants/tokens'
import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens'
import { useActiveWeb3React } from '../../hooks/web3'
import { ButtonText, CloseIcon, IconWrapper, TYPE } from '../../theme'
import { ButtonText, CloseIcon, IconWrapper, ThemedText } from '../../theme'
import { isAddress } from '../../utils'
import Column from '../Column'
import Row, { RowBetween, RowFixed } from '../Row'
......@@ -224,9 +224,9 @@ export function CurrencySearch({
</div>
) : (
<Column style={{ padding: '20px', height: '100%' }}>
<TYPE.main color={theme.text3} textAlign="center" mb="20px">
<ThemedText.Main color={theme.text3} textAlign="center" mb="20px">
<Trans>No results found.</Trans>
</TYPE.main>
</ThemedText.Main>
</Column>
)}
<Footer>
......@@ -236,9 +236,9 @@ export function CurrencySearch({
<IconWrapper size="16px" marginRight="6px" stroke={theme.primaryText1}>
<Edit />
</IconWrapper>
<TYPE.main color={theme.primaryText1}>
<ThemedText.Main color={theme.primaryText1}>
<Trans>Manage Token Lists</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
</ButtonText>
</Row>
......
......@@ -16,9 +16,9 @@ import { useAppDispatch } from 'state/hooks'
import { enableList, removeList } from 'state/lists/actions'
import { useAllLists } from 'state/lists/hooks'
import styled from 'styled-components/macro'
import { CloseIcon, TYPE } from 'theme'
import { CloseIcon, ThemedText } from 'theme'
import { ExternalLink } from '../../theme/components'
import { ExternalLink } from '../../theme'
import { CurrencyModalView } from './CurrencySearchModal'
import { Checkbox, PaddedColumn, TextDot } from './styleds'
......@@ -81,9 +81,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
<ArrowLeft style={{ cursor: 'pointer' }} onClick={() => setModalView(CurrencyModalView.manage)} />
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Import List</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={onDismiss} />
</RowBetween>
</PaddedColumn>
......@@ -96,18 +96,18 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
{list.logoURI && <ListLogo logoURI={list.logoURI} size="40px" />}
<AutoColumn gap="sm" style={{ marginLeft: '20px' }}>
<RowFixed>
<TYPE.body fontWeight={600} mr="6px">
<ThemedText.Body fontWeight={600} mr="6px">
{list.name}
</TYPE.body>
</ThemedText.Body>
<TextDot />
<TYPE.main fontSize={'16px'} ml="6px">
<ThemedText.Main fontSize={'16px'} ml="6px">
<Trans>{list.tokens.length} tokens</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
<ExternalLink href={`https://tokenlists.org/token-list?url=${listURL}`}>
<TYPE.main fontSize={'12px'} color={theme.blue1}>
<ThemedText.Main fontSize={'12px'} color={theme.blue1}>
{listURL}
</TYPE.main>
</ThemedText.Main>
</ExternalLink>
</AutoColumn>
</RowFixed>
......@@ -116,22 +116,22 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<Card style={{ backgroundColor: transparentize(0.8, theme.red1) }}>
<AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<AlertTriangle stroke={theme.red1} size={32} />
<TYPE.body fontWeight={500} fontSize={20} color={theme.red1}>
<ThemedText.Body fontWeight={500} fontSize={20} color={theme.red1}>
<Trans>Import at your own risk</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
<AutoColumn style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<TYPE.body fontWeight={500} color={theme.red1}>
<ThemedText.Body fontWeight={500} color={theme.red1}>
<Trans>
By adding this list you are implicitly trusting that the data is correct. Anyone can create a list,
including creating fake versions of existing lists and lists that claim to represent projects that do
not have one.
</Trans>
</TYPE.body>
<TYPE.body fontWeight={600} color={theme.red1}>
</ThemedText.Body>
<ThemedText.Body fontWeight={600} color={theme.red1}>
<Trans>If you purchase a token from this list, you may not be able to sell it back.</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
<AutoRow justify="center" style={{ cursor: 'pointer' }} onClick={() => setConfirmed(!confirmed)}>
<Checkbox
......@@ -140,9 +140,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
checked={confirmed}
onChange={() => setConfirmed(!confirmed)}
/>
<TYPE.body ml="10px" fontSize="16px" color={theme.red1} fontWeight={500}>
<ThemedText.Body ml="10px" fontSize="16px" color={theme.red1} fontWeight={500}>
<Trans>I understand</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoRow>
</Card>
......@@ -156,9 +156,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<Trans>Import</Trans>
</ButtonPrimary>
{addError ? (
<TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
<ThemedText.Error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
{addError}
</TYPE.error>
</ThemedText.Error>
) : null}
</AutoColumn>
{/* </Card> */}
......
......@@ -10,7 +10,7 @@ import useTheme from 'hooks/useTheme'
import { CSSProperties } from 'react'
import { CheckCircle } from 'react-feather'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
......@@ -67,16 +67,16 @@ export default function ImportRow({
<CurrencyLogo currency={token} size={'24px'} style={{ opacity: dim ? '0.6' : '1' }} />
<AutoColumn gap="4px" style={{ opacity: dim ? '0.6' : '1' }}>
<AutoRow>
<TYPE.body fontWeight={500}>{token.symbol}</TYPE.body>
<TYPE.darkGray ml="8px" fontWeight={300}>
<ThemedText.Body fontWeight={500}>{token.symbol}</ThemedText.Body>
<ThemedText.DarkGray ml="8px" fontWeight={300}>
<NameOverflow title={token.name}>{token.name}</NameOverflow>
</TYPE.darkGray>
</ThemedText.DarkGray>
</AutoRow>
{list && list.logoURI && (
<RowFixed>
<TYPE.small mr="4px" color={theme.text3}>
<ThemedText.Small mr="4px" color={theme.text3}>
<Trans>via {list.name} </Trans>
</TYPE.small>
</ThemedText.Small>
<ListLogo logoURI={list.logoURI} size="12px" />
</RowFixed>
)}
......@@ -97,9 +97,9 @@ export default function ImportRow({
) : (
<RowFixed style={{ minWidth: 'fit-content' }}>
<CheckIcon />
<TYPE.main color={theme.green1}>
<ThemedText.Main color={theme.green1}>
<Trans>Active</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
)}
</TokenSection>
......
......@@ -10,7 +10,7 @@ import useTheme from 'hooks/useTheme'
import { AlertCircle, ArrowLeft } from 'react-feather'
import { useAddUserToken } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { CloseIcon, TYPE } from 'theme'
import { CloseIcon, ThemedText } from 'theme'
import BlockedToken from './BlockedToken'
import { PaddedColumn } from './styleds'
......@@ -47,9 +47,9 @@ export function ImportToken(props: ImportProps) {
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Plural value={tokens.length} one="Import token" other="Import tokens" />
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
</RowBetween>
</PaddedColumn>
......@@ -57,12 +57,12 @@ export function ImportToken(props: ImportProps) {
<AutoColumn gap="md" style={{ marginBottom: '32px', padding: '1rem' }}>
<AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', padding: '1rem' }}>
<AlertCircle size={48} stroke={theme.text2} strokeWidth={1} />
<TYPE.body fontWeight={400} fontSize={16}>
<ThemedText.Body fontWeight={400} fontSize={16}>
<Trans>
This token doesn&apos;t appear on the active token list(s). Make sure this is the token that you want to
trade.
</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
{tokens.map((token) => (
<TokenImportCard token={token} list={list} key={'import' + token.address} />
......
......@@ -18,7 +18,7 @@ import useTheme from '../../hooks/useTheme'
import useToggle from '../../hooks/useToggle'
import { acceptListUpdate, disableList, enableList, removeList } from '../../state/lists/actions'
import { useActiveListUrls, useAllLists, useIsListActive } from '../../state/lists/hooks'
import { ExternalLink, IconWrapper, LinkStyledButton, TYPE } from '../../theme'
import { ExternalLink, IconWrapper, LinkStyledButton, ThemedText } from '../../theme'
import listVersionLabel from '../../utils/listVersionLabel'
import { parseENSAddress } from '../../utils/parseENSAddress'
import uriToHttp from '../../utils/uriToHttp'
......@@ -75,7 +75,7 @@ const StyledTitleText = styled.div<{ active: boolean }>`
color: ${({ theme, active }) => (active ? theme.white : theme.text2)};
`
const StyledListUrlText = styled(TYPE.main)<{ active: boolean }>`
const StyledListUrlText = styled(ThemedText.Main)<{ active: boolean }>`
font-size: 12px;
color: ${({ theme, active }) => (active ? theme.white : theme.text2)};
`
......@@ -361,9 +361,9 @@ export function ManageLists({
/>
</Row>
{addError ? (
<TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
<ThemedText.Error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
{addError}
</TYPE.error>
</ThemedText.Error>
) : null}
</PaddedColumn>
{tempList && (
......@@ -373,10 +373,10 @@ export function ManageLists({
<RowFixed>
{tempList.logoURI && <ListLogo logoURI={tempList.logoURI} size="40px" />}
<AutoColumn gap="4px" style={{ marginLeft: '20px' }}>
<TYPE.body fontWeight={600}>{tempList.name}</TYPE.body>
<TYPE.main fontSize={'12px'}>
<ThemedText.Body fontWeight={600}>{tempList.name}</ThemedText.Body>
<ThemedText.Main fontSize={'12px'}>
<Trans>{tempList.tokens.length} tokens</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoColumn>
</RowFixed>
{isImported ? (
......@@ -384,9 +384,9 @@ export function ManageLists({
<IconWrapper stroke={theme.text2} size="16px" marginRight={'10px'}>
<CheckCircle />
</IconWrapper>
<TYPE.body color={theme.text2}>
<ThemedText.Body color={theme.text2}>
<Trans>Loaded</Trans>
</TYPE.body>
</ThemedText.Body>
</RowFixed>
) : (
<ButtonPrimary
......
......@@ -9,7 +9,7 @@ import { useActiveWeb3React } from 'hooks/web3'
import { RefObject, useCallback, useMemo, useRef, useState } from 'react'
import { useRemoveUserAddedToken, useUserAddedTokens } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ButtonText, ExternalLink, ExternalLinkIcon, TrashIcon, TYPE } from 'theme'
import { ButtonText, ExternalLink, ExternalLinkIcon, ThemedText, TrashIcon } from 'theme'
import { isAddress } from 'utils'
import useTheme from '../../hooks/useTheme'
......@@ -81,9 +81,9 @@ export default function ManageTokens({
<RowFixed>
<CurrencyLogo currency={token} size={'20px'} />
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
<TYPE.main ml={'10px'} fontWeight={600}>
<ThemedText.Main ml={'10px'} fontWeight={600}>
{token.symbol}
</TYPE.main>
</ThemedText.Main>
</ExternalLink>
</RowFixed>
<RowFixed>
......@@ -111,9 +111,9 @@ export default function ManageTokens({
/>
</Row>
{searchQuery !== '' && !isAddressSearch && (
<TYPE.error error={true}>
<ThemedText.Error error={true}>
<Trans>Enter valid token address</Trans>
</TYPE.error>
</ThemedText.Error>
)}
{searchToken && (
<Card backgroundColor={theme.bg2} padding="10px 0">
......@@ -129,14 +129,14 @@ export default function ManageTokens({
<Separator />
<PaddedColumn gap="lg" style={{ overflow: 'auto', marginBottom: '10px' }}>
<RowBetween>
<TYPE.main fontWeight={600}>
<ThemedText.Main fontWeight={600}>
<Trans>{userAddedTokens?.length} Custom Tokens</Trans>
</TYPE.main>
</ThemedText.Main>
{userAddedTokens.length > 0 && (
<ButtonText onClick={handleRemoveAll}>
<TYPE.blue>
<ThemedText.Blue>
<Trans>Clear all</Trans>
</TYPE.blue>
</ThemedText.Blue>
</ButtonText>
)}
</RowBetween>
......@@ -144,9 +144,9 @@ export default function ManageTokens({
</PaddedColumn>
</Column>
<Footer>
<TYPE.darkGray>
<ThemedText.DarkGray>
<Trans>Tip: Custom tokens are stored locally in your browser</Trans>
</TYPE.darkGray>
</ThemedText.DarkGray>
</Footer>
</Wrapper>
)
......
......@@ -10,7 +10,7 @@ import { useActiveWeb3React } from 'hooks/web3'
import { transparentize } from 'polished'
import { AlertCircle } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro'
import { ExternalLink, TYPE } from 'theme'
import { ExternalLink, ThemedText } from 'theme'
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink'
const WarningWrapper = styled(Card)<{ highWarning: boolean }>`
......@@ -19,7 +19,7 @@ const WarningWrapper = styled(Card)<{ highWarning: boolean }>`
width: fit-content;
`
const AddressText = styled(TYPE.blue)`
const AddressText = styled(ThemedText.Blue)`
font-size: 12px;
word-break: break-all;
......@@ -39,12 +39,12 @@ const TokenImportCard = ({ list, token }: TokenImportCardProps) => {
<AutoColumn gap="10px" justify="center">
<CurrencyLogo currency={token} size={'32px'} />
<AutoColumn gap="4px" justify="center">
<TYPE.body ml="8px" mr="8px" fontWeight={500} fontSize={20}>
<ThemedText.Body ml="8px" mr="8px" fontWeight={500} fontSize={20}>
{token.symbol}
</TYPE.body>
<TYPE.darkGray fontWeight={400} fontSize={14}>
</ThemedText.Body>
<ThemedText.DarkGray fontWeight={400} fontSize={14}>
{token.name}
</TYPE.darkGray>
</ThemedText.DarkGray>
</AutoColumn>
{chainId && (
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
......@@ -54,17 +54,17 @@ const TokenImportCard = ({ list, token }: TokenImportCardProps) => {
{list !== undefined ? (
<RowFixed>
{list.logoURI && <ListLogo logoURI={list.logoURI} size="16px" />}
<TYPE.small ml="6px" fontSize={14} color={theme.text3}>
<ThemedText.Small ml="6px" fontSize={14} color={theme.text3}>
<Trans>via {list.name} token list</Trans>
</TYPE.small>
</ThemedText.Small>
</RowFixed>
) : (
<WarningWrapper $borderRadius="4px" padding="4px" highWarning={true}>
<RowFixed>
<AlertCircle stroke={theme.red1} size="10px" />
<TYPE.body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}>
<ThemedText.Body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}>
<Trans>Unknown Source</Trans>
</TYPE.body>
</ThemedText.Body>
</RowFixed>
</WarningWrapper>
)}
......
......@@ -13,7 +13,7 @@ import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { useModalOpen, useToggleSettingsMenu } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useClientSideRouter, useExpertModeManager } from '../../state/user/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
import Modal from '../Modal'
......@@ -203,9 +203,9 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa
{chainId === SupportedChainId.MAINNET && (
<RowBetween>
<RowFixed>
<TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Auto Router</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={<Trans>Use the Uniswap Labs API to get better pricing through a more efficient route.</Trans>}
/>
......@@ -226,9 +226,9 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa
<RowBetween>
<RowFixed>
<TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Expert Mode</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={
<Trans>Allow high price impact trades and skip the confirm screen. Use at your own risk.</Trans>
......
......@@ -5,9 +5,9 @@ import styled from 'styled-components/macro'
import { DEFAULT_LOCALE, LOCALE_LABEL, SupportedLocale } from '../../constants/locales'
import { navigatorLocale, useActiveLocale } from '../../hooks/useActiveLocale'
import { StyledInternalLink, TYPE } from '../../theme'
import { StyledInternalLink, ThemedText } from '../../theme'
const Container = styled(TYPE.small)`
const Container = styled(ThemedText.Small)`
opacity: 0.6;
:hover {
opacity: 1;
......
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>`
border-radius: 20px;
......@@ -25,7 +25,7 @@ const ToggleElement = styled.span<{ isActive?: boolean; bgColor?: string }>`
}
`
const StatusText = styled(TYPE.main)<{ isActive?: boolean }>`
const StatusText = styled(ThemedText.Main)<{ isActive?: boolean }>`
margin: 0 10px;
width: 24px;
color: ${({ theme, isActive }) => (isActive ? theme.text1 : theme.text3)};
......
......@@ -13,7 +13,7 @@ import Circle from '../../assets/images/blue-loader.svg'
import MetaMaskLogo from '../../assets/images/metamask.png'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink } from '../../theme'
import { CloseIcon, CustomLightSpinner } from '../../theme/components'
import { CloseIcon, CustomLightSpinner } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { TransactionSummary } from '../AccountDetails/TransactionSummary'
import { ButtonLight, ButtonPrimary } from '../Button'
......@@ -284,11 +284,11 @@ function L2Content({
</Text>
</ExternalLink>
) : (
<div style={{ height: '17px' }}></div>
<div style={{ height: '17px' }} />
)}
<Text color={theme.text3} style={{ margin: '20px 0 0 0' }} fontSize={'14px'}>
{!secondsToConfirm ? (
<div style={{ height: '24px' }}></div>
<div style={{ height: '24px' }} />
) : (
<div>
<Trans>Transaction completed in </Trans>
......
......@@ -8,7 +8,7 @@ import { useContext, useState } from 'react'
import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks'
import styled, { ThemeContext } from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
import QuestionHelper from '../QuestionHelper'
import { RowBetween, RowFixed } from '../Row'
......@@ -160,9 +160,9 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
<AutoColumn gap="md">
<AutoColumn gap="sm">
<RowFixed>
<TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Slippage tolerance</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={
<Trans>Your transaction will revert if the price changes unfavorably by more than this percentage.</Trans>
......@@ -229,9 +229,9 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
{showCustomDeadlineRow && (
<AutoColumn gap="sm">
<RowFixed>
<TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
<ThemedText.Black fontSize={14} fontWeight={400} color={theme.text2}>
<Trans>Transaction deadline</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={<Trans>Your transaction will revert if it is pending for more than this period of time.</Trans>}
/>
......@@ -255,9 +255,9 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
color={deadlineError ? 'red' : ''}
/>
</OptionCustom>
<TYPE.body style={{ paddingLeft: '8px' }} fontSize={14}>
<ThemedText.Body style={{ paddingLeft: '8px' }} fontSize={14}>
<Trans>minutes</Trans>
</TYPE.body>
</ThemedText.Body>
</RowFixed>
</AutoColumn>
)}
......
......@@ -19,7 +19,7 @@ import { SUPPORTED_WALLETS } from '../../constants/wallet'
import usePrevious from '../../hooks/usePrevious'
import { useModalOpen, useWalletModalToggle } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { isMobile } from '../../utils/userAgent'
import AccountDetails from '../AccountDetails'
import Card, { LightCard } from '../Card'
......@@ -344,9 +344,9 @@ export default function WalletModal({
<ArrowLeft />
</HoverText>
<Row justify="center">
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Legal & Privacy</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
</Row>
</HeaderRow>
<PrivacyPolicy />
......@@ -392,23 +392,23 @@ export default function WalletModal({
<AutoColumn gap="16px">
<LightCard>
<AutoRow style={{ flexWrap: 'nowrap' }}>
<TYPE.black fontSize={14}>
<ThemedText.Black fontSize={14}>
<Trans>
By connecting a wallet, you agree to Uniswap Labs’{' '}
<ExternalLink href="https://uniswap.org/terms-of-service/">Terms of Service</ExternalLink> and
acknowledge that you have read and understand the Uniswap{' '}
<ExternalLink href="https://uniswap.org/disclaimer/">Protocol Disclaimer</ExternalLink>.
</Trans>
</TYPE.black>
</ThemedText.Black>
</AutoRow>
</LightCard>
<LinkCard padding=".5rem" $borderRadius=".75rem" onClick={() => setWalletView(WALLET_VIEWS.LEGAL)}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<TYPE.white fontSize={14}>
<ThemedText.White fontSize={14}>
<Trans>How this app uses APIs</Trans>
</TYPE.white>
</ThemedText.White>
</AutoRow>
<ArrowRight size={16} />
</RowBetween>
......
......@@ -11,7 +11,7 @@ import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { useClaimCallback, useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { useIsTransactionPending } from '../../state/transactions/hooks'
import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE, UniTokenAnimated } from '../../theme'
import { CloseIcon, CustomLightSpinner, ExternalLink, ThemedText, UniTokenAnimated } from '../../theme'
import { shortenAddress } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import AddressInputPanel from '../AddressInputPanel'
......@@ -105,29 +105,29 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white fontWeight={500}>
<ThemedText.White fontWeight={500}>
<Trans>Claim UNI Token</Trans>
</TYPE.white>
</ThemedText.White>
<CloseIcon onClick={wrappedOnDismiss} style={{ zIndex: 99 }} stroke="white" />
</RowBetween>
<TYPE.white fontWeight={700} fontSize={36}>
<ThemedText.White fontWeight={700} fontSize={36}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
</TYPE.white>
</ThemedText.White>
</CardSection>
<Break />
</ModalUpper>
<AutoColumn gap="md" style={{ padding: '1rem', paddingTop: '0' }} justify="center">
<TYPE.subHeader fontWeight={500}>
<ThemedText.SubHeader fontWeight={500}>
<Trans>
Enter an address to trigger a UNI claim. If the address has any claimable UNI it will be sent to them on
submission.
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<AddressInputPanel value={typed} onChange={handleRecipientType} />
{parsedAddress && !hasAvailableClaim && (
<TYPE.error error={true}>
<ThemedText.Error error={true}>
<Trans>Address has no available claim</Trans>
</TYPE.error>
</ThemedText.Error>
)}
<ButtonPrimary
disabled={!isAddress(parsedAddress ?? '') || !hasAvailableClaim}
......@@ -159,23 +159,23 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader fontWeight={600} color="black">
<ThemedText.LargeHeader fontWeight={600} color="black">
{claimConfirmed ? <Trans>Claimed</Trans> : <Trans>Claiming</Trans>}
</TYPE.largeHeader>
</ThemedText.LargeHeader>
{!claimConfirmed && (
<Text fontSize={36} color={'#ff007a'} fontWeight={800}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
</Text>
)}
{parsedAddress && (
<TYPE.largeHeader fontWeight={600} color="black">
<ThemedText.LargeHeader fontWeight={600} color="black">
<Trans>for {shortenAddress(parsedAddress)}</Trans>
</TYPE.largeHeader>
</ThemedText.LargeHeader>
)}
</AutoColumn>
{claimConfirmed && (
<>
<TYPE.subHeader fontWeight={500} color="black">
<ThemedText.SubHeader fontWeight={500} color="black">
<span role="img" aria-label="party-hat">
🎉{' '}
</span>
......@@ -183,13 +183,13 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
<span role="img" aria-label="party-hat">
🎉
</span>
</TYPE.subHeader>
</ThemedText.SubHeader>
</>
)}
{attempting && !hash && (
<TYPE.subHeader color="black">
<ThemedText.SubHeader color="black">
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
)}
{attempting && hash && !claimConfirmed && chainId && hash && (
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)} style={{ zIndex: 99 }}>
......
......@@ -13,7 +13,7 @@ import { useModalOpen, useToggleSelfClaimModal } from '../../state/application/h
import { ApplicationModal } from '../../state/application/reducer'
import { useClaimCallback, useUserClaimData, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { useUserHasSubmittedClaim } from '../../state/transactions/hooks'
import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE, UniTokenAnimated } from '../../theme'
import { CloseIcon, CustomLightSpinner, ExternalLink, ThemedText, UniTokenAnimated } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { ButtonPrimary } from '../Button'
import { AutoColumn, ColumnCenter } from '../Column'
......@@ -100,63 +100,63 @@ export default function ClaimModal() {
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white fontWeight={500}>
<ThemedText.White fontWeight={500}>
<Trans>Claim UNI</Trans>
</TYPE.white>
</ThemedText.White>
<CloseIcon onClick={toggleClaimModal} style={{ zIndex: 99 }} color="white" />
</RowBetween>
<TYPE.white fontWeight={700} fontSize={36}>
<ThemedText.White fontWeight={700} fontSize={36}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
</TYPE.white>
</ThemedText.White>
</CardSection>
<Break />
<CardSection gap="sm">
{userClaimData?.flags?.isSOCKS && (
<RowBetween>
<TYPE.subHeader color="white">SOCKS</TYPE.subHeader>
<TYPE.subHeader color="white">
<ThemedText.SubHeader color="white">SOCKS</ThemedText.SubHeader>
<ThemedText.SubHeader color="white">
<Trans>{SOCKS_AMOUNT} UNI</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowBetween>
)}
{userClaimData?.flags?.isLP &&
unclaimedAmount &&
JSBI.greaterThanOrEqual(unclaimedAmount.quotient, nonLPAmount) && (
<RowBetween>
<TYPE.subHeader color="white">
<ThemedText.SubHeader color="white">
<Trans>Liquidity</Trans>
</TYPE.subHeader>
<TYPE.subHeader color="white">
</ThemedText.SubHeader>
<ThemedText.SubHeader color="white">
<Trans>
{unclaimedAmount
.subtract(CurrencyAmount.fromRawAmount(unclaimedAmount.currency, nonLPAmount))
.toFixed(0, { groupSeparator: ',' })}{' '}
UNI
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowBetween>
)}
{userClaimData?.flags?.isUser && (
<RowBetween>
<TYPE.subHeader color="white">
<ThemedText.SubHeader color="white">
<Trans>User</Trans>
</TYPE.subHeader>
<TYPE.subHeader color="white">
</ThemedText.SubHeader>
<ThemedText.SubHeader color="white">
<Trans>{USER_AMOUNT} UNI</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowBetween>
)}
</CardSection>
</ModalUpper>
<AutoColumn gap="md" style={{ padding: '1rem', paddingTop: '0' }} justify="center">
<TYPE.subHeader fontWeight={500}>
<ThemedText.SubHeader fontWeight={500}>
<Trans>
As a member of the Uniswap community you may claim UNI to be used for voting and governance.
<br />
<br />
<ExternalLink href="https://uniswap.org/blog/uni">Read more about UNI</ExternalLink>
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<ButtonPrimary
disabled={!isAddress(account ?? '')}
padding="16px 16px"
......@@ -187,9 +187,9 @@ export default function ClaimModal() {
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader fontWeight={600} color="black">
<ThemedText.LargeHeader fontWeight={600} color="black">
{claimConfirmed ? <Trans>Claimed!</Trans> : <Trans>Claiming</Trans>}
</TYPE.largeHeader>
</ThemedText.LargeHeader>
{!claimConfirmed && (
<Text fontSize={36} color={'#ff007a'} fontWeight={800}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
......@@ -198,7 +198,7 @@ export default function ClaimModal() {
</AutoColumn>
{claimConfirmed && (
<>
<TYPE.subHeader fontWeight={500} color="black">
<ThemedText.SubHeader fontWeight={500} color="black">
<Trans>
<span role="img" aria-label="party-hat">
🎉{' '}
......@@ -208,13 +208,13 @@ export default function ClaimModal() {
🎉
</span>
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</>
)}
{attempting && !claimSubmitted && (
<TYPE.subHeader color="black">
<ThemedText.SubHeader color="black">
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
)}
{attempting && claimSubmitted && !claimConfirmed && chainId && claimTxn?.hash && (
<ExternalLink
......
......@@ -8,7 +8,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { CloseIcon, TYPE } from '../../theme'
import { CloseIcon, ThemedText } from '../../theme'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
import Modal from '../Modal'
......@@ -74,24 +74,24 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
{!attempting && !hash && (
<ContentWrapper gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Claim</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={wrappedOnDismiss} />
</RowBetween>
{stakingInfo?.earnedAmount && (
<AutoColumn justify="center" gap="md">
<TYPE.body fontWeight={600} fontSize={36}>
<ThemedText.Body fontWeight={600} fontSize={36}>
{stakingInfo?.earnedAmount?.toSignificant(6)}
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>Unclaimed UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
)}
<TYPE.subHeader style={{ textAlign: 'center' }}>
<ThemedText.SubHeader style={{ textAlign: 'center' }}>
<Trans>When you claim without withdrawing your liquidity remains in the mining pool.</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<ButtonError disabled={!!error} error={!!error && !!stakingInfo?.stakedAmount} onClick={onClaimReward}>
{error ?? <Trans>Claim</Trans>}
</ButtonError>
......@@ -100,21 +100,21 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
{attempting && !hash && (
<LoadingView onDismiss={wrappedOnDismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.body fontSize={20}>
<ThemedText.Body fontSize={20}>
<Trans>Claiming {stakingInfo?.earnedAmount?.toSignificant(6)} UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</LoadingView>
)}
{hash && (
<SubmittedView onDismiss={wrappedOnDismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>Claimed UNI!</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</SubmittedView>
)}
......
......@@ -9,7 +9,7 @@ import { useTotalSupply } from '../../hooks/useTotalSupply'
import useUSDCPrice from '../../hooks/useUSDCPrice'
import { useV2Pair } from '../../hooks/useV2Pairs'
import { StakingInfo } from '../../state/stake/hooks'
import { StyledInternalLink, TYPE } from '../../theme'
import { StyledInternalLink, ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonPrimary } from '../Button'
......@@ -115,9 +115,9 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
<TopSection>
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={24} />
<TYPE.white fontWeight={600} fontSize={24} style={{ marginLeft: '8px' }}>
<ThemedText.White fontWeight={600} fontSize={24} style={{ marginLeft: '8px' }}>
{currency0.symbol}-{currency1.symbol}
</TYPE.white>
</ThemedText.White>
<StyledInternalLink to={`/uni/${currencyId(currency0)}/${currencyId(currency1)}`} style={{ width: '100%' }}>
<ButtonPrimary padding="8px" $borderRadius="8px">
......@@ -128,22 +128,22 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
<StatContainer>
<RowBetween>
<TYPE.white>
<ThemedText.White>
<Trans>Total deposited</Trans>
</TYPE.white>
<TYPE.white>
</ThemedText.White>
<ThemedText.White>
{valueOfTotalStakedAmountInUSDC ? (
<Trans>${valueOfTotalStakedAmountInUSDC.toFixed(0, { groupSeparator: ',' })}</Trans>
) : (
<Trans>{valueOfTotalStakedAmountInWETH?.toSignificant(4, { groupSeparator: ',' }) ?? '-'} ETH</Trans>
)}
</TYPE.white>
</ThemedText.White>
</RowBetween>
<RowBetween>
<TYPE.white>
<ThemedText.White>
<Trans>Pool rate</Trans>
</TYPE.white>
<TYPE.white>
</ThemedText.White>
<ThemedText.White>
{stakingInfo ? (
stakingInfo.active ? (
<Trans>
......@@ -156,7 +156,7 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
) : (
'-'
)}
</TYPE.white>
</ThemedText.White>
</RowBetween>
</StatContainer>
......@@ -164,13 +164,13 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
<>
<Break />
<BottomSection showBackground={true}>
<TYPE.black color={'white'} fontWeight={500}>
<ThemedText.Black color={'white'} fontWeight={500}>
<span>
<Trans>Your rate</Trans>
</span>
</TYPE.black>
</ThemedText.Black>
<TYPE.black style={{ textAlign: 'right' }} color={'white'} fontWeight={500}>
<ThemedText.Black style={{ textAlign: 'right' }} color={'white'} fontWeight={500}>
<span role="img" aria-label="wizard-icon" style={{ marginRight: '0.5rem' }}>
</span>
......@@ -188,7 +188,7 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
) : (
'-'
)}
</TYPE.black>
</ThemedText.Black>
</BottomSection>
</>
)}
......
......@@ -13,7 +13,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { CloseIcon, TYPE } from '../../theme'
import { CloseIcon, ThemedText } from '../../theme'
import { formatCurrencyAmount } from '../../utils/formatCurrencyAmount'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { ButtonConfirmed, ButtonError } from '../Button'
......@@ -159,9 +159,9 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
{!attempting && !hash && (
<ContentWrapper gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Deposit</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={wrappedOnDismiss} />
</RowBetween>
<CurrencyInputPanel
......@@ -178,19 +178,19 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
<HypotheticalRewardRate dim={!hypotheticalRewardRate.greaterThan('0')}>
<div>
<TYPE.black fontWeight={600}>
<ThemedText.Black fontWeight={600}>
<Trans>Weekly Rewards</Trans>
</TYPE.black>
</ThemedText.Black>
</div>
<TYPE.black>
<ThemedText.Black>
<Trans>
{hypotheticalRewardRate
.multiply((60 * 60 * 24 * 7).toString())
.toSignificant(4, { groupSeparator: ',' })}{' '}
UNI / week
</Trans>
</TYPE.black>
</ThemedText.Black>
</HypotheticalRewardRate>
<RowBetween>
......@@ -216,24 +216,24 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
{attempting && !hash && (
<LoadingView onDismiss={wrappedOnDismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Depositing Liquidity</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>{parsedAmount?.toSignificant(4)} UNI-V2</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</LoadingView>
)}
{attempting && hash && (
<SubmittedView onDismiss={wrappedOnDismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>Deposited {parsedAmount?.toSignificant(4)} UNI-V2</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</SubmittedView>
)}
......
......@@ -8,7 +8,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { CloseIcon, TYPE } from '../../theme'
import { CloseIcon, ThemedText } from '../../theme'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
import FormattedCurrencyAmount from '../FormattedCurrencyAmount'
......@@ -76,34 +76,34 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
{!attempting && !hash && (
<ContentWrapper gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Withdraw</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={wrappedOndismiss} />
</RowBetween>
{stakingInfo?.stakedAmount && (
<AutoColumn justify="center" gap="md">
<TYPE.body fontWeight={600} fontSize={36}>
<ThemedText.Body fontWeight={600} fontSize={36}>
{<FormattedCurrencyAmount currencyAmount={stakingInfo.stakedAmount} />}
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>Deposited liquidity:</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
)}
{stakingInfo?.earnedAmount && (
<AutoColumn justify="center" gap="md">
<TYPE.body fontWeight={600} fontSize={36}>
<ThemedText.Body fontWeight={600} fontSize={36}>
{<FormattedCurrencyAmount currencyAmount={stakingInfo?.earnedAmount} />}
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>Unclaimed UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
)}
<TYPE.subHeader style={{ textAlign: 'center' }}>
<ThemedText.SubHeader style={{ textAlign: 'center' }}>
<Trans>When you withdraw, your UNI is claimed and your liquidity is removed from the mining pool.</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<ButtonError disabled={!!error} error={!!error && !!stakingInfo?.stakedAmount} onClick={onWithdraw}>
{error ?? <Trans>Withdraw & Claim</Trans>}
</ButtonError>
......@@ -112,27 +112,27 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
{attempting && !hash && (
<LoadingView onDismiss={wrappedOndismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.body fontSize={20}>
<ThemedText.Body fontSize={20}>
<Trans>Withdrawing {stakingInfo?.stakedAmount?.toSignificant(4)} UNI-V2</Trans>
</TYPE.body>
<TYPE.body fontSize={20}>
</ThemedText.Body>
<ThemedText.Body fontSize={20}>
<Trans>Claiming {stakingInfo?.earnedAmount?.toSignificant(4)} UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</LoadingView>
)}
{hash && (
<SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>Withdrew UNI-V2!</Trans>
</TYPE.body>
<TYPE.body fontSize={20}>
</ThemedText.Body>
<ThemedText.Body fontSize={20}>
<Trans>Claimed UNI!</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</SubmittedView>
)}
......
......@@ -6,7 +6,7 @@ import { LoadingRows } from 'components/Loader/styled'
import { useContext, useMemo } from 'react'
import { ThemeContext } from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { computeRealizedLPFeePercent } from '../../utils/prices'
import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row'
......@@ -56,55 +56,55 @@ export function AdvancedSwapDetails({ trade, allowedSlippage, syncing = false }:
</TransactionDetailsLabel>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Liquidity Provider Fee</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={65}>
<TYPE.black textAlign="right" fontSize={14}>
<ThemedText.Black textAlign="right" fontSize={14}>
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${realizedLPFee.currency.symbol}` : '-'}
</TYPE.black>
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Price Impact</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={50}>
<TYPE.black textAlign="right" fontSize={14}>
<ThemedText.Black textAlign="right" fontSize={14}>
<FormattedPriceImpact priceImpact={priceImpact} />
</TYPE.black>
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Allowed Slippage</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={45}>
<TYPE.black textAlign="right" fontSize={14}>
<ThemedText.Black textAlign="right" fontSize={14}>
{allowedSlippage.toFixed(2)}%
</TYPE.black>
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<ThemedText.SubHeader color={theme.text1}>
{trade.tradeType === TradeType.EXACT_INPUT ? <Trans>Minimum received</Trans> : <Trans>Maximum sent</Trans>}
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={70}>
<TYPE.black textAlign="right" fontSize={14}>
<ThemedText.Black textAlign="right" fontSize={14}>
{trade.tradeType === TradeType.EXACT_INPUT
? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}`
: `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`}
</TYPE.black>
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
</AutoColumn>
......
import { Trans } from '@lingui/macro'
import { useRoutingAPIEnabled } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { ReactComponent as AutoRouterIcon } from '../../assets/svg/auto_router.svg'
import { ReactComponent as StaticRouterIcon } from '../../assets/svg/static_route.svg'
......@@ -26,7 +26,7 @@ const StyledStaticRouterIcon = styled(StaticRouterIcon)`
}
`
const StyledAutoRouterLabel = styled(TYPE.black)`
const StyledAutoRouterLabel = styled(ThemedText.Black)`
line-height: 1rem;
/* fallback color */
......@@ -51,8 +51,8 @@ export function AutoRouterLabel() {
return routingAPIEnabled ? (
<StyledAutoRouterLabel fontSize={14}>Auto Router</StyledAutoRouterLabel>
) : (
<TYPE.black fontSize={14}>
<ThemedText.Black fontSize={14}>
<Trans>Trade Route</Trans>
</TYPE.black>
</ThemedText.Black>
)
}
......@@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { RowBetween, RowFixed } from '../Row'
import SettingsTab from '../Settings'
......@@ -17,9 +17,9 @@ export default function SwapHeader({ allowedSlippage }: { allowedSlippage: Perce
<StyledSwapHeader>
<RowBetween>
<RowFixed>
<TYPE.black fontWeight={500} fontSize={16} style={{ marginRight: '8px' }}>
<ThemedText.Black fontWeight={500} fontSize={16} style={{ marginRight: '8px' }}>
<Trans>Swap</Trans>
</TYPE.black>
</ThemedText.Black>
</RowFixed>
<RowFixed>
<SettingsTab placeholderSlippage={allowedSlippage} />
......
......@@ -8,7 +8,7 @@ import { Text } from 'rebass'
import styled, { ThemeContext } from 'styled-components/macro'
import { useUSDCValue } from '../../hooks/useUSDCPrice'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { isAddress, shortenAddress } from '../../utils'
import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact'
import { ButtonPrimary } from '../Button'
......@@ -64,9 +64,9 @@ export default function SwapModalHeader({
<LightCard padding="0.75rem 1rem">
<AutoColumn gap={'8px'}>
<RowBetween>
<TYPE.body color={theme.text3} fontWeight={500} fontSize={14}>
<ThemedText.Body color={theme.text3} fontWeight={500} fontSize={14}>
<Trans>From</Trans>
</TYPE.body>
</ThemedText.Body>
<FiatValue fiatValue={fiatValueInput} />
</RowBetween>
<RowBetween align="center">
......@@ -94,15 +94,15 @@ export default function SwapModalHeader({
<LightCard padding="0.75rem 1rem" style={{ marginBottom: '0.25rem' }}>
<AutoColumn gap={'8px'}>
<RowBetween>
<TYPE.body color={theme.text3} fontWeight={500} fontSize={14}>
<ThemedText.Body color={theme.text3} fontWeight={500} fontSize={14}>
<Trans>To</Trans>
</TYPE.body>
<TYPE.body fontSize={14} color={theme.text3}>
</ThemedText.Body>
<ThemedText.Body fontSize={14} color={theme.text3}>
<FiatValue
fiatValue={fiatValueOutput}
priceImpact={computeFiatValuePriceImpact(fiatValueInput, fiatValueOutput)}
/>
</TYPE.body>
</ThemedText.Body>
</RowBetween>
<RowBetween align="flex-end">
<RowFixed gap={'0px'}>
......@@ -120,9 +120,9 @@ export default function SwapModalHeader({
</AutoColumn>
</LightCard>
<RowBetween style={{ marginTop: '0.25rem', padding: '0 1rem' }}>
<TYPE.body color={theme.text2} fontWeight={500} fontSize={14}>
<ThemedText.Body color={theme.text2} fontWeight={500} fontSize={14}>
<Trans>Price</Trans>
</TYPE.body>
</ThemedText.Body>
<TradePrice price={trade.executionPrice} showInverted={showInverted} setShowInverted={setShowInverted} />
</RowBetween>
......@@ -135,9 +135,9 @@ export default function SwapModalHeader({
<RowBetween>
<RowFixed>
<AlertTriangle size={20} style={{ marginRight: '8px', minWidth: 24 }} />
<TYPE.main color={theme.primary1}>
<ThemedText.Main color={theme.primary1}>
<Trans>Price Updated</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
<ButtonPrimary
style={{ padding: '.5rem', width: 'fit-content', fontSize: '0.825rem', borderRadius: '12px' }}
......@@ -151,7 +151,7 @@ export default function SwapModalHeader({
<AutoColumn justify="flex-start" gap="sm" style={{ padding: '.75rem 1rem' }}>
{trade.tradeType === TradeType.EXACT_INPUT ? (
<TYPE.italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
<ThemedText.Italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
<Trans>
Output is estimated. You will receive at least{' '}
<b>
......@@ -159,9 +159,9 @@ export default function SwapModalHeader({
</b>{' '}
or the transaction will revert.
</Trans>
</TYPE.italic>
</ThemedText.Italic>
) : (
<TYPE.italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
<ThemedText.Italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
<Trans>
Input is estimated. You will sell at most{' '}
<b>
......@@ -169,17 +169,17 @@ export default function SwapModalHeader({
</b>{' '}
or the transaction will revert.
</Trans>
</TYPE.italic>
</ThemedText.Italic>
)}
</AutoColumn>
{recipient !== null ? (
<AutoColumn justify="flex-start" gap="sm" style={{ padding: '12px 0 0 0px' }}>
<TYPE.main>
<ThemedText.Main>
<Trans>
Output will be sent to{' '}
<b title={recipient}>{isAddress(recipient) ? shortenAddress(recipient) : recipient}</b>
</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoColumn>
) : null}
</AutoColumn>
......
......@@ -11,7 +11,7 @@ import { Version } from 'hooks/useToggledVersion'
import { memo } from 'react'
import { useRoutingAPIEnabled } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { getTradeVersion } from 'utils/getTradeVersion'
import { AutoRouterLabel, AutoRouterLogo } from './RouterLabel'
......@@ -46,9 +46,9 @@ export default memo(function SwapRoute({
</LoadingRows>
) : (
<Badge>
<TYPE.black fontSize={12}>
<ThemedText.Black fontSize={12}>
{getTradeVersion(trade) === Version.v2 ? <Trans>V2</Trans> : <Trans>V3</Trans>}
</TYPE.black>
</ThemedText.Black>
</Badge>
)}
</RowBetween>
......@@ -65,9 +65,9 @@ export default memo(function SwapRoute({
/>
)}
{routingAPIEnabled && (
<TYPE.main fontSize={12} width={400}>
<ThemedText.Main fontSize={12} width={400}>
<Trans>This route optimizes your price by considering split routes, multiple hops, and gas costs.</Trans>
</TYPE.main>
</ThemedText.Main>
)}
</AutoColumn>
)
......
......@@ -4,7 +4,7 @@ import useUSDCPrice from 'hooks/useUSDCPrice'
import { useCallback, useContext } from 'react'
import { Text } from 'rebass'
import styled, { ThemeContext } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
interface TradePriceProps {
price: Price<Currency, Currency>
......@@ -49,9 +49,9 @@ export default function TradePrice({ price, showInverted, setShowInverted }: Tra
{text}
</Text>{' '}
{usdcPrice && (
<TYPE.darkGray>
<ThemedText.DarkGray>
<Trans>(${usdcPrice.toSignificant(6, { groupSeparator: ',' })})</Trans>
</TYPE.darkGray>
</ThemedText.DarkGray>
)}
</StyledPriceContainer>
)
......
......@@ -9,7 +9,7 @@ import { AutoRow, RowBetween } from 'components/Row'
import { useActiveWeb3React } from 'hooks/web3'
import { useState } from 'react'
import styled from 'styled-components/macro'
import { CloseIcon, ExternalLink, TYPE, Z_INDEX } from 'theme'
import { CloseIcon, ExternalLink, ThemedText, Z_INDEX } from 'theme'
import { useUnsupportedTokens } from '../../hooks/Tokens'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
......@@ -37,7 +37,7 @@ const StyledButtonEmpty = styled(ButtonEmpty)`
text-decoration: none;
`
const AddressText = styled(TYPE.blue)`
const AddressText = styled(ThemedText.Blue)`
font-size: 12px;
${({ theme }) => theme.mediaWidth.upToSmall`
......@@ -70,9 +70,9 @@ export default function UnsupportedCurrencyFooter({
<Card padding="2rem">
<AutoColumn gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Unsupported Assets</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={() => setShowDetails(false)} />
</RowBetween>
{tokens.map((token) => {
......@@ -84,7 +84,7 @@ export default function UnsupportedCurrencyFooter({
<AutoColumn gap="10px">
<AutoRow gap="5px" align="center">
<CurrencyLogo currency={token} size={'24px'} />
<TYPE.body fontWeight={500}>{token.symbol}</TYPE.body>
<ThemedText.Body fontWeight={500}>{token.symbol}</ThemedText.Body>
</AutoRow>
{chainId && (
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
......@@ -97,20 +97,20 @@ export default function UnsupportedCurrencyFooter({
)
})}
<AutoColumn gap="lg">
<TYPE.body fontWeight={500}>
<ThemedText.Body fontWeight={500}>
<Trans>
Some assets are not available through this interface because they may not work well with the smart
contracts or we are unable to allow trading for legal reasons.
</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</AutoColumn>
</Card>
</Modal>
<StyledButtonEmpty padding={'0'} onClick={() => setShowDetails(true)}>
<TYPE.blue>
<ThemedText.Blue>
<Trans>Read more about unsupported assets</Trans>
</TYPE.blue>
</ThemedText.Blue>
</StyledButtonEmpty>
</DetailsFooter>
)
......
......@@ -5,8 +5,8 @@ import { ReactNode } from 'react'
import { AlertTriangle } from 'react-feather'
import { Text } from 'rebass'
import styled, { css } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
import TradePrice from './TradePrice'
......@@ -133,7 +133,7 @@ export const SwapShowAcceptChanges = styled(AutoColumn)`
margin-top: 8px;
`
export const TransactionDetailsLabel = styled(TYPE.black)`
export const TransactionDetailsLabel = styled(ThemedText.Black)`
border-bottom: 1px solid ${({ theme }) => theme.bg2};
padding-bottom: 0.5rem;
`
......
......@@ -10,7 +10,7 @@ import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { useDelegateCallback } from '../../state/governance/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import AddressInputPanel from '../AddressInputPanel'
import { ButtonPrimary } from '../Button'
import { AutoColumn } from '../Column'
......@@ -95,23 +95,25 @@ export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalPro
<ContentWrapper gap="lg">
<AutoColumn gap="lg" justify="center">
<RowBetween>
<TYPE.mediumHeader fontWeight={500}>{title}</TYPE.mediumHeader>
<ThemedText.MediumHeader fontWeight={500}>{title}</ThemedText.MediumHeader>
<StyledClosed stroke="black" onClick={wrappedOndismiss} />
</RowBetween>
<TYPE.body>
<ThemedText.Body>
<Trans>Earned UNI tokens represent voting shares in Uniswap governance.</Trans>
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>You can either vote on each proposal yourself or delegate your votes to a third party.</Trans>
</TYPE.body>
</ThemedText.Body>
{usingDelegate && <AddressInputPanel value={typed} onChange={handleRecipientType} />}
<ButtonPrimary disabled={!isAddress(parsedAddress ?? '')} onClick={onDelegate}>
<TYPE.mediumHeader color="white">
<ThemedText.MediumHeader color="white">
{usingDelegate ? <Trans>Delegate Votes</Trans> : <Trans>Self Delegate</Trans>}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
</ButtonPrimary>
<TextButton onClick={() => setUsingDelegate(!usingDelegate)}>
<TYPE.blue>{usingDelegate ? <Trans>Remove Delegate</Trans> : <Trans>Add Delegate +</Trans>}</TYPE.blue>
<ThemedText.Blue>
{usingDelegate ? <Trans>Remove Delegate</Trans> : <Trans>Add Delegate +</Trans>}
</ThemedText.Blue>
</TextButton>
</AutoColumn>
</ContentWrapper>
......@@ -119,20 +121,20 @@ export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalPro
{attempting && !hash && (
<LoadingView onDismiss={wrappedOndismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
{usingDelegate ? <Trans>Delegating votes</Trans> : <Trans>Unlocking Votes</Trans>}
</TYPE.largeHeader>
<TYPE.main fontSize={36}> {formatCurrencyAmount(uniBalance, 4)}</TYPE.main>
</ThemedText.LargeHeader>
<ThemedText.Main fontSize={36}> {formatCurrencyAmount(uniBalance, 4)}</ThemedText.Main>
</AutoColumn>
</LoadingView>
)}
{hash && (
<SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.main fontSize={36}>{formatCurrencyAmount(uniBalance, 4)}</TYPE.main>
</ThemedText.LargeHeader>
<ThemedText.Main fontSize={36}>{formatCurrencyAmount(uniBalance, 4)}</ThemedText.Main>
</AutoColumn>
</SubmittedView>
)}
......
......@@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro'
import { L2_CHAIN_IDS } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
const EmptyProposals = styled.div`
border: 1px solid ${({ theme }) => theme.text4};
......@@ -25,14 +25,14 @@ interface EmptyStateProps {
}
const EmptyState = ({ HeaderContent, SubHeaderContent }: EmptyStateProps) => (
<EmptyProposals>
<TYPE.body style={{ marginBottom: '8px' }}>
<ThemedText.Body style={{ marginBottom: '8px' }}>
<HeaderContent />
</TYPE.body>
<TYPE.subHeader>
</ThemedText.Body>
<ThemedText.SubHeader>
<Sub>
<SubHeaderContent />
</Sub>
</TYPE.subHeader>
</ThemedText.SubHeader>
</EmptyProposals>
)
......
......@@ -8,8 +8,8 @@ import Circle from '../../assets/images/blue-loader.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { useUserVotes, useVoteCallback } from '../../state/governance/hooks'
import { VoteOption } from '../../state/governance/types'
import { CustomLightSpinner, TYPE } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { CustomLightSpinner, ThemedText } from '../../theme'
import { ExternalLink } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { ButtonPrimary } from '../Button'
import { AutoColumn, ColumnCenter } from '../Column'
......@@ -85,7 +85,7 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, voteOption }:
<ContentWrapper gap="lg">
<AutoColumn gap="lg" justify="center">
<RowBetween>
<TYPE.mediumHeader fontWeight={500}>
<ThemedText.MediumHeader fontWeight={500}>
{voteOption === VoteOption.Against ? (
<Trans>Vote against proposal {proposalId}</Trans>
) : voteOption === VoteOption.For ? (
......@@ -93,14 +93,14 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, voteOption }:
) : (
<Trans>Vote to abstain on proposal {proposalId}</Trans>
)}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<StyledClosed stroke="black" onClick={wrappedOndismiss} />
</RowBetween>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>{formatCurrencyAmount(availableVotes, 4)} Votes</Trans>
</TYPE.largeHeader>
</ThemedText.LargeHeader>
<ButtonPrimary onClick={onVote}>
<TYPE.mediumHeader color="white">
<ThemedText.MediumHeader color="white">
{voteOption === VoteOption.Against ? (
<Trans>Vote against proposal {proposalId}</Trans>
) : voteOption === VoteOption.For ? (
......@@ -108,7 +108,7 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, voteOption }:
) : (
<Trans>Vote to abstain on proposal {proposalId}</Trans>
)}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
</ButtonPrimary>
</AutoColumn>
</ContentWrapper>
......@@ -124,13 +124,13 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, voteOption }:
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Submitting Vote</Trans>
</TYPE.largeHeader>
</ThemedText.LargeHeader>
</AutoColumn>
<TYPE.subHeader>
<ThemedText.SubHeader>
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</AutoColumn>
</ConfirmOrLoadingWrapper>
)}
......@@ -145,18 +145,18 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, voteOption }:
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
</ThemedText.LargeHeader>
</AutoColumn>
{chainId && (
<ExternalLink
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
style={{ marginLeft: '4px' }}
>
<TYPE.subHeader>
<ThemedText.SubHeader>
<Trans>View transaction on Explorer</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</ExternalLink>
)}
</AutoColumn>
......
......@@ -5,10 +5,10 @@ export const OVERLAY_READY = 'OVERLAY_READY'
type FormaticSupportedChains = 1 | 3 | 4 | 42
const CHAIN_ID_NETWORK_ARGUMENT: { readonly [chainId in FormaticSupportedChains]: string | undefined } = {
[1]: undefined,
[3]: 'ropsten',
[4]: 'rinkeby',
[42]: 'kovan',
1: undefined,
3: 'ropsten',
4: 'rinkeby',
42: 'kovan',
}
export class FortmaticConnector extends FortmaticConnectorCore {
......
......@@ -19,5 +19,5 @@ export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13
// Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time
export const AVERAGE_BLOCK_TIME_IN_SECS: { [chainId: number]: number } = {
[1]: DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS,
1: DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS,
}
......@@ -13,6 +13,9 @@ import {
FRAX,
FXS,
renBTC,
rETH2,
sETH2,
SWISE,
TRIBE,
USDC,
USDC_ARBITRUM,
......@@ -53,6 +56,8 @@ export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = {
[SupportedChainId.MAINNET]: {
'0xF16E4d813f4DcfDe4c5b44f305c908742De84eF0': [ETH2X_FLI],
[rETH2.address]: [sETH2],
[SWISE.address]: [sETH2],
[FEI.address]: [TRIBE],
[TRIBE.address]: [FEI],
[FRAX.address]: [FXS],
......
......@@ -136,6 +136,27 @@ export const ETH2X_FLI = new Token(
'ETH2x-FLI',
'ETH 2x Flexible Leverage Index'
)
export const sETH2 = new Token(
SupportedChainId.MAINNET,
'0xFe2e637202056d30016725477c5da089Ab0A043A',
18,
'sETH2',
'StakeWise Staked ETH2'
)
export const rETH2 = new Token(
SupportedChainId.MAINNET,
'0x20BC832ca081b91433ff6c17f85701B6e92486c5',
18,
'rETH2',
'StakeWise Reward ETH2'
)
export const SWISE = new Token(
SupportedChainId.MAINNET,
'0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2',
18,
'SWISE',
'StakeWise'
)
export const UNI: { [chainId: number]: Token } = {
[SupportedChainId.MAINNET]: new Token(SupportedChainId.MAINNET, UNI_ADDRESS[1], 18, 'UNI', 'Uniswap'),
[SupportedChainId.RINKEBY]: new Token(SupportedChainId.RINKEBY, UNI_ADDRESS[4], 18, 'UNI', 'Uniswap'),
......
import { arrayify } from '@ethersproject/bytes'
import { parseBytes32String } from '@ethersproject/strings'
import { Currency, Token } from '@uniswap/sdk-core'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import { useMemo } from 'react'
import { createTokenFilterFunction } from '../components/SearchModal/filtering'
import { ExtendedEther, WETH9_EXTENDED } from '../constants/tokens'
import { useAllLists, useCombinedActiveList, useInactiveListUrls } from '../state/lists/hooks'
import { WrappedTokenInfo } from '../state/lists/wrappedTokenInfo'
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
import { useUserAddedTokens } from '../state/user/hooks'
import { isAddress } from '../utils'
import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks'
import { useBytes32TokenContract, useTokenContract } from './useContract'
import { useActiveWeb3React } from './web3'
// reduce token map into standard address <-> Token mapping, optionally include user added tokens
function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } {
const { chainId } = useActiveWeb3React()
const userAddedTokens = useUserAddedTokens()
return useMemo(() => {
if (!chainId) return {}
// reduce to just tokens
const mapWithoutUrls = Object.keys(tokenMap[chainId] ?? {}).reduce<{ [address: string]: Token }>(
(newMap, address) => {
newMap[address] = tokenMap[chainId][address].token
return newMap
},
{}
)
if (includeUserAdded) {
return (
userAddedTokens
// reduce into all ALL_TOKENS filtered by the current chain
.reduce<{ [address: string]: Token }>(
(tokenMap, token) => {
tokenMap[token.address] = token
return tokenMap
},
// must make a copy because reduce modifies the map, and we do not
// want to make a copy in every iteration
{ ...mapWithoutUrls }
)
)
}
return mapWithoutUrls
}, [chainId, userAddedTokens, tokenMap, includeUserAdded])
}
export function useAllTokens(): { [address: string]: Token } {
const allTokens = useCombinedActiveList()
return useTokensFromMap(allTokens, true)
}
type BridgeInfo = Record<
SupportedChainId,
{
tokenAddress: string
originBridgeAddress: string
destBridgeAddress: string
}
>
export function useUnsupportedTokens(): { [address: string]: Token } {
const { chainId } = useActiveWeb3React()
const listsByUrl = useAllLists()
const unsupportedTokensMap = useUnsupportedTokenList()
const unsupportedTokens = useTokensFromMap(unsupportedTokensMap, false)
// checks the default L2 lists to see if `bridgeInfo` has an L1 address value that is unsupported
const l2InferredBlockedTokens: typeof unsupportedTokens = useMemo(() => {
if (!chainId || !L2_CHAIN_IDS.includes(chainId)) {
return {}
}
if (!listsByUrl) {
return {}
}
const listUrl = CHAIN_INFO[chainId as SupportedL2ChainId].defaultListUrl
const { current: list } = listsByUrl[listUrl]
if (!list) {
return {}
}
const unsupportedSet = new Set(Object.keys(unsupportedTokens))
return list.tokens.reduce((acc, tokenInfo) => {
const bridgeInfo = tokenInfo.extensions?.bridgeInfo as unknown as BridgeInfo
if (
bridgeInfo &&
bridgeInfo[SupportedChainId.MAINNET] &&
bridgeInfo[SupportedChainId.MAINNET].tokenAddress &&
unsupportedSet.has(bridgeInfo[SupportedChainId.MAINNET].tokenAddress)
) {
const address = bridgeInfo[SupportedChainId.MAINNET].tokenAddress
// don't rely on decimals--it's possible that a token could be bridged w/ different decimals on the L2
return { ...acc, [address]: new Token(SupportedChainId.MAINNET, address, tokenInfo.decimals) }
}
return acc
}, {})
}, [chainId, listsByUrl, unsupportedTokens])
return { ...unsupportedTokens, ...l2InferredBlockedTokens }
}
export function useSearchInactiveTokenLists(search: string | undefined, minResults = 10): WrappedTokenInfo[] {
const lists = useAllLists()
const inactiveUrls = useInactiveListUrls()
const { chainId } = useActiveWeb3React()
const activeTokens = useAllTokens()
return useMemo(() => {
if (!search || search.trim().length === 0) return []
const tokenFilter = createTokenFilterFunction(search)
const result: WrappedTokenInfo[] = []
const addressSet: { [address: string]: true } = {}
for (const url of inactiveUrls) {
const list = lists[url].current
if (!list) continue
for (const tokenInfo of list.tokens) {
if (tokenInfo.chainId === chainId && tokenFilter(tokenInfo)) {
const wrapped: WrappedTokenInfo = new WrappedTokenInfo(tokenInfo, list)
if (!(wrapped.address in activeTokens) && !addressSet[wrapped.address]) {
addressSet[wrapped.address] = true
result.push(wrapped)
if (result.length >= minResults) return result
}
}
}
}
return result
}, [activeTokens, chainId, inactiveUrls, lists, minResults, search])
}
export function useIsTokenActive(token: Token | undefined | null): boolean {
const activeTokens = useAllTokens()
if (!activeTokens || !token) {
return false
}
return !!activeTokens[token.address]
}
// Check if currency is included in custom list from user storage
export function useIsUserAddedToken(currency: Currency | undefined | null): boolean {
const userAddedTokens = useUserAddedTokens()
if (!currency) {
return false
}
return !!userAddedTokens.find((token) => currency.equals(token))
}
// parse a name or symbol from a token response
const BYTES32_REGEX = /^0x[a-fA-F0-9]{64}$/
function parseStringOrBytes32(str: string | undefined, bytes32: string | undefined, defaultValue: string): string {
return str && str.length > 0
? str
: // need to check for proper bytes string and valid terminator
bytes32 && BYTES32_REGEX.test(bytes32) && arrayify(bytes32)[31] === 0
? parseBytes32String(bytes32)
: defaultValue
}
// undefined if invalid or does not exist
// null if loading or null was passed
// otherwise returns the token
export function useToken(tokenAddress?: string | null): Token | undefined | null {
const { chainId } = useActiveWeb3React()
const tokens = useAllTokens()
const address = isAddress(tokenAddress)
const tokenContract = useTokenContract(address ? address : undefined, false)
const tokenContractBytes32 = useBytes32TokenContract(address ? address : undefined, false)
const token: Token | undefined = address ? tokens[address] : undefined
const tokenName = useSingleCallResult(token ? undefined : tokenContract, 'name', undefined, NEVER_RELOAD)
const tokenNameBytes32 = useSingleCallResult(
token ? undefined : tokenContractBytes32,
'name',
undefined,
NEVER_RELOAD
)
const symbol = useSingleCallResult(token ? undefined : tokenContract, 'symbol', undefined, NEVER_RELOAD)
const symbolBytes32 = useSingleCallResult(token ? undefined : tokenContractBytes32, 'symbol', undefined, NEVER_RELOAD)
const decimals = useSingleCallResult(token ? undefined : tokenContract, 'decimals', undefined, NEVER_RELOAD)
return useMemo(() => {
if (token) return token
if (tokenAddress === null) return null
if (!chainId || !address) return undefined
if (decimals.loading || symbol.loading || tokenName.loading) return null
if (decimals.result) {
return new Token(
chainId,
address,
decimals.result[0],
parseStringOrBytes32(symbol.result?.[0], symbolBytes32.result?.[0], 'UNKNOWN'),
parseStringOrBytes32(tokenName.result?.[0], tokenNameBytes32.result?.[0], 'Unknown Token')
)
}
return undefined
}, [
address,
chainId,
decimals.loading,
decimals.result,
symbol.loading,
symbol.result,
symbolBytes32.result,
token,
tokenAddress,
tokenName.loading,
tokenName.result,
tokenNameBytes32.result,
])
}
export function useCurrency(currencyId: string | null | undefined): Currency | null | undefined {
const { chainId } = useActiveWeb3React()
const isETH = currencyId?.toUpperCase() === 'ETH'
const token = useToken(isETH ? undefined : currencyId)
const extendedEther = useMemo(
() =>
chainId
? ExtendedEther.onChain(chainId)
: // display mainnet when not connected
ExtendedEther.onChain(SupportedChainId.MAINNET),
[chainId]
)
const weth = chainId ? WETH9_EXTENDED[chainId] : undefined
if (currencyId === null || currencyId === undefined) return currencyId
if (weth?.address?.toUpperCase() === currencyId?.toUpperCase()) return weth
return isETH ? extendedEther : token
}
import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales'
import { useMemo } from 'react'
import store from 'state'
import { useUserLocale } from 'state/user/hooks'
import useParsedQueryString from './useParsedQueryString'
import { parsedQueryString } from './useParsedQueryString'
/**
* Given a locale string (e.g. from user agent), return the best match for corresponding SupportedLocale
* @param maybeSupportedLocale the fuzzy locale identifier
*/
function parseLocale(maybeSupportedLocale: unknown): SupportedLocale | undefined {
if (typeof maybeSupportedLocale !== 'string') return undefined
const lowerMaybeSupportedLocale = maybeSupportedLocale.toLowerCase()
return SUPPORTED_LOCALES.find(
(locale) => locale.toLowerCase() === lowerMaybeSupportedLocale || locale.split('-')[0] === lowerMaybeSupportedLocale
)
}
/**
* Returns the supported locale read from the user agent (navigator)
*/
export function navigatorLocale(): SupportedLocale | undefined {
if (!navigator.language) return undefined
const [language, region] = navigator.language.split('-')
if (region) {
return parseLocale(`${language}-${region.toUpperCase()}`) ?? parseLocale(language)
}
return parseLocale(language)
}
function storeLocale(): SupportedLocale | undefined {
return store.getState().user.userLocale ?? undefined
}
export const initialLocale =
parseLocale(parsedQueryString().lng) ?? storeLocale() ?? navigatorLocale() ?? DEFAULT_LOCALE
function useUrlLocale() {
const parsed = useParsedQueryString()
return parseLocale(parsed.lng)
}
/**
* Returns the currently active locale, from a combination of user agent, query string, and user settings stored in redux
* Stores the query string locale in redux (if set) to persist across sessions
*/
export function useActiveLocale(): SupportedLocale {
const urlLocale = useUrlLocale()
const userLocale = useUserLocale()
return useMemo(() => urlLocale ?? userLocale ?? navigatorLocale() ?? DEFAULT_LOCALE, [urlLocale, userLocale])
}
import { Currency, Token } from '@uniswap/sdk-core'
import { useActiveWeb3React } from 'hooks/web3'
import { useCallback, useState } from 'react'
import { getTokenLogoURL } from './../components/CurrencyLogo/index'
export default function useAddTokenToMetamask(currencyToAdd: Currency | undefined): {
addToken: () => void
success: boolean | undefined
} {
const { library } = useActiveWeb3React()
const token: Token | undefined = currencyToAdd?.wrapped
const [success, setSuccess] = useState<boolean | undefined>()
const addToken = useCallback(() => {
if (library && library.provider.isMetaMask && library.provider.request && token) {
library.provider
.request({
method: 'wallet_watchAsset',
params: {
//@ts-ignore // need this for incorrect ethers provider type
type: 'ERC20',
options: {
address: token.address,
symbol: token.symbol,
decimals: token.decimals,
image: getTokenLogoURL(token.address),
},
},
})
.then((success) => {
setSuccess(success)
})
.catch(() => setSuccess(false))
} else {
setSuccess(false)
}
}, [library, token])
return { addToken, success }
}
import { Currency, Token } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants/routing'
export function useAllCurrencyCombinations(currencyA?: Currency, currencyB?: Currency): [Token, Token][] {
const chainId = currencyA?.chainId
const [tokenA, tokenB] = chainId ? [currencyA?.wrapped, currencyB?.wrapped] : [undefined, undefined]
const bases: Token[] = useMemo(() => {
if (!chainId || chainId !== tokenB?.chainId) return []
const common = BASES_TO_CHECK_TRADES_AGAINST[chainId] ?? []
const additionalA = tokenA ? ADDITIONAL_BASES[chainId]?.[tokenA.address] ?? [] : []
const additionalB = tokenB ? ADDITIONAL_BASES[chainId]?.[tokenB.address] ?? [] : []
return [...common, ...additionalA, ...additionalB]
}, [chainId, tokenA, tokenB])
const basePairs: [Token, Token][] = useMemo(
() =>
bases
.flatMap((base): [Token, Token][] => bases.map((otherBase) => [base, otherBase]))
// though redundant with the first filter below, that expression runs more often, so this is probably worthwhile
.filter(([t0, t1]) => !t0.equals(t1)),
[bases]
)
return useMemo(
() =>
tokenA && tokenB
? [
// the direct pair
[tokenA, tokenB] as [Token, Token],
// token A against all bases
...bases.map((base): [Token, Token] => [tokenA, base]),
// token B against all bases
...bases.map((base): [Token, Token] => [tokenB, base]),
// each base against all bases
...basePairs,
]
// filter out invalid pairs comprised of the same asset (e.g. WETH<>WETH)
.filter(([t0, t1]) => !t0.equals(t1))
// filter out duplicate pairs
.filter(([t0, t1], i, otherPairs) => {
// find the first index in the array at which there are the same 2 tokens as the current
const firstIndexInOtherPairs = otherPairs.findIndex(([t0Other, t1Other]) => {
return (t0.equals(t0Other) && t1.equals(t1Other)) || (t0.equals(t1Other) && t1.equals(t0Other))
})
// only accept the first occurrence of the same 2 tokens
return firstIndexInOtherPairs === i
})
// optionally filter out some pairs for tokens with custom bases defined
.filter(([tokenA, tokenB]) => {
if (!chainId) return true
const customBases = CUSTOM_BASES[chainId]
const customBasesA: Token[] | undefined = customBases?.[tokenA.address]
const customBasesB: Token[] | undefined = customBases?.[tokenB.address]
if (!customBasesA && !customBasesB) return true
if (customBasesA && !customBasesA.find((base) => tokenB.equals(base))) return false
if (customBasesB && !customBasesB.find((base) => tokenA.equals(base))) return false
return true
})
: [],
[tokenA, tokenB, bases, basePairs, chainId]
)
}
import { Currency } from '@uniswap/sdk-core'
import { Pool, Route } from '@uniswap/v3-sdk'
import { useMemo } from 'react'
import { useV3SwapPools } from './useV3SwapPools'
import { useActiveWeb3React } from './web3'
/**
* Returns true if poolA is equivalent to poolB
* @param poolA one of the two pools
* @param poolB the other pool
*/
function poolEquals(poolA: Pool, poolB: Pool): boolean {
return (
poolA === poolB ||
(poolA.token0.equals(poolB.token0) && poolA.token1.equals(poolB.token1) && poolA.fee === poolB.fee)
)
}
function computeAllRoutes(
currencyIn: Currency,
currencyOut: Currency,
pools: Pool[],
chainId: number,
currentPath: Pool[] = [],
allPaths: Route<Currency, Currency>[] = [],
startCurrencyIn: Currency = currencyIn,
maxHops = 2
): Route<Currency, Currency>[] {
const tokenIn = currencyIn?.wrapped
const tokenOut = currencyOut?.wrapped
if (!tokenIn || !tokenOut) throw new Error('Missing tokenIn/tokenOut')
for (const pool of pools) {
if (!pool.involvesToken(tokenIn) || currentPath.find((pathPool) => poolEquals(pool, pathPool))) continue
const outputToken = pool.token0.equals(tokenIn) ? pool.token1 : pool.token0
if (outputToken.equals(tokenOut)) {
allPaths.push(new Route([...currentPath, pool], startCurrencyIn, currencyOut))
} else if (maxHops > 1) {
computeAllRoutes(
outputToken,
currencyOut,
pools,
chainId,
[...currentPath, pool],
allPaths,
startCurrencyIn,
maxHops - 1
)
}
}
return allPaths
}
/**
* Returns all the routes from an input currency to an output currency
* @param currencyIn the input currency
* @param currencyOut the output currency
*/
export function useAllV3Routes(
currencyIn?: Currency,
currencyOut?: Currency
): { loading: boolean; routes: Route<Currency, Currency>[] } {
const { chainId } = useActiveWeb3React()
const { pools, loading: poolsLoading } = useV3SwapPools(currencyIn, currencyOut)
return useMemo(() => {
if (poolsLoading || !chainId || !pools || !currencyIn || !currencyOut) return { loading: true, routes: [] }
const routes = computeAllRoutes(currencyIn, currencyOut, pools, chainId, [], [], currencyIn, 2)
return { loading: false, routes }
}, [chainId, currencyIn, currencyOut, pools, poolsLoading])
}
import { useEffect } from 'react'
import { useAppDispatch } from 'state/hooks'
import { updateUserExpertMode } from '../state/user/actions'
import useParsedQueryString from './useParsedQueryString'
export default function ApeModeQueryParamReader(): null {
useApeModeQueryParamReader()
return null
}
function useApeModeQueryParamReader() {
const dispatch = useAppDispatch()
const { ape } = useParsedQueryString()
useEffect(() => {
if (typeof ape !== 'string') return
if (ape === '' || ape.toLowerCase() === 'true') {
dispatch(updateUserExpertMode({ userExpertMode: true }))
}
})
}
import ArgentWalletContractABI from '../abis/argent-wallet-contract.json'
import { ArgentWalletContract } from '../abis/types'
import { useContract } from './useContract'
import useIsArgentWallet from './useIsArgentWallet'
import { useActiveWeb3React } from './web3'
export function useArgentWalletContract(): ArgentWalletContract | null {
const { account } = useActiveWeb3React()
const isArgentWallet = useIsArgentWallet()
return useContract(
isArgentWallet ? account ?? undefined : undefined,
ArgentWalletContractABI,
true
) as ArgentWalletContract
}
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { Pair, Trade } from '@uniswap/v2-sdk'
import { useMemo } from 'react'
import { isTradeBetter } from 'utils/isTradeBetter'
import { BETTER_TRADE_LESS_HOPS_THRESHOLD } from '../constants/misc'
import { useAllCurrencyCombinations } from './useAllCurrencyCombinations'
import { PairState, useV2Pairs } from './useV2Pairs'
function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): Pair[] {
const allCurrencyCombinations = useAllCurrencyCombinations(currencyA, currencyB)
const allPairs = useV2Pairs(allCurrencyCombinations)
return useMemo(
() =>
Object.values(
allPairs
// filter out invalid pairs
.filter((result): result is [PairState.EXISTS, Pair] => Boolean(result[0] === PairState.EXISTS && result[1]))
.map(([, pair]) => pair)
),
[allPairs]
)
}
const MAX_HOPS = 3
/**
* Returns the best v2 trade for a desired swap
* @param tradeType whether the swap is an exact in/out
* @param amountSpecified the exact amount to swap in/out
* @param otherCurrency the desired output/payment currency
*/
export function useBestV2Trade(
tradeType: TradeType.EXACT_INPUT | TradeType.EXACT_OUTPUT,
amountSpecified?: CurrencyAmount<Currency>,
otherCurrency?: Currency,
{ maxHops = MAX_HOPS } = {}
): Trade<Currency, Currency, TradeType.EXACT_INPUT | TradeType.EXACT_OUTPUT> | null {
const [currencyIn, currencyOut] = useMemo(
() =>
tradeType === TradeType.EXACT_INPUT
? [amountSpecified?.currency, otherCurrency]
: [otherCurrency, amountSpecified?.currency],
[tradeType, amountSpecified, otherCurrency]
)
const allowedPairs = useAllCommonPairs(currencyIn, currencyOut)
return useMemo(() => {
if (amountSpecified && currencyIn && currencyOut && allowedPairs.length > 0) {
if (maxHops === 1) {
const options = { maxHops: 1, maxNumResults: 1 }
if (tradeType === TradeType.EXACT_INPUT) {
const amountIn = amountSpecified
return Trade.bestTradeExactIn(allowedPairs, amountIn, currencyOut, options)[0] ?? null
} else {
const amountOut = amountSpecified
return Trade.bestTradeExactOut(allowedPairs, currencyIn, amountOut, options)[0] ?? null
}
}
// search through trades with varying hops, find best trade out of them
let bestTradeSoFar: Trade<Currency, Currency, TradeType.EXACT_INPUT | TradeType.EXACT_OUTPUT> | null = null
for (let i = 1; i <= maxHops; i++) {
const options = { maxHops: i, maxNumResults: 1 }
let currentTrade: Trade<Currency, Currency, TradeType.EXACT_INPUT | TradeType.EXACT_OUTPUT> | null
if (tradeType === TradeType.EXACT_INPUT) {
const amountIn = amountSpecified
currentTrade = Trade.bestTradeExactIn(allowedPairs, amountIn, currencyOut, options)[0] ?? null
} else {
const amountOut = amountSpecified
currentTrade = Trade.bestTradeExactOut(allowedPairs, currencyIn, amountOut, options)[0] ?? null
}
// if current trade is best yet, save it
if (isTradeBetter(bestTradeSoFar, currentTrade, BETTER_TRADE_LESS_HOPS_THRESHOLD)) {
bestTradeSoFar = currentTrade
}
}
return bestTradeSoFar
}
return null
}, [tradeType, amountSpecified, currencyIn, currencyOut, allowedPairs, maxHops])
}
import { Token } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains'
import Vibrant from 'node-vibrant/lib/bundle'
import { shade } from 'polished'
import { useLayoutEffect, useState } from 'react'
import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
import uriToHttp from 'utils/uriToHttp'
import { hex } from 'wcag-contrast'
function URIForEthToken(address: string) {
return `https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/${address}/logo.png`
}
async function getColorFromToken(token: Token): Promise<string | null> {
if (!(token instanceof WrappedTokenInfo)) {
return null
}
const wrappedToken = token as WrappedTokenInfo
const { address } = wrappedToken
let { logoURI } = wrappedToken
if (!logoURI) {
if (token.chainId !== SupportedChainId.MAINNET) {
return null
} else {
logoURI = URIForEthToken(address)
}
}
try {
return await getColorFromUriPath(logoURI)
} catch (e) {
if (logoURI === URIForEthToken(address)) {
return null
}
try {
logoURI = URIForEthToken(address)
return await getColorFromUriPath(logoURI)
} catch (e) {}
}
return null
}
async function getColorFromUriPath(uri: string): Promise<string | null> {
const formattedPath = uriToHttp(uri)[0]
const palette = await Vibrant.from(formattedPath).getPalette()
if (!palette?.Vibrant) {
return null
}
let detectedHex = palette.Vibrant.hex
let AAscore = hex(detectedHex, '#FFF')
while (AAscore < 3) {
detectedHex = shade(0.005, detectedHex)
AAscore = hex(detectedHex, '#FFF')
}
return detectedHex
}
export function useColor(token?: Token) {
const [color, setColor] = useState('#2172E5')
useLayoutEffect(() => {
let stale = false
if (token) {
getColorFromToken(token).then((tokenColor) => {
if (!stale && tokenColor !== null) {
setColor(tokenColor)
}
})
}
return () => {
stale = true
setColor('#2172E5')
}
}, [token])
return color
}
export function useListColor(listImageUri?: string) {
const [color, setColor] = useState('#2172E5')
useLayoutEffect(() => {
let stale = false
if (listImageUri) {
getColorFromUriPath(listImageUri).then((color) => {
if (!stale && color !== null) {
setColor(color)
}
})
}
return () => {
stale = true
setColor('#2172E5')
}
}, [listImageUri])
return color
}
import { Contract } from '@ethersproject/contracts'
import { abi as GOVERNANCE_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
import { abi as UNI_ABI } from '@uniswap/governance/build/Uni.json'
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
import { abi as MERKLE_DISTRIBUTOR_ABI } from '@uniswap/merkle-distributor/build/MerkleDistributor.json'
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { abi as IUniswapV2Router02ABI } from '@uniswap/v2-periphery/build/IUniswapV2Router02.json'
import { abi as QuoterABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json'
import { abi as MulticallABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import { abi as V2MigratorABI } from '@uniswap/v3-periphery/artifacts/contracts/V3Migrator.sol/V3Migrator.json'
import ARGENT_WALLET_DETECTOR_ABI from 'abis/argent-wallet-detector.json'
import EIP_2612 from 'abis/eip_2612.json'
import ENS_PUBLIC_RESOLVER_ABI from 'abis/ens-public-resolver.json'
import ENS_ABI from 'abis/ens-registrar.json'
import ERC20_ABI from 'abis/erc20.json'
import ERC20_BYTES32_ABI from 'abis/erc20_bytes32.json'
import ERC721_ABI from 'abis/erc721.json'
import ERC1155_ABI from 'abis/erc1155.json'
import GOVERNOR_BRAVO_ABI from 'abis/governor-bravo.json'
import WETH_ABI from 'abis/weth.json'
import {
ARGENT_WALLET_DETECTOR_ADDRESS,
ENS_REGISTRAR_ADDRESSES,
GOVERNANCE_ALPHA_V0_ADDRESSES,
GOVERNANCE_ALPHA_V1_ADDRESSES,
GOVERNANCE_BRAVO_ADDRESSES,
MERKLE_DISTRIBUTOR_ADDRESS,
MULTICALL_ADDRESS,
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
QUOTER_ADDRESSES,
V2_ROUTER_ADDRESS,
V3_MIGRATOR_ADDRESSES,
} from 'constants/addresses'
import { useMemo } from 'react'
import { NonfungiblePositionManager, Quoter, UniswapInterfaceMulticall } from 'types/v3'
import { V3Migrator } from 'types/v3/V3Migrator'
import { getContract } from 'utils'
import { ArgentWalletDetector, EnsPublicResolver, EnsRegistrar, Erc20, Erc721, Erc1155, Weth } from '../abis/types'
import { UNI, WETH9_EXTENDED } from '../constants/tokens'
import { useActiveWeb3React } from './web3'
// returns null on errors
export function useContract<T extends Contract = Contract>(
addressOrAddressMap: string | { [chainId: number]: string } | undefined,
ABI: any,
withSignerIfPossible = true
): T | null {
const { library, account, chainId } = useActiveWeb3React()
return useMemo(() => {
if (!addressOrAddressMap || !ABI || !library || !chainId) return null
let address: string | undefined
if (typeof addressOrAddressMap === 'string') address = addressOrAddressMap
else address = addressOrAddressMap[chainId]
if (!address) return null
try {
return getContract(address, ABI, library, withSignerIfPossible && account ? account : undefined)
} catch (error) {
console.error('Failed to get contract', error)
return null
}
}, [addressOrAddressMap, ABI, library, chainId, withSignerIfPossible, account]) as T
}
export function useV2MigratorContract() {
return useContract<V3Migrator>(V3_MIGRATOR_ADDRESSES, V2MigratorABI, true)
}
export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean) {
return useContract<Erc20>(tokenAddress, ERC20_ABI, withSignerIfPossible)
}
export function useWETHContract(withSignerIfPossible?: boolean) {
const { chainId } = useActiveWeb3React()
return useContract<Weth>(chainId ? WETH9_EXTENDED[chainId]?.address : undefined, WETH_ABI, withSignerIfPossible)
}
export function useERC721Contract(nftAddress?: string) {
return useContract<Erc721>(nftAddress, ERC721_ABI, false)
}
export function useERC1155Contract(nftAddress?: string) {
return useContract<Erc1155>(nftAddress, ERC1155_ABI, false)
}
export function useArgentWalletDetectorContract() {
return useContract<ArgentWalletDetector>(ARGENT_WALLET_DETECTOR_ADDRESS, ARGENT_WALLET_DETECTOR_ABI, false)
}
export function useENSRegistrarContract(withSignerIfPossible?: boolean) {
return useContract<EnsRegistrar>(ENS_REGISTRAR_ADDRESSES, ENS_ABI, withSignerIfPossible)
}
export function useENSResolverContract(address: string | undefined, withSignerIfPossible?: boolean) {
return useContract<EnsPublicResolver>(address, ENS_PUBLIC_RESOLVER_ABI, withSignerIfPossible)
}
export function useBytes32TokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null {
return useContract(tokenAddress, ERC20_BYTES32_ABI, withSignerIfPossible)
}
export function useEIP2612Contract(tokenAddress?: string): Contract | null {
return useContract(tokenAddress, EIP_2612, false)
}
export function usePairContract(pairAddress?: string, withSignerIfPossible?: boolean): Contract | null {
return useContract(pairAddress, IUniswapV2PairABI, withSignerIfPossible)
}
export function useV2RouterContract(): Contract | null {
return useContract(V2_ROUTER_ADDRESS, IUniswapV2Router02ABI, true)
}
export function useMulticall2Contract() {
return useContract<UniswapInterfaceMulticall>(MULTICALL_ADDRESS, MulticallABI, false) as UniswapInterfaceMulticall
}
export function useMerkleDistributorContract() {
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
}
export function useGovernanceV0Contract(): Contract | null {
return useContract(GOVERNANCE_ALPHA_V0_ADDRESSES, GOVERNANCE_ABI, false)
}
export function useGovernanceV1Contract(): Contract | null {
return useContract(GOVERNANCE_ALPHA_V1_ADDRESSES, GOVERNANCE_ABI, false)
}
export function useGovernanceBravoContract(): Contract | null {
return useContract(GOVERNANCE_BRAVO_ADDRESSES, GOVERNOR_BRAVO_ABI, true)
}
export const useLatestGovernanceContract = useGovernanceBravoContract
export function useUniContract() {
const { chainId } = useActiveWeb3React()
return useContract(chainId ? UNI[chainId]?.address : undefined, UNI_ABI, true)
}
export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
}
export function useV3NFTPositionManagerContract(withSignerIfPossible?: boolean): NonfungiblePositionManager | null {
return useContract<NonfungiblePositionManager>(
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
NFTPositionManagerABI,
withSignerIfPossible
)
}
export function useV3Quoter() {
return useContract<Quoter>(QUOTER_ADDRESSES, QuoterABI)
}
import copy from 'copy-to-clipboard'
import { useCallback, useEffect, useState } from 'react'
export default function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => void] {
const [isCopied, setIsCopied] = useState(false)
const staticCopy = useCallback((text) => {
const didCopy = copy(text)
setIsCopied(didCopy)
}, [])
useEffect(() => {
if (isCopied) {
const hide = setTimeout(() => {
setIsCopied(false)
}, timeout)
return () => {
clearTimeout(hide)
}
}
return undefined
}, [isCopied, setIsCopied, timeout])
return [isCopied, staticCopy]
}
import { BigNumber } from '@ethersproject/bignumber'
import { useSingleCallResult } from '../state/multicall/hooks'
import { useMulticall2Contract } from './useContract'
// gets the current timestamp from the blockchain
export default function useCurrentBlockTimestamp(): BigNumber | undefined {
const multicall = useMulticall2Contract()
return useSingleCallResult(multicall, 'getCurrentBlockTimestamp')?.result?.[0]
}
import { useEffect, useState } from 'react'
// modified from https://usehooks.com/useDebounce/
export default function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect(() => {
// Update debounced value after delay
const handler = setTimeout(() => {
setDebouncedValue(value)
}, delay)
// Cancel the timeout if value changes (also on delay change or unmount)
// This is how we prevent debounced value from updating if value is changed ...
// .. within the delay period. Timeout gets cleared and restarted.
return () => {
clearTimeout(handler)
}
}, [value, delay])
return debouncedValue
}
import { useCallback, useEffect, useRef, useState } from 'react'
/**
* Easy way to debounce the handling of a rapidly changing value, e.g. a changing slider input
* @param value value that is rapidly changing
* @param onChange change handler that should receive the debounced updates to the value
* @param debouncedMs how long we should wait for changes to be applied
*/
export default function useDebouncedChangeHandler<T>(
value: T,
onChange: (newValue: T) => void,
debouncedMs = 100
): [T, (value: T) => void] {
const [inner, setInner] = useState<T>(() => value)
const timer = useRef<ReturnType<typeof setTimeout>>()
const onChangeInner = useCallback(
(newValue: T) => {
setInner(newValue)
if (timer.current) {
clearTimeout(timer.current)
}
timer.current = setTimeout(() => {
onChange(newValue)
timer.current = undefined
}, debouncedMs)
},
[debouncedMs, onChange]
)
useEffect(() => {
if (timer.current) {
clearTimeout(timer.current)
timer.current = undefined
}
setInner(value)
}, [value])
return [inner, onChangeInner]
}
import { Pool, Position } from '@uniswap/v3-sdk'
import { usePool } from 'hooks/usePools'
import { PositionDetails } from 'types/position'
import { useCurrency } from './Tokens'
export function useDerivedPositionInfo(positionDetails: PositionDetails | undefined): {
position: Position | undefined
pool: Pool | undefined
} {
const currency0 = useCurrency(positionDetails?.token0)
const currency1 = useCurrency(positionDetails?.token1)
// construct pool data
const [, pool] = usePool(currency0 ?? undefined, currency1 ?? undefined, positionDetails?.fee)
let position = undefined
if (pool && positionDetails) {
position = new Position({
pool,
liquidity: positionDetails.liquidity.toString(),
tickLower: positionDetails.tickLower,
tickUpper: positionDetails.tickUpper,
})
}
return {
position,
pool: pool ?? undefined,
}
}
import { isAddress } from '../utils'
import useENSAddress from './useENSAddress'
import useENSName from './useENSName'
/**
* Given a name or address, does a lookup to resolve to an address and name
* @param nameOrAddress ENS name or address
*/
export default function useENS(nameOrAddress?: string | null): {
loading: boolean
address: string | null
name: string | null
} {
const validated = isAddress(nameOrAddress)
const reverseLookup = useENSName(validated ? validated : undefined)
const lookup = useENSAddress(nameOrAddress)
return {
loading: reverseLookup.loading || lookup.loading,
address: validated ? validated : lookup.address,
name: reverseLookup.ENSName ? reverseLookup.ENSName : !validated && lookup.address ? nameOrAddress || null : null,
}
}
import { namehash } from '@ethersproject/hash'
import { useMemo } from 'react'
import { useSingleCallResult } from '../state/multicall/hooks'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract } from './useContract'
import useDebounce from './useDebounce'
/**
* Does a lookup for an ENS name to find its address.
*/
export default function useENSAddress(ensName?: string | null): { loading: boolean; address: string | null } {
const debouncedName = useDebounce(ensName, 200)
const ensNodeArgument = useMemo(() => {
if (!debouncedName) return [undefined]
try {
return debouncedName ? [namehash(debouncedName)] : [undefined]
} catch (error) {
return [undefined]
}
}, [debouncedName])
const registrarContract = useENSRegistrarContract(false)
const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
const resolverAddressResult = resolverAddress.result?.[0]
const resolverContract = useENSResolverContract(
resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined,
false
)
const addr = useSingleCallResult(resolverContract, 'addr', ensNodeArgument)
const changed = debouncedName !== ensName
return {
address: changed ? null : addr.result?.[0] ?? null,
loading: changed || resolverAddress.loading || addr.loading,
}
}
import { namehash } from '@ethersproject/hash'
import { useEffect, useMemo, useState } from 'react'
import uriToHttp from 'utils/uriToHttp'
import { useSingleCallResult } from '../state/multicall/hooks'
import { isAddress } from '../utils'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract, useERC721Contract, useERC1155Contract } from './useContract'
import useDebounce from './useDebounce'
import useENSName from './useENSName'
import { useActiveWeb3React } from './web3'
/**
* Returns the ENS avatar URI, if available.
* Spec: https://gist.github.com/Arachnid/9db60bd75277969ee1689c8742b75182.
*/
export default function useENSAvatar(
address?: string,
enforceOwnership = true
): { avatar: string | null; loading: boolean } {
const debouncedAddress = useDebounce(address, 200)
const node = useMemo(() => {
if (!debouncedAddress || !isAddress(debouncedAddress)) return undefined
try {
return debouncedAddress ? namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`) : undefined
} catch (error) {
return undefined
}
}, [debouncedAddress])
const addressAvatar = useAvatarFromNode(node)
const nameAvatar = useAvatarFromNode(namehash(useENSName(address).ENSName ?? ''))
let avatar = addressAvatar.avatar || nameAvatar.avatar
const nftAvatar = useAvatarFromNFT(avatar, enforceOwnership)
avatar = nftAvatar.avatar || avatar
const http = avatar && uriToHttp(avatar)[0]
const changed = debouncedAddress !== address
return {
avatar: changed ? null : http ?? null,
loading: changed || addressAvatar.loading || nameAvatar.loading || nftAvatar.loading,
}
}
function useAvatarFromNode(node?: string): { avatar?: string; loading: boolean } {
const nodeArgument = useMemo(() => [node], [node])
const textArgument = useMemo(() => [node, 'avatar'], [node])
const registrarContract = useENSRegistrarContract(false)
const resolverAddress = useSingleCallResult(registrarContract, 'resolver', nodeArgument)
const resolverAddressResult = resolverAddress.result?.[0]
const resolverContract = useENSResolverContract(
resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined,
false
)
const avatar = useSingleCallResult(resolverContract, 'text', textArgument)
return {
avatar: avatar.result?.[0],
loading: resolverAddress.loading || avatar.loading,
}
}
function useAvatarFromNFT(nftUri = '', enforceOwnership: boolean): { avatar?: string; loading: boolean } {
const parts = nftUri.toLowerCase().split(':')
const protocol = parts[0]
// ignore the chain from eip155
// TODO: when we are able, pull only from the specified chain
const [, erc] = parts[1]?.split('/') ?? []
const [contractAddress, id] = parts[2]?.split('/') ?? []
const isERC721 = protocol === 'eip155' && erc === 'erc721'
const isERC1155 = protocol === 'eip155' && erc === 'erc1155'
const erc721 = useERC721Uri(isERC721 ? contractAddress : undefined, id, enforceOwnership)
const erc1155 = useERC1155Uri(isERC1155 ? contractAddress : undefined, id, enforceOwnership)
const uri = erc721.uri || erc1155.uri
const http = uri && uriToHttp(uri)[0]
const [loading, setLoading] = useState(false)
const [avatar, setAvatar] = useState(undefined)
useEffect(() => {
setAvatar(undefined)
if (http) {
setLoading(true)
fetch(http)
.then((res) => res.json())
.then(({ image }) => {
setAvatar(image)
})
.catch((e) => console.warn(e))
.finally(() => {
setLoading(false)
})
}
}, [http])
return { avatar, loading: erc721.loading || erc1155.loading || loading }
}
function useERC721Uri(
contractAddress: string | undefined,
id: string | undefined,
enforceOwnership: boolean
): { uri?: string; loading: boolean } {
const idArgument = useMemo(() => [id], [id])
const { account } = useActiveWeb3React()
const contract = useERC721Contract(contractAddress)
const owner = useSingleCallResult(contract, 'ownerOf', idArgument)
const uri = useSingleCallResult(contract, 'tokenURI', idArgument)
return {
uri: !enforceOwnership || account === owner.result?.[0] ? uri.result?.[0] : undefined,
loading: owner.loading || uri.loading,
}
}
function useERC1155Uri(
contractAddress: string | undefined,
id: string | undefined,
enforceOwnership: boolean
): { uri?: string; loading: boolean } {
const { account } = useActiveWeb3React()
const idArgument = useMemo(() => [id], [id])
const accountArgument = useMemo(() => [account || '', id], [account, id])
const contract = useERC1155Contract(contractAddress)
const balance = useSingleCallResult(contract, 'balanceOf', accountArgument)
const uri = useSingleCallResult(contract, 'uri', idArgument)
return {
uri: !enforceOwnership || balance.result?.[0] > 0 ? uri.result?.[0] : undefined,
loading: balance.loading || uri.loading,
}
}
import { namehash } from '@ethersproject/hash'
import { useMemo } from 'react'
import { useSingleCallResult } from '../state/multicall/hooks'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract } from './useContract'
/**
* Does a lookup for an ENS name to find its contenthash.
*/
export default function useENSContentHash(ensName?: string | null): { loading: boolean; contenthash: string | null } {
const ensNodeArgument = useMemo(() => {
if (!ensName) return [undefined]
try {
return ensName ? [namehash(ensName)] : [undefined]
} catch (error) {
return [undefined]
}
}, [ensName])
const registrarContract = useENSRegistrarContract(false)
const resolverAddressResult = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
const resolverAddress = resolverAddressResult.result?.[0]
const resolverContract = useENSResolverContract(
resolverAddress && isZero(resolverAddress) ? undefined : resolverAddress,
false
)
const contenthash = useSingleCallResult(resolverContract, 'contenthash', ensNodeArgument)
return {
contenthash: contenthash.result?.[0] ?? null,
loading: resolverAddressResult.loading || contenthash.loading,
}
}
import { namehash } from '@ethersproject/hash'
import { useMemo } from 'react'
import { useSingleCallResult } from '../state/multicall/hooks'
import { isAddress } from '../utils'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract } from './useContract'
import useDebounce from './useDebounce'
/**
* Does a reverse lookup for an address to find its ENS name.
* Note this is not the same as looking up an ENS name to find an address.
*/
export default function useENSName(address?: string): { ENSName: string | null; loading: boolean } {
const debouncedAddress = useDebounce(address, 200)
const ensNodeArgument = useMemo(() => {
if (!debouncedAddress || !isAddress(debouncedAddress)) return [undefined]
try {
return debouncedAddress ? [namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)] : [undefined]
} catch (error) {
return [undefined]
}
}, [debouncedAddress])
const registrarContract = useENSRegistrarContract(false)
const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
const resolverAddressResult = resolverAddress.result?.[0]
const resolverContract = useENSResolverContract(
resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined,
false
)
const name = useSingleCallResult(resolverContract, 'name', ensNodeArgument)
const changed = debouncedAddress !== address
return {
ENSName: changed ? null : name.result?.[0] ?? null,
loading: changed || resolverAddress.loading || name.loading,
}
}
......@@ -34,23 +34,23 @@ const PERMITTABLE_TOKENS: {
[checksummedTokenAddress: string]: PermitInfo
}
} = {
[1]: {
1: {
[USDC.address]: { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
[DAI.address]: { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
[UNI[1].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
},
[4]: {
['0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735']: { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
4: {
'0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735': { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
[UNI[4].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
},
[3]: {
3: {
[UNI[3].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
['0x07865c6E87B9F70255377e024ace6630C1Eaa37F']: { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
'0x07865c6E87B9F70255377e024ace6630C1Eaa37F': { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
},
[5]: {
5: {
[UNI[5].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
},
[42]: {
42: {
[UNI[42].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
},
}
......
import { skipToken } from '@reduxjs/toolkit/query/react'
import { Currency, Token } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import ms from 'ms.macro'
import { useMemo } from 'react'
import ReactGA from 'react-ga'
import { useBlockNumber } from 'state/application/hooks'
import { useFeeTierDistributionQuery } from 'state/data/enhanced'
import { FeeTierDistributionQuery } from 'state/data/generated'
import { PoolState, usePool } from './usePools'
// maximum number of blocks past which we consider the data stale
const MAX_DATA_BLOCK_AGE = 20
interface FeeTierDistribution {
isLoading: boolean
isError: boolean
largestUsageFeeTier?: FeeAmount | undefined
// distributions as percentages of overall liquidity
distributions?: Record<FeeAmount, number | undefined>
}
export function useFeeTierDistribution(
currencyA: Currency | undefined,
currencyB: Currency | undefined
): FeeTierDistribution {
const { isFetching, isLoading, isUninitialized, isError, distributions } = usePoolTVL(
currencyA?.wrapped,
currencyB?.wrapped
)
// fetch all pool states to determine pool state
const [poolStateVeryLow] = usePool(currencyA, currencyB, FeeAmount.LOWEST)
const [poolStateLow] = usePool(currencyA, currencyB, FeeAmount.LOW)
const [poolStateMedium] = usePool(currencyA, currencyB, FeeAmount.MEDIUM)
const [poolStateHigh] = usePool(currencyA, currencyB, FeeAmount.HIGH)
return useMemo(() => {
if (isLoading || isFetching || isUninitialized || isError || !distributions) {
return {
isLoading: isLoading || isFetching || !isUninitialized,
isError,
distributions,
}
}
const largestUsageFeeTier = Object.keys(distributions)
.map((d) => Number(d))
.filter((d: FeeAmount) => distributions[d] !== 0 && distributions[d] !== undefined)
.reduce((a: FeeAmount, b: FeeAmount) => ((distributions[a] ?? 0) > (distributions[b] ?? 0) ? a : b), -1)
const percentages =
!isLoading &&
!isError &&
distributions &&
poolStateVeryLow !== PoolState.LOADING &&
poolStateLow !== PoolState.LOADING &&
poolStateMedium !== PoolState.LOADING &&
poolStateHigh !== PoolState.LOADING
? {
[FeeAmount.LOWEST]:
poolStateVeryLow === PoolState.EXISTS ? (distributions[FeeAmount.LOWEST] ?? 0) * 100 : undefined,
[FeeAmount.LOW]: poolStateLow === PoolState.EXISTS ? (distributions[FeeAmount.LOW] ?? 0) * 100 : undefined,
[FeeAmount.MEDIUM]:
poolStateMedium === PoolState.EXISTS ? (distributions[FeeAmount.MEDIUM] ?? 0) * 100 : undefined,
[FeeAmount.HIGH]:
poolStateHigh === PoolState.EXISTS ? (distributions[FeeAmount.HIGH] ?? 0) * 100 : undefined,
}
: undefined
return {
isLoading,
isError,
distributions: percentages,
largestUsageFeeTier: largestUsageFeeTier === -1 ? undefined : largestUsageFeeTier,
}
}, [
isLoading,
isFetching,
isUninitialized,
isError,
distributions,
poolStateVeryLow,
poolStateLow,
poolStateMedium,
poolStateHigh,
])
}
function usePoolTVL(token0: Token | undefined, token1: Token | undefined) {
const latestBlock = useBlockNumber()
const { isLoading, isFetching, isUninitialized, isError, data } = useFeeTierDistributionQuery(
token0 && token1 ? { token0: token0.address.toLowerCase(), token1: token1.address.toLowerCase() } : skipToken,
{
pollingInterval: ms`30s`,
}
)
const { asToken0, asToken1, _meta } = (data as FeeTierDistributionQuery) ?? {}
return useMemo(() => {
if (!latestBlock || !_meta || !asToken0 || !asToken1) {
return {
isLoading,
isFetching,
isUninitialized,
isError,
}
}
if (latestBlock - (_meta?.block?.number ?? 0) > MAX_DATA_BLOCK_AGE) {
ReactGA.exception({
description: `Graph stale (latest block: ${latestBlock})`,
})
return {
isLoading,
isFetching,
isUninitialized,
isError,
}
}
const all = asToken0.concat(asToken1)
// sum tvl for token0 and token1 by fee tier
const tvlByFeeTier = all.reduce<{ [feeAmount: number]: [number | undefined, number | undefined] }>(
(acc, value) => {
acc[value.feeTier][0] = (acc[value.feeTier][0] ?? 0) + Number(value.totalValueLockedToken0)
acc[value.feeTier][1] = (acc[value.feeTier][1] ?? 0) + Number(value.totalValueLockedToken1)
return acc
},
{
[FeeAmount.LOWEST]: [undefined, undefined],
[FeeAmount.LOW]: [undefined, undefined],
[FeeAmount.MEDIUM]: [undefined, undefined],
[FeeAmount.HIGH]: [undefined, undefined],
} as Record<FeeAmount, [number | undefined, number | undefined]>
)
// sum total tvl for token0 and token1
const [sumToken0Tvl, sumToken1Tvl] = Object.values(tvlByFeeTier).reduce(
(acc: [number, number], value) => {
acc[0] += value[0] ?? 0
acc[1] += value[1] ?? 0
return acc
},
[0, 0]
)
// returns undefined if both tvl0 and tvl1 are undefined (pool not created)
const mean = (tvl0: number | undefined, sumTvl0: number, tvl1: number | undefined, sumTvl1: number) =>
tvl0 === undefined && tvl1 === undefined ? undefined : ((tvl0 ?? 0) + (tvl1 ?? 0)) / (sumTvl0 + sumTvl1) || 0
const distributions: Record<FeeAmount, number | undefined> = {
[FeeAmount.LOWEST]: mean(
tvlByFeeTier[FeeAmount.LOWEST][0],
sumToken0Tvl,
tvlByFeeTier[FeeAmount.LOWEST][1],
sumToken1Tvl
),
[FeeAmount.LOW]: mean(tvlByFeeTier[FeeAmount.LOW][0], sumToken0Tvl, tvlByFeeTier[FeeAmount.LOW][1], sumToken1Tvl),
[FeeAmount.MEDIUM]: mean(
tvlByFeeTier[FeeAmount.MEDIUM][0],
sumToken0Tvl,
tvlByFeeTier[FeeAmount.MEDIUM][1],
sumToken1Tvl
),
[FeeAmount.HIGH]: mean(
tvlByFeeTier[FeeAmount.HIGH][0],
sumToken0Tvl,
tvlByFeeTier[FeeAmount.HIGH][1],
sumToken1Tvl
),
}
return {
isLoading,
isFetching,
isUninitialized,
isError,
distributions,
}
}, [_meta, asToken0, asToken1, isLoading, isError, isFetching, isUninitialized, latestBlock])
}
import { nanoid } from '@reduxjs/toolkit'
import { TokenList } from '@uniswap/token-lists'
import { useCallback } from 'react'
import { useAppDispatch } from 'state/hooks'
import { getNetworkLibrary } from '../connectors'
import { fetchTokenList } from '../state/lists/actions'
import getTokenList from '../utils/getTokenList'
import resolveENSContentHash from '../utils/resolveENSContentHash'
import { useActiveWeb3React } from './web3'
export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean) => Promise<TokenList> {
const { chainId, library } = useActiveWeb3React()
const dispatch = useAppDispatch()
const ensResolver = useCallback(
async (ensName: string) => {
if (!library || chainId !== 1) {
const networkLibrary = getNetworkLibrary()
const network = await networkLibrary.getNetwork()
if (networkLibrary && network.chainId === 1) {
return resolveENSContentHash(ensName, networkLibrary)
}
throw new Error('Could not construct mainnet ENS resolver')
}
return resolveENSContentHash(ensName, library)
},
[chainId, library]
)
// note: prevent dispatch if using for list search or unsupported list
return useCallback(
async (listUrl: string, sendDispatch = true) => {
const requestId = nanoid()
sendDispatch && dispatch(fetchTokenList.pending({ requestId, url: listUrl }))
return getTokenList(listUrl, ensResolver)
.then((tokenList) => {
sendDispatch && dispatch(fetchTokenList.fulfilled({ url: listUrl, tokenList, requestId }))
return tokenList
})
.catch((error) => {
console.debug(`Failed to get list at url ${listUrl}`, error)
sendDispatch && dispatch(fetchTokenList.rejected({ url: listUrl, requestId, errorMessage: error.message }))
throw error
})
},
[dispatch, ensResolver]
)
}
import JSBI from 'jsbi'
import { useSingleCallResult } from '../state/multicall/hooks'
import { useContract } from './useContract'
import useENSAddress from './useENSAddress'
const CHAIN_DATA_ABI = [
{
inputs: [],
name: 'latestAnswer',
outputs: [{ internalType: 'int256', name: '', type: 'int256' }],
stateMutability: 'view',
type: 'function',
},
]
/**
* Returns the price of 1 gas in WEI for the currently selected network using the chainlink fast gas price oracle
*/
export default function useGasPrice(): JSBI | undefined {
const { address } = useENSAddress('fast-gas-gwei.data.eth')
const contract = useContract(address ?? undefined, CHAIN_DATA_ABI, false)
const resultStr = useSingleCallResult(contract, 'latestAnswer').result?.[0]?.toString()
return typeof resultStr === 'string' ? JSBI.BigInt(resultStr) : undefined
}
import { useMemo } from 'react'
import contenthashToUri from '../utils/contenthashToUri'
import { parseENSAddress } from '../utils/parseENSAddress'
import uriToHttp from '../utils/uriToHttp'
import useENSContentHash from './useENSContentHash'
export default function useHttpLocations(uri: string | undefined): string[] {
const ens = useMemo(() => (uri ? parseENSAddress(uri) : undefined), [uri])
const resolvedContentHash = useENSContentHash(ens?.ensName)
return useMemo(() => {
if (ens) {
return resolvedContentHash.contenthash ? uriToHttp(contenthashToUri(resolvedContentHash.contenthash)) : []
} else {
return uri ? uriToHttp(uri) : []
}
}, [ens, resolvedContentHash.contenthash, uri])
}
import { useEffect, useRef } from 'react'
export default function useInterval(callback: () => void, delay: null | number, leading = true) {
const savedCallback = useRef<() => void>()
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback
}, [callback])
// Set up the interval.
useEffect(() => {
function tick() {
const current = savedCallback.current
current && current()
}
if (delay !== null) {
if (leading) tick()
const id = setInterval(tick, delay)
return () => clearInterval(id)
}
return undefined
}, [delay, leading])
}
import { useMemo } from 'react'
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
import { useArgentWalletDetectorContract } from './useContract'
import { useActiveWeb3React } from './web3'
export default function useIsArgentWallet(): boolean {
const { account } = useActiveWeb3React()
const argentWalletDetector = useArgentWalletDetectorContract()
const inputs = useMemo(() => [account ?? undefined], [account])
const call = useSingleCallResult(argentWalletDetector, 'isArgentWallet', inputs, NEVER_RELOAD)
return call?.result?.[0] ?? false
}
import { Currency } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { useUnsupportedTokens } from './Tokens'
/**
* Returns true if the input currency or output currency cannot be traded in the interface
* @param currencyIn the input currency to check
* @param currencyOut the output currency to check
*/
export function useIsSwapUnsupported(currencyIn?: Currency | null, currencyOut?: Currency | null): boolean {
const unsupportedTokens = useUnsupportedTokens()
return useMemo(() => {
if (!unsupportedTokens) {
return false
}
const currencyInUnsupported = Boolean(currencyIn?.isToken && unsupportedTokens[currencyIn.address])
const currencyOutUnsupported = Boolean(currencyOut?.isToken && unsupportedTokens[currencyOut.address])
return currencyInUnsupported || currencyOutUnsupported
}, [currencyIn, currencyOut, unsupportedTokens])
}
import { FeeAmount, nearestUsableTick, TICK_SPACINGS, TickMath } from '@uniswap/v3-sdk'
import { useMemo } from 'react'
import { Bound } from 'state/mint/v3/actions'
export default function useIsTickAtLimit(
feeAmount: FeeAmount | undefined,
tickLower: number | undefined,
tickUpper: number | undefined
) {
return useMemo(
() => ({
[Bound.LOWER]:
feeAmount && tickLower
? tickLower === nearestUsableTick(TickMath.MIN_TICK, TICK_SPACINGS[feeAmount as FeeAmount])
: undefined,
[Bound.UPPER]:
feeAmount && tickUpper
? tickUpper === nearestUsableTick(TickMath.MAX_TICK, TICK_SPACINGS[feeAmount as FeeAmount])
: undefined,
}),
[feeAmount, tickLower, tickUpper]
)
}
import { useCallback, useEffect, useState } from 'react'
const VISIBILITY_STATE_SUPPORTED = 'visibilityState' in document
function isWindowVisible() {
return !VISIBILITY_STATE_SUPPORTED || document.visibilityState !== 'hidden'
}
/**
* Returns whether the window is currently visible to the user.
*/
export default function useIsWindowVisible(): boolean {
const [focused, setFocused] = useState<boolean>(isWindowVisible())
const listener = useCallback(() => {
setFocused(isWindowVisible())
}, [setFocused])
useEffect(() => {
if (!VISIBILITY_STATE_SUPPORTED) return undefined
document.addEventListener('visibilitychange', listener)
return () => {
document.removeEventListener('visibilitychange', listener)
}
}, [listener])
return focused
}
import { useEffect, useState } from 'react'
/**
* Returns the last value of type T that passes a filter function
* @param value changing value
* @param filterFn function that determines whether a given value should be considered for the last value
*/
export default function useLast<T>(
value: T | undefined | null,
filterFn?: (value: T | null | undefined) => boolean
): T | null | undefined {
const [last, setLast] = useState<T | null | undefined>(filterFn && filterFn(value) ? value : undefined)
useEffect(() => {
setLast((last) => {
const shouldUse: boolean = filterFn ? filterFn(value) : true
if (shouldUse) return value
return last
})
}, [filterFn, value])
return last
}
import { SupportedLocale } from 'constants/locales'
import { LocationDescriptor } from 'history'
import useParsedQueryString from 'hooks/useParsedQueryString'
import { stringify } from 'qs'
import { useMemo } from 'react'
import ReactGA from 'react-ga'
import { useLocation } from 'react-router-dom'
import { useActiveLocale } from './useActiveLocale'
export function useLocationLinkProps(locale: SupportedLocale | null): {
to?: LocationDescriptor
onClick?: () => void
} {
const location = useLocation()
const qs = useParsedQueryString()
const activeLocale = useActiveLocale()
return useMemo(
() =>
!locale
? {}
: {
to: {
...location,
search: stringify({ ...qs, lng: locale }),
},
onClick: () => {
ReactGA.event({
category: 'Localization',
action: 'Switch Locale',
label: `${activeLocale} -> ${locale}`,
})
},
},
[location, qs, activeLocale, locale]
)
}
import { useState } from 'react'
import useInterval from './useInterval'
const useMachineTimeMs = (updateInterval: number): number => {
const [now, setNow] = useState(Date.now())
useInterval(() => {
setNow(Date.now())
}, updateInterval)
return now
}
export default useMachineTimeMs
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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