Compare commits

...

33 Commits

Author SHA1 Message Date
Moody Salem
809902efec fixes https://github.com/Uniswap/uniswap-interface/issues/1386 2021-05-13 12:17:34 -05:00
Noah Zinsmeister
70be9894fa bump walletlink connector (#1563) 2021-05-13 12:35:17 -04:00
Moody Salem
698ad5bac9 bump v3 sdk 2021-05-13 11:21:07 -05:00
Moody Salem
cd37b7533d put the error reason in the message so we can differentiate between unrecognized errors 2021-05-13 11:16:37 -05:00
Justin Domingue
c0cd6a1c8d handle ape= query parameter (#1555)
* handle expert_mode= and ape= query parameters

* removed console log

* use useParsedQueryString

* only handle setting ape mode
2021-05-13 12:01:58 -04:00
Moody Salem
f6245d1093 retry more frequently, couple more error nits 2021-05-13 10:51:06 -05:00
Moody Salem
83c784f7c0 improve the error coverage 2021-05-13 10:51:06 -05:00
Moody Salem
3d95b1a33b fix access of undefined property 2021-05-13 09:37:04 -05:00
Moody Salem
5c96942922 fix: show better errors 2021-05-13 09:02:48 -05:00
Justin Domingue
d27c83b382 use styled-components/macro to display className in dev builds (#1541) 2021-05-13 09:15:13 -04:00
Moody Salem
b2f88965a9 handle errors better 2021-05-12 22:05:00 -05:00
Moody Salem
95db44e0fc add a little state to the automatic issue body 2021-05-12 18:20:16 -05:00
Moody Salem
7d45ff5ca8 fix 0 decimal tokens error 2021-05-12 17:29:02 -05:00
Moody Salem
8964cf86aa nit with how we convert percent to negative value 2021-05-12 17:13:40 -05:00
Moody Salem
0e9f23ed56 hover text nit 2021-05-12 17:12:16 -05:00
Moody Salem
e08e597655 show list in import token dialog 2021-05-12 17:01:20 -05:00
Moody Salem
744db49803 do not show duplicate token results, and stop searching as soon as possible 2021-05-12 16:54:05 -05:00
Moody Salem
54f59e02fd add page url to the issue template 2021-05-12 16:17:46 -05:00
Moody Salem
7950e5c083 fixes https://github.com/Uniswap/uniswap-interface/issues/1548 2021-05-12 16:16:00 -05:00
Ian Lapham
dd33205bf6 update string in token amount formatting (#1539) 2021-05-12 14:19:01 -04:00
Moody Salem
397a20b9ec fix the issue title 2021-05-12 13:14:02 -05:00
Moody Salem
0aac0b43aa clean up the error boundary 2021-05-12 13:11:10 -05:00
Ian Lapham
702500794d truncate and format large numbers (#1518)
* truncate and format large numbers

* update truncation shorthand

* update logic for detecting small amount
2021-05-12 14:08:05 -04:00
Moody Salem
8bea95fab2 fix the transaction deadline errors 2021-05-12 13:01:31 -05:00
Moody Salem
27094c87f2 clean up price impact formatting 2021-05-12 12:39:21 -05:00
Justin Domingue
bede9171c3 add header background on scroll body overlap (#1531)
* add header background-color on scroll overlap

* slide background in/out on scroll

* remove unused import

Co-authored-by: Justin Domingue <domingue.justin@gmail.com>
2021-05-12 13:19:43 -04:00
Justin Domingue
251d7c0bc2 Fix NFT SVG performance issue in browser (#1509)
* only animate NFT SVG on hover by using a canvas

* handle high dpis

* animation transition between canvas and img

* set start state to not animated

* removed animations that were causing issues on Firefox

* simplify code

* remove debugger statement

* remove useEffect in favor of an event handler

* hide canvas without unmounting to avoid blinking

* fix lint error

* fix flicker on hover by leaving canvas always visible

* add comment about z-index

Co-authored-by: Justin Domingue <domingue.justin@gmail.com>
2021-05-12 13:02:52 -04:00
Moody Salem
285e4f28f5 fix bug in fiat value price impact display 2021-05-12 11:56:18 -05:00
Moody Salem
3aa045303a remove a few unused isToken calls 2021-05-12 11:43:30 -05:00
Noah Zinsmeister
e0a7c3794e bump gas margin to 20% 2021-05-12 12:35:46 -04:00
Noah Zinsmeister
f5fc5da341 fix erroneous addition of tokensOwned{0,1} (#1533)
only pass tokenId to useV3PositionFees
2021-05-12 12:20:20 -04:00
Moody Salem
bea5c0484b fix lint errors, show source list in extra tokens 2021-05-12 09:32:24 -05:00
Moody Salem
27960532ca refactor: use new sdk version (#1472)
* do not construct tokens for wrapped token info

* some cleanup of the wrapped token info

* back to extends, bump sdk core version via v2/v3 sdk updates

* Revert "back to extends, bump sdk core version via v2/v3 sdk updates"

This reverts commit 92cc5073

* update the sdk version

* fix some more uses of instanceof

* finish the refactor

* mess with the currency list performance

* start replacing with the latest v3/v2 sdks

* raw -> quotient

* more cleanup

* finish the refactor

* clean up currency list refactor

* fix list rendering

* perf(token lists): improve app performance when there are large inactive token lists (#1510)

* improve inactive token lists performance

* cleanup before larger changes to combine inactive lists

* only do the search if the query does not match any active lists, limit the number of results

* more performance improvements

* search inactive lists more aggressively
2021-05-12 08:52:17 -05:00
166 changed files with 1892 additions and 1201 deletions

View File

@@ -1,4 +1,4 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: Support
url: https://discord.gg/FCfyBSbCU5

View File

@@ -94,19 +94,13 @@ jobs:
The latest release is always accessible via our alias to the Cloudflare IPFS gateway at [app.uniswap.org](https://app.uniswap.org).
You can also access the Uniswap Interface directly from an IPFS gateway.
The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to store your settings.
**Beware** that other sites you access via the _same_ IPFS gateway can read and modify your settings on the Uniswap interface without your permission.
You can avoid this issue by using a subdomain IPFS gateway, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
The preferred URLs below are safe to use to access this specific release.
**BEWARE**: The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported.
**You should always use an IPFS gateway that enforces origin separation**, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
Your Uniswap settings are never remembered across different URLs.
Preferred URLs:
IPFS gateways:
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.cf-ipfs.com/
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/)
Other IPFS gateways:
- https://cloudflare-ipfs.com/ipfs/${{ steps.upload.outputs.hash }}/
- https://ipfs.infura.io/ipfs/${{ steps.upload.outputs.hash }}/
- https://ipfs.io/ipfs/${{ steps.upload.outputs.hash }}/
${{ needs.bump_version.outputs.changelog }}

View File

@@ -22,12 +22,6 @@ To access the Uniswap Interface, use an IPFS gateway link from the
[latest release](https://github.com/Uniswap/uniswap-interface/releases/latest),
or visit [app.uniswap.org](https://app.uniswap.org).
## Listing a token
Please see the
[@uniswap/default-token-list](https://github.com/uniswap/default-token-list)
repository.
## Development
### Install Dependencies

View File

@@ -0,0 +1,8 @@
const isDev = process.env.NODE_ENV !== 'production'
module.exports = {
styledComponents: {
fileName: isDev,
displayName: isDev,
},
}

View File

@@ -9,6 +9,7 @@
"@popperjs/core": "^2.4.4",
"@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3",
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.3.5",
"@storybook/addon-actions": "^6.1.17",
"@storybook/addon-essentials": "^6.1.17",
@@ -47,16 +48,16 @@
"@uniswap/token-lists": "^1.0.0-beta.19",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^1.0.9",
"@uniswap/v2-sdk": "^3.0.0-alpha.0",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "1.0.0",
"@uniswap/v3-sdk": "^1.0.8",
"@uniswap/v3-sdk": "^3.0.0-alpha.2",
"@web3-react/core": "^6.0.9",
"@web3-react/fortmatic-connector": "^6.0.9",
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/portis-connector": "^6.0.9",
"@web3-react/walletconnect-connector": "^6.1.1",
"@web3-react/walletlink-connector": "^6.0.9",
"@web3-react/walletlink-connector": "^6.2.0",
"ajv": "^6.12.3",
"cids": "^1.0.0",
"copy-to-clipboard": "^3.2.0",

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useCopyClipboard from '../../hooks/useCopyClipboard'
import { LinkStyledButton } from '../../theme'

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { CheckCircle, Triangle } from 'react-feather'
import { useActiveWeb3React } from '../../hooks'

View File

@@ -1,7 +1,7 @@
import React from 'react'
import Badge, { BadgeVariant } from 'components/Badge'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { MouseoverTooltip } from '../../components/Tooltip'
import { useTranslation } from 'react-i18next'

View File

@@ -1,5 +1,5 @@
import { Story } from '@storybook/react/types-6-0'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import React from 'react'
import {
ButtonConfirmed,

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { RowBetween } from '../Row'

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Box } from 'rebass/styled-components'
const Card = styled(Box)<{ width?: string; padding?: string; border?: string; borderRadius?: string }>`

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
const Column = styled.div`
display: flex;

View File

@@ -1,4 +1,4 @@
import { CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import React, { useMemo } from 'react'
import useTheme from '../../hooks/useTheme'
import { TYPE } from '../../theme'
@@ -9,7 +9,7 @@ export function FiatValue({
fiatValue,
priceImpact,
}: {
fiatValue: CurrencyAmount | null | undefined
fiatValue: CurrencyAmount<Currency> | null | undefined
priceImpact?: Percent
}) {
const theme = useTheme()
@@ -25,9 +25,9 @@ export function FiatValue({
return (
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
{fiatValue ? '~' : ''}$
<HoverInlineText text={fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'} />{' '}
<HoverInlineText text={fiatValue ? fiatValue?.toSignificant(6, { groupSeparator: ',' }) : '-'} />{' '}
{priceImpact ? (
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-100).toSignificant(3)}%)</span>
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-1).toSignificant(3)}%)</span>
) : null}
</TYPE.body>
)

View File

@@ -1,7 +1,7 @@
import { Pair } from '@uniswap/v2-sdk'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import React, { useState, useCallback } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
@@ -18,6 +18,7 @@ import useTheme from '../../hooks/useTheme'
import { Lock } from 'react-feather'
import { AutoColumn } from 'components/Column'
import { FiatValue } from './FiatValue'
import { formatTokenAmount } from 'utils/formatTokenAmount'
const InputPanel = styled.div<{ hideInput?: boolean }>`
${({ theme }) => theme.flexColumnNoWrap}
@@ -134,11 +135,7 @@ const StyledBalanceMax = styled.button<{ disabled?: boolean }>`
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};
margin-left: 0.25rem;
:hover {
/* border: 1px solid ${({ theme }) => theme.primary1}; */
}
:focus {
/* border: 1px solid ${({ theme }) => theme.primary1}; */
outline: none;
}
@@ -159,7 +156,7 @@ interface CurrencyInputPanelProps {
pair?: Pair | null
hideInput?: boolean
otherCurrency?: Currency | null
fiatValue?: CurrencyAmount | null
fiatValue?: CurrencyAmount<Token> | null
priceImpact?: Percent
id: string
showCommonBases?: boolean
@@ -273,7 +270,7 @@ export default function CurrencyInputPanel({
>
{!hideBalance && !!currency && selectedCurrencyBalance
? (customBalanceText ?? 'Balance: ') +
selectedCurrencyBalance?.toSignificant(4) +
formatTokenAmount(selectedCurrencyBalance, 4) +
' ' +
currency.symbol
: '-'}
@@ -285,7 +282,6 @@ export default function CurrencyInputPanel({
) : (
'-'
)}
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
</RowBetween>
</FiatRow>

View File

@@ -1,9 +1,9 @@
import { ChainId, Currency, ETHER, Token } from '@uniswap/sdk-core'
import { ChainId, Currency } from '@uniswap/sdk-core'
import React, { useMemo } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import EthereumLogo from '../../assets/images/ethereum-logo.png'
import useHttpLocations from '../../hooks/useHttpLocations'
import { WrappedTokenInfo } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import Logo from '../Logo'
export const getTokenLogoURL = (address: string) =>
@@ -37,9 +37,9 @@ export default function CurrencyLogo({
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
const srcs: string[] = useMemo(() => {
if (currency === ETHER) return []
if (!currency || currency.isEther) return []
if (currency instanceof Token) {
if (currency.isToken) {
const defaultUrls = currency.chainId === ChainId.MAINNET ? [getTokenLogoURL(currency.address)] : []
if (currency instanceof WrappedTokenInfo) {
return [...uriLocations, ...defaultUrls]
@@ -49,7 +49,7 @@ export default function CurrencyLogo({
return []
}, [currency, uriLocations])
if (currency === ETHER) {
if (currency?.isEther) {
return <StyledEthereumLogo src={EthereumLogo} size={size} style={style} {...rest} />
}

View File

@@ -1,6 +1,6 @@
import { Currency } from '@uniswap/sdk-core'
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import CurrencyLogo from '../CurrencyLogo'
const Wrapper = styled.div<{ margin: boolean; sizeraw: number }>`

View File

@@ -1,9 +1,11 @@
import React, { ErrorInfo } from 'react'
import store, { AppState } from '../../state'
import { ExternalLink, ThemedBackground, TYPE } from '../../theme'
import { AutoColumn } from '../Column'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import ReactGA from 'react-ga'
import { getUserAgent } from '../../utils/getUserAgent'
import { AutoRow } from '../Row'
const FallbackWrapper = styled.div`
display: flex;
@@ -14,14 +16,15 @@ const FallbackWrapper = styled.div`
`
const BodyWrapper = styled.div<{ margin?: string }>`
position: relative;
margin-top: 1rem;
max-width: 60%;
padding: 1rem;
width: 100%;
white-space: ;
`
const CodeBlockWrapper = styled.div`
background: ${({ theme }) => theme.bg0};
overflow: auto;
white-space: pre;
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
border-radius: 24px;
@@ -79,18 +82,30 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
<TYPE.main fontSize={10}>{error.stack}</TYPE.main>
</code>
</CodeBlockWrapper>
<LinkWrapper>
<ExternalLink
id={`create-github-issue-link`}
href={`https://github.com/Uniswap/uniswap-interface/issues/new?assignees=&labels=bug&body=${encodedBody}&title=Crash report`}
target="_blank"
>
<TYPE.link fontSize={16}>
Create an issue on GitHub
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
<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}>
Create an issue on GitHub
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
<LinkWrapper>
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
<TYPE.link fontSize={16}>
Get support on Discord
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
</AutoRow>
</AutoColumn>
</BodyWrapper>
</FallbackWrapper>
@@ -100,22 +115,45 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
}
}
function getRelevantState(): null | keyof AppState {
const path = window.location.hash
if (!path.startsWith('#/')) {
return null
}
const pieces = path.substring(2).split(/[\/\\?]/)
switch (pieces[0]) {
case 'swap':
return 'swap'
case 'add':
if (pieces[1] === 'v2') return 'mint'
else return 'mintV3'
case 'remove':
if (pieces[1] === 'v2') return 'burn'
else return 'burnV3'
}
return null
}
function issueBody(error: Error): string {
if (!error) throw new Error('no error to report')
const relevantState = getRelevantState()
const deviceData = getUserAgent()
return `**Bug Description**
return `## URL
App crashed
${window.location.href}
**Steps to Reproduce**
1. Go to ...
2. Click on ...
...
${
relevantState
? `## \`${relevantState}\` state
\`\`\`json
${JSON.stringify(store.getState()[relevantState], null, 2)}
\`\`\`
`
: ''
}
${
error.name &&
`**Error**
`## Error
\`\`\`
${error.name}${error.message && `: ${error.message}`}
@@ -124,7 +162,7 @@ ${error.name}${error.message && `: ${error.message}`}
}
${
error.stack &&
`**Stacktrace**
`## Stacktrace
\`\`\`
${error.stack}
@@ -133,9 +171,9 @@ ${error.stack}
}
${
deviceData &&
`**Device data**
`## Device data
\`\`\`json5
\`\`\`json
${JSON.stringify(deviceData, null, 2)}
\`\`\`
`

View File

@@ -6,7 +6,7 @@ import { DynamicSection } from 'pages/AddLiquidity/styled'
import { TYPE } from 'theme'
import { RowBetween } from 'components/Row'
import { ButtonRadioChecked } from 'components/Button'
import styled from 'styled-components'
import styled from 'styled-components/macro'
const ResponsiveText = styled(TYPE.label)`
${({ theme }) => theme.mediaWidth.upToSmall`

View File

@@ -1,6 +1,6 @@
import JSBI from 'jsbi'
import React from 'react'
import { CurrencyAmount, Fraction } from '@uniswap/sdk-core'
import { JSBI } from '@uniswap/v2-sdk'
import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core'
const CURRENCY_AMOUNT_MIN = new Fraction(JSBI.BigInt(1), JSBI.BigInt(1000000))
@@ -8,7 +8,7 @@ export default function FormattedCurrencyAmount({
currencyAmount,
significantDigits = 4,
}: {
currencyAmount: CurrencyAmount
currencyAmount: CurrencyAmount<Currency>
significantDigits?: number
}) {
return (

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AlertTriangle, X } from 'react-feather'
import { useURLWarningToggle, useURLWarningVisible } from '../../state/user/hooks'

View File

@@ -1,7 +1,7 @@
import { ChainId, TokenAmount } from '@uniswap/sdk-core'
import { ChainId, CurrencyAmount, Token } from '@uniswap/sdk-core'
import React, { useMemo } from 'react'
import { X } from 'react-feather'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { UNI } from '../../constants'
import { useTotalSupply } from '../../hooks/useTotalSupply'
@@ -45,14 +45,14 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
const uni = chainId ? UNI[chainId] : undefined
const total = useAggregateUniBalance()
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, uni)
const uniToClaim: TokenAmount | undefined = useTotalUniEarned()
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(account ?? undefined, uni)
const uniToClaim: CurrencyAmount<Token> | undefined = useTotalUniEarned()
const totalSupply: TokenAmount | undefined = useTotalSupply(uni)
const totalSupply: CurrencyAmount<Token> | undefined = useTotalSupply(uni)
const uniPrice = useUSDCPrice(uni)
const blockTimestamp = useCurrentBlockTimestamp()
const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
const circulation: TokenAmount | undefined = useMemo(
const circulation: CurrencyAmount<Token> | undefined = useMemo(
() =>
blockTimestamp && uni && chainId === ChainId.MAINNET
? computeUniCirculation(uni, blockTimestamp, unclaimedUni)

View File

@@ -1,11 +1,12 @@
import { ChainId } from '@uniswap/sdk-core'
import useScrollPosition from '@react-hook/window-scroll'
import React, { useState } from 'react'
import { Text } from 'rebass'
import { NavLink } from 'react-router-dom'
import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import { Moon, Sun } from 'react-feather'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Logo from '../../assets/svg/logo.svg'
import LogoDark from '../../assets/svg/logo_white.svg'
@@ -29,7 +30,7 @@ import { Dots } from '../swap/styleds'
import Modal from '../Modal'
import UniBalanceContent from './UniBalanceContent'
const HeaderFrame = styled.div`
const HeaderFrame = styled.div<{ showBackground: boolean }>`
display: grid;
grid-template-columns: 120px 1fr 120px;
align-items: center;
@@ -39,12 +40,17 @@ const HeaderFrame = styled.div`
width: 100%;
top: 0;
position: relative;
/* border-bottom: 1px solid ${({ theme }) => theme.bg2}; */
padding: 1rem;
z-index: 21;
/* background-color: ${({ theme }) => theme.bg1}; */
position: relative;
/* Background slide effect on scroll. */
background-image: ${({ theme }) => `linear-gradient(to bottom, transparent 50%, ${theme.bg0} 50% )}}`}
background-position: ${({ showBackground }) => (showBackground ? '0 -100%' : '0 0')};
background-size: 100% 200%;
box-shadow: 0px 0px 0px 1px ${({ theme, showBackground }) => (showBackground ? theme.bg2 : 'transparent;')};
transition: background-position .1s, box-shadow .1s;
${({ theme }) => theme.mediaWidth.upToMedium`
padding: 1rem;
grid-template-columns: 120px 1fr;
@@ -319,8 +325,10 @@ export default function Header() {
const [showUniBalanceModal, setShowUniBalanceModal] = useState(false)
const showClaimPopup = useShowClaimPopup()
const scrollY = useScrollPosition()
return (
<HeaderFrame>
<HeaderFrame showBackground={scrollY > 45}>
<ClaimModal />
<Modal isOpen={showUniBalanceModal} onDismiss={() => setShowUniBalanceModal(false)}>
<UniBalanceContent setShowUniBalanceModal={setShowUniBalanceModal} />

View File

@@ -1,9 +1,9 @@
import Tooltip from 'components/Tooltip'
import React, { useState } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
const TextWrapper = styled.span<{ margin: boolean; link: boolean; fontSize?: string; adjustSize?: boolean }>`
position: relative;
const TextWrapper = styled.span<{ margin: boolean; link?: boolean; fontSize?: string; adjustSize?: boolean }>`
cursor: auto;
margin-left: ${({ margin }) => margin && '4px'};
color: ${({ theme, link }) => (link ? theme.blue1 : theme.text1)};
font-size: ${({ fontSize }) => fontSize ?? 'inherit'};
@@ -32,7 +32,7 @@ const HoverInlineText = ({
const [showHover, setShowHover] = useState(false)
if (!text) {
return <span></span>
return <span />
}
if (text.length > maxCharacters) {
@@ -43,7 +43,7 @@ const HoverInlineText = ({
onMouseLeave={() => setShowHover(false)}
margin={margin}
adjustSize={adjustSize}
link={!!link}
link={link}
fontSize={fontSize}
{...rest}
>
@@ -54,7 +54,7 @@ const HoverInlineText = ({
}
return (
<TextWrapper margin={margin} adjustSize={adjustSize} link={!!link} fontSize={fontSize} {...rest}>
<TextWrapper margin={margin} adjustSize={adjustSize} link={link} fontSize={fontSize} {...rest}>
{text}
</TextWrapper>
)

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useRef } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks'
import Jazzicon from 'jazzicon'

View File

@@ -1,7 +1,7 @@
import { Story } from '@storybook/react/types-6-0'
import React from 'react'
// import Row, { RowFixed } from 'components/Row'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Component, { LineChartProps } from './'
import { dummyData } from './data'
// import { AutoColumn } from 'components/Column'

View File

@@ -3,7 +3,7 @@ import { createChart, IChartApi } from 'lightweight-charts'
import { darken } from 'polished'
import { RowBetween } from 'components/Row'
import Card from '../Card'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useTheme from 'hooks/useTheme'
const Wrapper = styled(Card)`

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useHttpLocations from '../../hooks/useHttpLocations'
import Logo from '../Logo'

View File

@@ -1,6 +1,6 @@
import { Story } from '@storybook/react/types-6-0'
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Component from './index'
const Wrapper = styled.div`

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import { NavLink, Link as HistoryLink } from 'react-router-dom'

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { escapeRegExp } from '../../utils'
const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>`

View File

@@ -2,7 +2,7 @@ import { Placement } from '@popperjs/core'
import { transparentize } from 'polished'
import React, { useCallback, useState } from 'react'
import { usePopper } from 'react-popper'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useInterval from '../../hooks/useInterval'
import Portal from '@reach/portal'

View File

@@ -1,4 +1,4 @@
import { TokenAmount } from '@uniswap/sdk-core'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import React, { useEffect } from 'react'
import { X } from 'react-feather'
import styled, { keyframes } from 'styled-components'
@@ -65,7 +65,7 @@ export default function ClaimPopup() {
// const userHasAvailableclaim = useUserHasAvailableClaim()
const userHasAvailableclaim: boolean = useUserHasAvailableClaim(account)
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
// listen for available claim and show popup if needed
useEffect(() => {

View File

@@ -3,7 +3,7 @@ import React, { useCallback, useMemo } from 'react'
import ReactGA from 'react-ga'
import { useDispatch } from 'react-redux'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AppDispatch } from '../../state'
import { useRemovePopup } from '../../state/application/hooks'
import { acceptListUpdate } from '../../state/lists/actions'

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useActivePopups } from '../../state/application/hooks'
import { AutoColumn } from '../Column'
import PopupItem from './PopupItem'

View File

@@ -2,7 +2,7 @@ import React from 'react'
import { Token } from '@uniswap/sdk-core'
import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { unwrappedToken } from '../../utils/wrappedCurrency'
import { ButtonEmpty } from '../Button'

View File

@@ -1,10 +1,11 @@
import JSBI from 'jsbi'
import React, { useState } from 'react'
import { Percent, TokenAmount } from '@uniswap/sdk-core'
import { JSBI, Pair } from '@uniswap/v2-sdk'
import { Percent, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { ChevronDown, ChevronUp } from 'react-feather'
import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks'
@@ -38,7 +39,7 @@ interface PositionCardProps {
pair: Pair
showUnwrapped?: boolean
border?: string
stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
stakedBalance?: CurrencyAmount<Token> // optional balance to indicate that liquidity is deposited in mining pool
}
export default function V2PositionCard({ pair, border, stakedBalance }: PositionCardProps) {
@@ -56,8 +57,10 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
: undefined
const [token0Deposited, token1Deposited] =
@@ -65,7 +68,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? [
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
@@ -174,7 +177,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
</Text>
</FixedHeightRow>
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.quotient, BIG_INT_ZERO) && (
<RowBetween marginTop="10px">
<ButtonPrimary
padding="8px"

View File

@@ -1,11 +1,12 @@
import { Percent, TokenAmount } from '@uniswap/sdk-core'
import { JSBI, Pair } from '@uniswap/v2-sdk'
import JSBI from 'jsbi'
import { Percent, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { darken } from 'polished'
import React, { useState } from 'react'
import { ChevronDown, ChevronUp } from 'react-feather'
import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks'
@@ -49,7 +50,7 @@ interface PositionCardProps {
pair: Pair
showUnwrapped?: boolean
border?: string
stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
stakedBalance?: CurrencyAmount<Token> // optional balance to indicate that liquidity is deposited in mining pool
}
export function MinimalPositionCard({ pair, showUnwrapped = false, border }: PositionCardProps) {
@@ -64,8 +65,10 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
const totalPoolTokens = useTotalSupply(pair.liquidityToken)
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
: undefined
const [token0Deposited, token1Deposited] =
@@ -73,7 +76,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? [
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
@@ -82,7 +85,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
return (
<>
{userPoolBalance && JSBI.greaterThan(userPoolBalance.raw, JSBI.BigInt(0)) ? (
{userPoolBalance && JSBI.greaterThan(userPoolBalance.quotient, JSBI.BigInt(0)) ? (
<GreyCard border={border}>
<AutoColumn gap="12px">
<FixedHeightRow>
@@ -175,8 +178,10 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
: undefined
const [token0Deposited, token1Deposited] =
@@ -184,7 +189,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? [
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
@@ -296,7 +301,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
View accrued fees and analytics<span style={{ fontSize: '11px' }}></span>
</ExternalLink>
</ButtonSecondary>
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.quotient, BIG_INT_ZERO) && (
<RowBetween marginTop="10px">
<ButtonPrimary
padding="8px"
@@ -327,7 +332,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
</ButtonPrimary>
</RowBetween>
)}
{stakedBalance && JSBI.greaterThan(stakedBalance.raw, BIG_INT_ZERO) && (
{stakedBalance && JSBI.greaterThan(stakedBalance.quotient, BIG_INT_ZERO) && (
<ButtonPrimary
padding="8px"
borderRadius="8px"

View File

@@ -4,7 +4,7 @@
// import { basisPointsToPercent } from 'utils'
// import { DAI, WBTC } from '../../constants'
// import Component, { PositionListProps } from './index'
// import { TokenAmount } from '@uniswap/sdk-core'
// import { CurrencyAmount } from '@uniswap/sdk-core'
// import JSBI from 'jsbi'
// const FEE_BIPS = {
@@ -12,8 +12,8 @@
// THIRTY: basisPointsToPercent(30),
// ONE_HUNDRED: basisPointsToPercent(100),
// }
// const daiAmount = new TokenAmount(DAI, JSBI.BigInt(500 * 10 ** 18))
// const wbtcAmount = new TokenAmount(WBTC, JSBI.BigInt(10 ** 7))
// const daiAmount = CurrencyAmount.fromRawAmount(DAI, JSBI.BigInt(500 * 10 ** 18))
// const wbtcAmount = CurrencyAmount.fromRawAmount(WBTC, JSBI.BigInt(10 ** 7))
// const positions = [
// {
// feesEarned: {

View File

@@ -1,7 +1,7 @@
import PositionListItem from 'components/PositionListItem'
import React from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { MEDIA_WIDTHS } from 'theme'
import { PositionDetails } from 'types/position'

View File

@@ -5,7 +5,7 @@ import DoubleCurrencyLogo from 'components/DoubleLogo'
import { usePool } from 'hooks/usePools'
import { useToken } from 'hooks/Tokens'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { HideSmall, MEDIA_WIDTHS, SmallOnly } from 'theme'
import { PositionDetails } from 'types/position'
import { WETH9, Price, Token, Percent } from '@uniswap/sdk-core'
@@ -121,8 +121,8 @@ export interface PositionListItemProps {
export function getPriceOrderingFromPositionForUI(
position?: Position
): {
priceLower?: Price
priceUpper?: Price
priceLower?: Price<Token, Token>
priceUpper?: Price<Token, Token>
quote?: Token
base?: Token
} {
@@ -130,8 +130,8 @@ export function getPriceOrderingFromPositionForUI(
return {}
}
const token0 = position.amount0.token
const token1 = position.amount1.token
const token0 = position.amount0.currency
const token1 = position.amount1.currency
// if token0 is a dollar-stable asset, set it as the quote token
const stables = [DAI, USDC, USDT]

View File

@@ -13,7 +13,7 @@ import RateToggle from 'components/RateToggle'
import DoubleCurrencyLogo from 'components/DoubleLogo'
import RangeBadge from 'components/Badge/RangeBadge'
import { ThemeContext } from 'styled-components'
import { JSBI } from '@uniswap/v2-sdk'
import JSBI from 'jsbi'
export const PositionPreview = ({
position,

View File

@@ -1,5 +1,5 @@
import React, { useContext } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AutoColumn } from '../Column'
import { ThemeContext } from 'styled-components'
import { TYPE } from '../../theme'

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Tooltip from '../Tooltip'
const QuestionWrapper = styled.div`

View File

@@ -1,5 +1,5 @@
import React from 'react'
import { Currency, Price } from '@uniswap/sdk-core'
import { Currency, Price, Token } from '@uniswap/sdk-core'
import StepCounter from 'components/InputStepCounter/InputStepCounter'
import { RowBetween } from 'components/Row'
import { useActiveWeb3React } from 'hooks'
@@ -19,8 +19,8 @@ export default function RangeSelector({
currencyB,
feeAmount,
}: {
priceLower?: Price
priceUpper?: Price
priceLower?: Price<Token, Token>
priceUpper?: Price<Token, Token>
getDecrementLower: () => string
getIncrementLower: () => string
getDecrementUpper: () => string

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Box } from 'rebass/styled-components'
const Row = styled(Box)<{

View File

@@ -1,7 +1,7 @@
import React from 'react'
import { Text } from 'rebass'
import { ChainId, Currency, currencyEquals, Token, ETHER } from '@uniswap/sdk-core'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { SUGGESTED_BASES } from '../../constants'
import { AutoColumn } from '../Column'
@@ -49,7 +49,7 @@ export default function CommonBases({
onSelect(ETHER)
}
}}
disable={selectedCurrency === ETHER}
disable={selectedCurrency?.isEther}
>
<CurrencyLogo currency={ETHER} style={{ marginRight: 8 }} />
<Text fontWeight={500} fontSize={16}>
@@ -57,7 +57,7 @@ export default function CommonBases({
</Text>
</BaseWrapper>
{(typeof chainId === 'number' ? SUGGESTED_BASES[chainId] ?? [] : []).map((token: Token) => {
const selected = selectedCurrency instanceof Token && selectedCurrency.address === token.address
const selected = selectedCurrency?.isToken && selectedCurrency.address === token.address
return (
<BaseWrapper onClick={() => !selected && onSelect(token)} disable={selected} key={token.address}>
<CurrencyLogo currency={token} style={{ marginRight: 8 }} />

View File

@@ -1,13 +1,14 @@
import { Currency, CurrencyAmount, currencyEquals, ETHER, Token } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, currencyEquals, Token } from '@uniswap/sdk-core'
import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks'
import { WrappedTokenInfo, useCombinedActiveList } from '../../state/lists/hooks'
import { useCombinedActiveList } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { useIsUserAddedToken, useAllInactiveTokens } from '../../hooks/Tokens'
import { useIsUserAddedToken } from '../../hooks/Tokens'
import Column from '../Column'
import { RowFixed, RowBetween } from '../Row'
import CurrencyLogo from '../CurrencyLogo'
@@ -23,7 +24,7 @@ import QuestionHelper from 'components/QuestionHelper'
import useTheme from 'hooks/useTheme'
function currencyKey(currency: Currency): string {
return currency instanceof Token ? currency.address : currency === ETHER ? 'ETHER' : ''
return currency.isToken ? currency.address : 'ETHER'
}
const StyledBalanceText = styled(Text)`
@@ -55,7 +56,7 @@ const FixedContentRow = styled.div`
align-items: center;
`
function Balance({ balance }: { balance: CurrencyAmount }) {
function Balance({ balance }: { balance: CurrencyAmount<Currency> }) {
return <StyledBalanceText title={balance.toExact()}>{balance.toSignificant(4)}</StyledBalanceText>
}
@@ -113,7 +114,7 @@ function CurrencyRow({
const { account } = useActiveWeb3React()
const key = currencyKey(currency)
const selectedTokenList = useCombinedActiveList()
const isOnSelectedList = isTokenOnList(selectedTokenList, currency)
const isOnSelectedList = isTokenOnList(selectedTokenList, currency.isToken ? currency : undefined)
const customAdded = useIsUserAddedToken(currency)
const balance = useCurrencyBalance(account ?? undefined, currency)
@@ -132,7 +133,7 @@ function CurrencyRow({
{currency.symbol}
</Text>
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
{currency.name} {!isOnSelectedList && customAdded && '• Added by user'}
{currency.name} {!currency.isEther && !isOnSelectedList && customAdded && '• Added by user'}
</TYPE.darkGray>
</Column>
<TokenTags currency={currency} />
@@ -143,84 +144,84 @@ function CurrencyRow({
)
}
const BREAK_LINE = 'BREAK'
type BreakLine = typeof BREAK_LINE
function isBreakLine(x: unknown): x is BreakLine {
return x === BREAK_LINE
}
function BreakLineComponent({ style }: { style: CSSProperties }) {
const theme = useTheme()
return (
<FixedContentRow style={style}>
<LightGreyCard padding="8px 12px" borderRadius="8px">
<RowBetween>
<RowFixed>
<TokenListLogoWrapper src={TokenListLogo} />
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
Expanded results from inactive Token Lists
</TYPE.main>
</RowFixed>
<QuestionHelper text="Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists." />
</RowBetween>
</LightGreyCard>
</FixedContentRow>
)
}
export default function CurrencyList({
height,
currencies,
otherListTokens,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
showImportView,
setImportToken,
breakIndex,
}: {
height: number
currencies: Currency[]
otherListTokens?: WrappedTokenInfo[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
showImportView: () => void
setImportToken: (token: Token) => void
breakIndex: number | undefined
}) {
const itemData: (Currency | undefined)[] = useMemo(() => {
let formatted: (Currency | undefined)[] = showETH ? [Currency.ETHER, ...currencies] : currencies
if (breakIndex !== undefined) {
formatted = [...formatted.slice(0, breakIndex), undefined, ...formatted.slice(breakIndex, formatted.length)]
const itemData: (Currency | BreakLine)[] = useMemo(() => {
if (otherListTokens && otherListTokens?.length > 0) {
return [...currencies, BREAK_LINE, ...otherListTokens]
}
return formatted
}, [breakIndex, currencies, showETH])
return currencies
}, [currencies, otherListTokens])
const { chainId } = useActiveWeb3React()
const theme = useTheme()
const inactiveTokens: {
[address: string]: Token
} = useAllInactiveTokens()
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
function TokenRow({ data, index, style }) {
const row: Currency | BreakLine = data[index]
if (isBreakLine(row)) {
return <BreakLineComponent style={style} />
}
const currency = row
const isSelected = Boolean(currency && selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(currency && otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => currency && onCurrencySelect(currency)
const token = wrappedCurrency(currency, chainId)
const showImport = inactiveTokens && token && Object.keys(inactiveTokens).includes(token.address)
if (index === breakIndex || !data) {
return (
<FixedContentRow style={style}>
<LightGreyCard padding="8px 12px" borderRadius="8px">
<RowBetween>
<RowFixed>
<TokenListLogoWrapper src={TokenListLogo} />
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
Expanded results from inactive Token Lists
</TYPE.main>
</RowFixed>
<QuestionHelper text="Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists." />
</RowBetween>
</LightGreyCard>
</FixedContentRow>
)
}
const showImport = index > currencies.length
if (showImport && token) {
return (
<ImportRow
style={style}
token={token}
showImportView={showImportView}
setImportToken={setImportToken}
dim={true}
/>
<ImportRow style={style} token={token} showImportView={showImportView} setImportToken={setImportToken} dim />
)
} else {
} else if (currency) {
return (
<CurrencyRow
style={style}
@@ -230,22 +231,18 @@ export default function CurrencyList({
otherSelected={otherSelected}
/>
)
} else {
return null
}
},
[
chainId,
inactiveTokens,
onCurrencySelect,
otherCurrency,
selectedCurrency,
setImportToken,
showImportView,
breakIndex,
theme.text1,
]
[chainId, currencies.length, onCurrencySelect, otherCurrency, selectedCurrency, setImportToken, showImportView]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
const itemKey = useCallback((index: number, data: typeof itemData) => {
const currency = data[index]
if (isBreakLine(currency)) return BREAK_LINE
return currencyKey(currency)
}, [])
return (
<FixedSizeList

View File

@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import { useActiveWeb3React } from '../../hooks'
import { useAllTokens, useToken, useIsUserAddedToken, useFoundOnInactiveList } from '../../hooks/Tokens'
import { useAllTokens, useToken, useIsUserAddedToken, useSearchInactiveTokenLists } from '../../hooks/Tokens'
import { CloseIcon, TYPE, ButtonText, IconWrapper } from '../../theme'
import { isAddress } from '../../utils'
import Column from '../Column'
@@ -16,7 +16,7 @@ import { filterTokens, useSortedTokensByQuery } from './filtering'
import { useTokenComparator } from './sorting'
import { PaddedColumn, SearchInput, Separator } from './styleds'
import AutoSizer from 'react-virtualized-auto-sizer'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useToggle from 'hooks/useToggle'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import useTheme from 'hooks/useTheme'
@@ -94,11 +94,6 @@ export function CurrencySearch({
}
}, [isAddressSearch])
const showETH: boolean = useMemo(() => {
const s = debouncedQuery.toLowerCase().trim()
return s === '' || s === 'e' || s === 'et' || s === 'eth'
}, [debouncedQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const filteredTokens: Token[] = useMemo(() => {
@@ -111,6 +106,14 @@ export function CurrencySearch({
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
const filteredSortedTokensWithETH: Currency[] = useMemo(() => {
const s = debouncedQuery.toLowerCase().trim()
if (s === '' || s === 'e' || s === 'et' || s === 'eth') {
return [ETHER, ...filteredSortedTokens]
}
return filteredSortedTokens
}, [debouncedQuery, filteredSortedTokens])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
@@ -139,17 +142,17 @@ export function CurrencySearch({
const s = debouncedQuery.toLowerCase().trim()
if (s === 'eth') {
handleCurrencySelect(ETHER)
} else if (filteredSortedTokens.length > 0) {
} else if (filteredSortedTokensWithETH.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
filteredSortedTokensWithETH[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
filteredSortedTokensWithETH.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
handleCurrencySelect(filteredSortedTokensWithETH[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, debouncedQuery]
[filteredSortedTokensWithETH, handleCurrencySelect, debouncedQuery]
)
// menu ui
@@ -158,8 +161,9 @@ export function CurrencySearch({
useOnClickOutside(node, open ? toggle : undefined)
// if no results on main list, show option to expand into inactive
const inactiveTokens = useFoundOnInactiveList(debouncedQuery)
const filteredInactiveTokens: Token[] = useSortedTokensByQuery(inactiveTokens, debouncedQuery)
const filteredInactiveTokens = useSearchInactiveTokenLists(
filteredTokens.length === 0 || (debouncedQuery.length > 2 && !isAddressSearch) ? debouncedQuery : undefined
)
return (
<ContentWrapper>
@@ -197,11 +201,8 @@ export function CurrencySearch({
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={
filteredInactiveTokens ? filteredSortedTokens.concat(filteredInactiveTokens) : filteredSortedTokens
}
breakIndex={inactiveTokens && filteredSortedTokens ? filteredSortedTokens.length : undefined}
currencies={filteredSortedTokensWithETH}
otherListTokens={filteredInactiveTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}

View File

@@ -1,6 +1,7 @@
import { Currency, Token } from '@uniswap/sdk-core'
import React, { useCallback, useEffect, useState } from 'react'
import useLast from '../../hooks/useLast'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import Modal from '../Modal'
import { CurrencySearch } from './CurrencySearch'
import { ImportToken } from './ImportToken'
@@ -81,6 +82,7 @@ export default function CurrencySearchModal({
<ImportToken
tokens={[importToken]}
onDismiss={onDismiss}
list={importToken instanceof WrappedTokenInfo ? importToken.list : undefined}
onBack={() =>
setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search)
}

View File

@@ -1,5 +1,5 @@
import React, { useState, useCallback } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import ReactGA from 'react-ga'
import { TYPE, CloseIcon } from 'theme'
import Card from 'components/Card'

View File

@@ -5,13 +5,12 @@ import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import { TYPE } from 'theme'
import ListLogo from 'components/ListLogo'
import { useActiveWeb3React } from 'hooks'
import { useCombinedInactiveList } from 'state/lists/hooks'
import useTheme from 'hooks/useTheme'
import { ButtonPrimary } from 'components/Button'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useIsUserAddedToken, useIsTokenActive } from 'hooks/Tokens'
import { CheckCircle } from 'react-feather'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
const TokenSection = styled.div<{ dim?: boolean }>`
padding: 4px 20px;
@@ -53,18 +52,14 @@ export default function ImportRow({
showImportView: () => void
setImportToken: (token: Token) => void
}) {
// gloabls
const { chainId } = useActiveWeb3React()
const theme = useTheme()
// check if token comes from list
const inactiveTokenList = useCombinedInactiveList()
const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
// check if already active on list or local storage tokens
const isAdded = useIsUserAddedToken(token)
const isActive = useIsTokenActive(token)
const list = token instanceof WrappedTokenInfo ? token.list : undefined
return (
<TokenSection style={style}>
<CurrencyLogo currency={token} size={'24px'} style={{ opacity: dim ? '0.6' : '1' }} />

View File

@@ -1,6 +1,7 @@
import { TokenList } from '@uniswap/token-lists/dist/types'
import React from 'react'
import { Token, Currency } from '@uniswap/sdk-core'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { TYPE, CloseIcon } from 'theme'
import Card from 'components/Card'
import { AutoColumn } from 'components/Column'
@@ -15,7 +16,6 @@ import { useAddUserToken } from 'state/user/hooks'
import { getEtherscanLink } from 'utils'
import { useActiveWeb3React } from 'hooks'
import { ExternalLink } from '../../theme/components'
import { useCombinedInactiveList } from 'state/lists/hooks'
import ListLogo from 'components/ListLogo'
import { PaddedColumn } from './styleds'
@@ -41,28 +41,26 @@ const AddressText = styled(TYPE.blue)`
interface ImportProps {
tokens: Token[]
list?: TokenList
onBack?: () => void
onDismiss?: () => void
handleCurrencySelect?: (currency: Currency) => void
}
export function ImportToken({ tokens, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
const theme = useTheme()
const { chainId } = useActiveWeb3React()
const addToken = useAddUserToken()
// use for showing import source on inactive tokens
const inactiveTokenList = useCombinedInactiveList()
return (
<Wrapper>
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div></div>}
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
<TYPE.mediumHeader>Import {tokens.length > 1 ? 'Tokens' : 'Token'}</TYPE.mediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div></div>}
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
</RowBetween>
</PaddedColumn>
<SectionBreak />
@@ -76,7 +74,6 @@ export function ImportToken({ tokens, onBack, onDismiss, handleCurrencySelect }:
</TYPE.body>
</AutoColumn>
{tokens.map((token) => {
const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
return (
<Card
backgroundColor={theme.bg2}

View File

@@ -4,7 +4,7 @@ import { RowBetween } from 'components/Row'
import { ArrowLeft } from 'react-feather'
import { Text } from 'rebass'
import { CloseIcon } from 'theme'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Token } from '@uniswap/sdk-core'
import { ManageLists } from './ManageLists'
import ManageTokens from './ManageTokens'

View File

@@ -3,7 +3,7 @@ import { Settings, CheckCircle } from 'react-feather'
import ReactGA from 'react-ga'
import { usePopper } from 'react-popper'
import { useDispatch, useSelector } from 'react-redux'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useFetchListCallback } from '../../hooks/useFetchListCallback'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { TokenList } from '@uniswap/token-lists'

View File

@@ -4,7 +4,7 @@ import { PaddedColumn, Separator, SearchInput } from './styleds'
import Row, { RowBetween, RowFixed } from 'components/Row'
import { TYPE, ExternalLinkIcon, TrashIcon, ButtonText, ExternalLink } from 'theme'
import { useToken } from 'hooks/Tokens'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useUserAddedTokens, useRemoveUserAddedToken } from 'state/user/hooks'
import { Token } from '@uniswap/sdk-core'
import CurrencyLogo from 'components/CurrencyLogo'

View File

@@ -1,6 +1,6 @@
import React from 'react'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { RowFixed } from '../Row'
export const FilterWrapper = styled(RowFixed)`

View File

@@ -1,14 +1,20 @@
import { TokenInfo } from '@uniswap/token-lists'
import { useMemo } from 'react'
import { isAddress } from '../../utils'
import { Token } from '@uniswap/sdk-core'
export function filterTokens(tokens: Token[], search: string): Token[] {
if (search.length === 0) return tokens
const alwaysTrue = () => true
/**
* Create a filter function to apply to a token for whether it matches a particular search query
* @param search the search query to apply to the token
*/
export function createTokenFilterFunction<T extends Token | TokenInfo>(search: string): (tokens: T) => boolean {
const searchingAddress = isAddress(search)
if (searchingAddress) {
return tokens.filter((token) => token.address === searchingAddress)
const lower = searchingAddress.toLowerCase()
return (t: T) => ('isToken' in t ? searchingAddress === t.address : lower === t.address.toLowerCase())
}
const lowerSearchParts = search
@@ -16,9 +22,7 @@ export function filterTokens(tokens: Token[], search: string): Token[] {
.split(/\s+/)
.filter((s) => s.length > 0)
if (lowerSearchParts.length === 0) {
return tokens
}
if (lowerSearchParts.length === 0) return alwaysTrue
const matchesSearch = (s: string): boolean => {
const sParts = s
@@ -29,10 +33,11 @@ export function filterTokens(tokens: Token[], search: string): Token[] {
return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
}
return tokens.filter((token) => {
const { symbol, name } = token
return (symbol && matchesSearch(symbol)) || (name && matchesSearch(name))
})
return ({ name, symbol }: T): boolean => Boolean((symbol && matchesSearch(symbol)) || (name && matchesSearch(name)))
}
export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: string): T[] {
return tokens.filter(createTokenFilterFunction(search))
}
export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] {

View File

@@ -1,9 +1,9 @@
import { Token, TokenAmount } from '@uniswap/sdk-core'
import { Token, CurrencyAmount, Currency } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { useAllTokenBalances } from '../../state/wallet/hooks'
// compare two token amounts with highest one coming first
function balanceComparator(balanceA?: TokenAmount, balanceB?: TokenAmount) {
function balanceComparator(balanceA?: CurrencyAmount<Currency>, balanceB?: CurrencyAmount<Currency>) {
if (balanceA && balanceB) {
return balanceA.greaterThan(balanceB) ? -1 : balanceA.equalTo(balanceB) ? 0 : 1
} else if (balanceA && balanceA.greaterThan('0')) {
@@ -15,7 +15,7 @@ function balanceComparator(balanceA?: TokenAmount, balanceB?: TokenAmount) {
}
function getTokenComparator(balances: {
[tokenAddress: string]: TokenAmount | undefined
[tokenAddress: string]: CurrencyAmount<Currency> | undefined
}): (tokenA: Token, tokenB: Token) => number {
return function sortTokens(tokenA: Token, tokenB: Token): number {
// -1 = a is first

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row'

View File

@@ -94,6 +94,8 @@ const MenuFlyout = styled.span`
${({ theme }) => theme.mediaWidth.upToMedium`
min-width: 18.125rem;
`};
user-select: none;
`
const Break = styled.div`

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
const StyledRangeInput = styled.input<{ size: number }>`
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */

View File

@@ -1,6 +1,6 @@
import { readableColor } from 'polished'
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { colors } from 'theme'
const Swatch = styled.div`

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { TYPE } from '../../theme'
const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>`

View File

@@ -1,5 +1,5 @@
import { Story } from '@storybook/react/types-6-0'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import React, { useState } from 'react'
import MultiToggle from './MultiToggle'

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
export const ToggleWrapper = styled.button<{ width?: string }>`
display: flex;

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
const ToggleElement = styled.span<{ isActive?: boolean; isOnSwitch?: boolean }>`
padding: 0.25rem 0.5rem;

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Popover, { PopoverProps } from '../Popover'
const TooltipContainer = styled.div`

View File

@@ -136,11 +136,16 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
if (value.length === 0) {
setDeadline(DEFAULT_DEADLINE_FROM_NOW)
} else {
const parsed: number = Math.floor(Number.parseFloat(value) * 60)
if (!Number.isInteger(parsed) || parsed < 60) {
try {
const parsed: number = Math.floor(Number.parseFloat(value) * 60)
if (!Number.isInteger(parsed) || parsed < 60 || parsed > 180 * 60) {
setDeadlineError(DeadlineError.InvalidInput)
} else {
setDeadline(parsed)
}
} catch (error) {
console.error(error)
setDeadlineError(DeadlineError.InvalidInput)
} else {
setDeadline(parsed)
}
}
}

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { ExternalLink } from '../../theme'
const InfoCard = styled.button<{ active?: boolean }>`

View File

@@ -1,6 +1,6 @@
import { AbstractConnector } from '@web3-react/abstract-connector'
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Option from './Option'
import { SUPPORTED_WALLETS } from '../../constants'
import { injected } from '../../connectors'

View File

@@ -5,7 +5,7 @@ import { AutoRow } from 'components/Row'
import React, { useEffect, useState } from 'react'
import { isMobile } from 'react-device-detect'
import ReactGA from 'react-ga'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import MetamaskIcon from '../../assets/images/metamask.png'
import { ReactComponent as Close } from '../../assets/images/x.svg'
import { fortmatic, injected, portis } from '../../connectors'

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'
import { useWeb3React } from '@web3-react/core'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useTranslation } from 'react-i18next'
import { network } from '../../connectors'

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react'
import Modal from '../Modal'
import { AutoColumn, ColumnCenter } from '../Column'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { DataCard, CardSection, Break } from '../earn/styled'
import { RowBetween } from '../Row'
import { TYPE, ExternalLink, CloseIcon, CustomLightSpinner, UniTokenAnimated } from '../../theme'
@@ -17,7 +17,7 @@ import { isAddress } from 'ethers/lib/utils'
import Confetti from '../Confetti'
import { CardNoise, CardBGImage, CardBGImageSmaller } from '../earn/styled'
import { useIsTransactionPending } from '../../state/transactions/hooks'
import { TokenAmount } from '@uniswap/sdk-core'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { getEtherscanLink, shortenAddress } from '../../utils'
const ContentWrapper = styled(AutoColumn)`
@@ -59,7 +59,7 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
// monitor the status of the claim from contracts and txns
const { claimCallback } = useClaimCallback(parsedAddress)
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(parsedAddress)
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(parsedAddress)
// check if the user has something available
const hasAvailableClaim = useUserHasAvailableClaim(parsedAddress)

View File

@@ -1,9 +1,9 @@
import { TokenAmount } from '@uniswap/sdk-core'
import { JSBI } from '@uniswap/v2-sdk'
import JSBI from 'jsbi'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { isAddress } from 'ethers/lib/utils'
import React, { useEffect, useState } from 'react'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import tokenLogo from '../../assets/images/token-logo.png'
import { useActiveWeb3React } from '../../hooks'
@@ -60,7 +60,7 @@ export default function ClaimModal() {
// monitor the status of the claim from contracts and txns
const { claimCallback } = useClaimCallback(account)
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
const { claimSubmitted, claimTxn } = useUserHasSubmittedClaim(account ?? undefined)
const claimConfirmed = Boolean(claimTxn?.receipt)
@@ -116,12 +116,12 @@ export default function ClaimModal() {
)}
{userClaimData?.flags?.isLP &&
unclaimedAmount &&
JSBI.greaterThanOrEqual(unclaimedAmount.raw, nonLPAmount) && (
JSBI.greaterThanOrEqual(unclaimedAmount.quotient, nonLPAmount) && (
<RowBetween>
<TYPE.subHeader color="white">Liquidity</TYPE.subHeader>
<TYPE.subHeader color="white">
{unclaimedAmount
.subtract(new TokenAmount(unclaimedAmount.token, nonLPAmount))
.subtract(CurrencyAmount.fromRawAmount(unclaimedAmount.currency, nonLPAmount))
.toFixed(0, { groupSeparator: ',' })}{' '}
UNI
</TYPE.subHeader>

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react'
import Modal from '../Modal'
import { AutoColumn } from '../Column'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { RowBetween } from '../Row'
import { TYPE, CloseIcon } from '../../theme'
import { ButtonError } from '../Button'

View File

@@ -1,11 +1,11 @@
import React from 'react'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { TYPE, StyledInternalLink } from '../../theme'
import DoubleCurrencyLogo from '../DoubleLogo'
import { ETHER, TokenAmount } from '@uniswap/sdk-core'
import { JSBI } from '@uniswap/v2-sdk'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import { ButtonPrimary } from '../Button'
import { StakingInfo } from '../../state/stake/hooks'
import { useColor } from '../../hooks/useColor'
@@ -79,25 +79,25 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
const isStaking = Boolean(stakingInfo.stakedAmount.greaterThan('0'))
// get the color of the token
const token = currency0 === ETHER ? token1 : token0
const WETH = currency0 === ETHER ? token0 : token1
const token = currency0.isEther ? token1 : token0
const WETH = currency0.isEther ? token0 : token1
const backgroundColor = useColor(token)
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo.stakedAmount.token)
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo.stakedAmount.currency)
const [, stakingTokenPair] = useV2Pair(...stakingInfo.tokens)
// let returnOverMonth: Percent = new Percent('0')
let valueOfTotalStakedAmountInWETH: TokenAmount | undefined
let valueOfTotalStakedAmountInWETH: CurrencyAmount<Token> | undefined
if (totalSupplyOfStakingToken && stakingTokenPair) {
// take the total amount of LP tokens staked, multiply by ETH value of all LP tokens, divide by all LP tokens
valueOfTotalStakedAmountInWETH = new TokenAmount(
valueOfTotalStakedAmountInWETH = CurrencyAmount.fromRawAmount(
WETH,
JSBI.divide(
JSBI.multiply(
JSBI.multiply(stakingInfo.totalStakedAmount.raw, stakingTokenPair.reserveOf(WETH).raw),
JSBI.multiply(stakingInfo.totalStakedAmount.quotient, stakingTokenPair.reserveOf(WETH).quotient),
JSBI.BigInt(2) // this is b/c the value of LP shares are ~double the value of the WETH they entitle owner to
),
totalSupplyOfStakingToken.raw
totalSupplyOfStakingToken.quotient
)
)
}

View File

@@ -4,14 +4,14 @@ import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
import Modal from '../Modal'
import { AutoColumn } from '../Column'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { RowBetween } from '../Row'
import { TYPE, CloseIcon } from '../../theme'
import { ButtonConfirmed, ButtonError } from '../Button'
import ProgressCircles from '../ProgressSteps'
import CurrencyInputPanel from '../CurrencyInputPanel'
import { Pair } from '@uniswap/v2-sdk'
import { TokenAmount } from '@uniswap/sdk-core'
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
import { useActiveWeb3React } from '../../hooks'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { usePairContract, useStakingContract } from '../../hooks/useContract'
@@ -40,7 +40,7 @@ interface StakingModalProps {
isOpen: boolean
onDismiss: () => void
stakingInfo: StakingInfo
userLiquidityUnstaked: TokenAmount | undefined
userLiquidityUnstaked: CurrencyAmount<Token> | undefined
}
export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiquidityUnstaked }: StakingModalProps) {
@@ -48,10 +48,14 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
// track and parse user input
const [typedValue, setTypedValue] = useState('')
const { parsedAmount, error } = useDerivedStakeInfo(typedValue, stakingInfo.stakedAmount.token, userLiquidityUnstaked)
const { parsedAmount, error } = useDerivedStakeInfo(
typedValue,
stakingInfo.stakedAmount.currency,
userLiquidityUnstaked
)
const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId)
let hypotheticalRewardRate: TokenAmount = new TokenAmount(stakingInfo.rewardRate.token, '0')
let hypotheticalRewardRate: CurrencyAmount<Token> = CurrencyAmount.fromRawAmount(stakingInfo.rewardRate.currency, '0')
if (parsedAmountWrapped?.greaterThan('0')) {
hypotheticalRewardRate = stakingInfo.getHypotheticalRewardRate(
stakingInfo.stakedAmount.add(parsedAmountWrapped),
@@ -71,7 +75,10 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
}, [onDismiss])
// pair contract for this token to be staked
const dummyPair = new Pair(new TokenAmount(stakingInfo.tokens[0], '0'), new TokenAmount(stakingInfo.tokens[1], '0'))
const dummyPair = new Pair(
CurrencyAmount.fromRawAmount(stakingInfo.tokens[0], '0'),
CurrencyAmount.fromRawAmount(stakingInfo.tokens[1], '0')
)
const pairContract = usePairContract(dummyPair.liquidityToken.address)
// approval data for stake
@@ -84,11 +91,11 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
setAttempting(true)
if (stakingContract && parsedAmount && deadline) {
if (approval === ApprovalState.APPROVED) {
await stakingContract.stake(`0x${parsedAmount.raw.toString(16)}`, { gasLimit: 350000 })
await stakingContract.stake(`0x${parsedAmount.quotient.toString(16)}`, { gasLimit: 350000 })
} else if (signatureData) {
stakingContract
.stakeWithPermit(
`0x${parsedAmount.raw.toString(16)}`,
`0x${parsedAmount.quotient.toString(16)}`,
signatureData.deadline,
signatureData.v,
signatureData.r,
@@ -155,7 +162,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
onUserInput={onUserInput}
onMax={handleMax}
showMaxButton={!atMaxAmount}
currency={stakingInfo.stakedAmount.token}
currency={stakingInfo.stakedAmount.currency}
pair={dummyPair}
label={''}
customBalanceText={'Available to deposit: '}

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react'
import Modal from '../Modal'
import { AutoColumn } from '../Column'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { RowBetween } from '../Row'
import { TYPE, CloseIcon } from '../../theme'
import { ButtonError } from '../Button'

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AutoColumn } from '../Column'
import uImage from '../../assets/images/big_unicorn.png'

View File

@@ -1,4 +1,4 @@
import { Percent } from '@uniswap/sdk-core'
import { Percent, Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useContext } from 'react'
@@ -12,7 +12,7 @@ import FormattedPriceImpact from './FormattedPriceImpact'
import SwapRoute from './SwapRoute'
export interface AdvancedSwapDetailsProps {
trade?: V2Trade | V3Trade
trade?: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
allowedSlippage: Percent
}

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useLastTruthy } from '../../hooks/useLast'
import { AdvancedSwapDetails, AdvancedSwapDetailsProps } from './AdvancedSwapDetails'

View File

@@ -7,7 +7,7 @@ import useParsedQueryString from '../../hooks/useParsedQueryString'
import { DEFAULT_VERSION, Version } from '../../hooks/useToggledVersion'
import { HideSmall, TYPE, SmallOnly } from '../../theme'
import { ButtonPrimary } from '../Button'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Zap } from 'react-feather'
const ResponsiveButton = styled(ButtonPrimary)`

View File

@@ -1,4 +1,4 @@
import { currencyEquals, Percent } from '@uniswap/sdk-core'
import { Currency, currencyEquals, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useCallback, useMemo } from 'react'
@@ -13,7 +13,11 @@ import SwapModalHeader from './SwapModalHeader'
* Returns true if the trade requires a confirmation of details before we can submit it
* @param args either a pair of V2 trades or a pair of V3 trades
*/
function tradeMeaningfullyDiffers(...args: [V2Trade, V2Trade] | [V3Trade, V3Trade]): boolean {
function tradeMeaningfullyDiffers(
...args:
| [V2Trade<Currency, Currency, TradeType>, V2Trade<Currency, Currency, TradeType>]
| [V3Trade<Currency, Currency, TradeType>, V3Trade<Currency, Currency, TradeType>]
): boolean {
const [tradeA, tradeB] = args
return (
tradeA.tradeType !== tradeB.tradeType ||
@@ -38,8 +42,8 @@ export default function ConfirmSwapModal({
txHash,
}: {
isOpen: boolean
trade: V2Trade | V3Trade | undefined
originalTrade: V2Trade | V3Trade | undefined
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
originalTrade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
attemptingTxn: boolean
txHash: string | undefined
recipient: string | null

View File

@@ -1,6 +1,5 @@
import { Percent } from '@uniswap/sdk-core'
import React from 'react'
import { ONE_BIPS } from '../../constants'
import { warningSeverity } from '../../utils/prices'
import { ErrorText, ErrorPill } from './styleds'
@@ -10,11 +9,7 @@ import { ErrorText, ErrorPill } from './styleds'
export default function FormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
return (
<ErrorText fontWeight={500} fontSize={12} severity={warningSeverity(priceImpact)}>
{priceImpact
? priceImpact.lessThan(ONE_BIPS)
? `-${priceImpact.toFixed(2)}%`
: `${priceImpact.toFixed(2)}%`
: '-'}
{priceImpact ? `${priceImpact.multiply(-1).toFixed(2)}%` : '-'}
</ErrorText>
)
}
@@ -22,11 +17,7 @@ export default function FormattedPriceImpact({ priceImpact }: { priceImpact?: Pe
export function SmallFormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
return (
<ErrorPill fontWeight={500} fontSize={12} severity={warningSeverity(priceImpact)}>
{priceImpact
? priceImpact.lessThan(ONE_BIPS)
? `(-${priceImpact.toFixed(2)}%)`
: `(-${priceImpact.toFixed(2)}%)`
: '-'}
{priceImpact ? `(${priceImpact.multiply(-1).toFixed(2)}%)` : '-'}
</ErrorPill>
)
}

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import SettingsTab from '../Settings'
import { Percent } from '@uniswap/sdk-core'

View File

@@ -1,3 +1,4 @@
import { Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
@@ -12,7 +13,7 @@ export default function SwapModalFooter({
swapErrorMessage,
disabledConfirm,
}: {
trade: V2Trade | V3Trade
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
onConfirm: () => void
swapErrorMessage: string | undefined
disabledConfirm: boolean

View File

@@ -1,4 +1,4 @@
import { Percent, TradeType } from '@uniswap/sdk-core'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useContext, useState } from 'react'
@@ -47,7 +47,7 @@ export default function SwapModalHeader({
showAcceptChanges,
onAcceptChanges,
}: {
trade: V2Trade | V3Trade
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
allowedSlippage: Percent
recipient: string | null
showAcceptChanges: boolean

View File

@@ -1,3 +1,4 @@
import { Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade, FeeAmount } from '@uniswap/v3-sdk'
import React, { Fragment, memo, useContext } from 'react'
@@ -14,7 +15,11 @@ function LabeledArrow({}: { fee: FeeAmount }) {
return <ChevronRight size={14} color={theme.text2} />
}
export default memo(function SwapRoute({ trade }: { trade: V2Trade | V3Trade }) {
export default memo(function SwapRoute({
trade,
}: {
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
}) {
const tokenPath = trade instanceof V2Trade ? trade.route.path : trade.route.tokenPath
const theme = useContext(ThemeContext)
return (

View File

@@ -1,12 +1,11 @@
import React, { useCallback } from 'react'
import { Price } from '@uniswap/sdk-core'
import { Price, Currency } from '@uniswap/sdk-core'
import { useContext } from 'react'
import { Text } from 'rebass'
import styled, { ThemeContext } from 'styled-components'
interface TradePriceProps {
price: Price
price: Price<Currency, Currency>
showInverted: boolean
setShowInverted: (showInverted: boolean) => void
}

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { TYPE, CloseIcon, ExternalLink } from 'theme'
import { ButtonEmpty } from 'components/Button'
import Modal from 'components/Modal'

View File

@@ -55,7 +55,7 @@ export const ErrorText = styled(Text)<{ severity?: 0 | 1 | 2 | 3 | 4 }>`
? theme.yellow2
: severity === 1
? theme.text1
: theme.green1};
: theme.text2};
`
export const ErrorPill = styled(Text)<{ severity?: 0 | 1 | 2 | 3 | 4 }>`

View File

@@ -2,7 +2,7 @@ import React, { useState } from 'react'
import Modal from '../Modal'
import { AutoColumn } from '../Column'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { RowBetween } from '../Row'
import { TYPE } from '../../theme'
import { X } from 'react-feather'
@@ -15,6 +15,7 @@ import { useDelegateCallback } from '../../state/governance/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { UNI } from '../../constants'
import { LoadingView, SubmittedView } from '../ModalViews'
import { formatTokenAmount } from 'utils/formatTokenAmount'
const ContentWrapper = styled(AutoColumn)`
width: 100%;
@@ -116,7 +117,7 @@ export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalPro
<LoadingView onDismiss={wrappedOndismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>{usingDelegate ? 'Delegating votes' : 'Unlocking Votes'}</TYPE.largeHeader>
<TYPE.main fontSize={36}>{uniBalance?.toSignificant(4)}</TYPE.main>
<TYPE.main fontSize={36}> {formatTokenAmount(uniBalance, 4)}</TYPE.main>
</AutoColumn>
</LoadingView>
)}
@@ -124,7 +125,7 @@ export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalPro
<SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
<TYPE.main fontSize={36}>{uniBalance?.toSignificant(4)}</TYPE.main>
<TYPE.main fontSize={36}>{formatTokenAmount(uniBalance, 4)}</TYPE.main>
</AutoColumn>
</SubmittedView>
)}

View File

@@ -12,7 +12,8 @@ import Circle from '../../assets/images/blue-loader.svg'
import { useVoteCallback, useUserVotes } from '../../state/governance/hooks'
import { getEtherscanLink } from '../../utils'
import { ExternalLink } from '../../theme/components'
import { TokenAmount } from '@uniswap/sdk-core'
import { formatTokenAmount } from 'utils/formatTokenAmount'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
const ContentWrapper = styled(AutoColumn)`
width: 100%;
@@ -48,7 +49,7 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, support }: Vo
}: {
voteCallback: (proposalId: string | undefined, support: boolean) => Promise<string> | undefined
} = useVoteCallback()
const availableVotes: TokenAmount | undefined = useUserVotes()
const availableVotes: CurrencyAmount<Token> | undefined = useUserVotes()
// monitor call to help UI loading state
const [hash, setHash] = useState<string | undefined>()
@@ -92,7 +93,7 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, support }: Vo
} proposal ${proposalId}`}</TYPE.mediumHeader>
<StyledClosed stroke="black" onClick={wrappedOndismiss} />
</RowBetween>
<TYPE.largeHeader>{availableVotes?.toSignificant(4)} Votes</TYPE.largeHeader>
<TYPE.largeHeader>{formatTokenAmount(availableVotes, 4)} Votes</TYPE.largeHeader>
<ButtonPrimary onClick={onVote}>
<TYPE.mediumHeader color="white">{`Vote ${
support ? 'for ' : 'against'

View File

@@ -1,16 +1,17 @@
import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks'
import { parseBytes32String } from '@ethersproject/strings'
import { Currency, ETHER, Token, currencyEquals } from '@uniswap/sdk-core'
import { Currency, currencyEquals, ETHER, Token } from '@uniswap/sdk-core'
import { arrayify } from 'ethers/lib/utils'
import { useMemo } from 'react'
import { useCombinedActiveList, useCombinedInactiveList } from '../state/lists/hooks'
import { createTokenFilterFunction } from '../components/SearchModal/filtering'
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 { useActiveWeb3React } from './index'
import { useBytes32TokenContract, useTokenContract } from './useContract'
import { filterTokens } from '../components/SearchModal/filtering'
import { arrayify } from 'ethers/lib/utils'
// reduce token map into standard address <-> Token mapping, optionally include user added tokens
function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } {
@@ -51,30 +52,39 @@ export function useAllTokens(): { [address: string]: Token } {
return useTokensFromMap(allTokens, true)
}
export function useAllInactiveTokens(): { [address: string]: Token } {
// get inactive tokens
const inactiveTokensMap = useCombinedInactiveList()
const inactiveTokens = useTokensFromMap(inactiveTokensMap, false)
// filter out any token that are on active list
const activeTokensAddresses = Object.keys(useAllTokens())
const filteredInactive = activeTokensAddresses
? Object.keys(inactiveTokens).reduce<{ [address: string]: Token }>((newMap, address) => {
if (!activeTokensAddresses.includes(address)) {
newMap[address] = inactiveTokens[address]
}
return newMap
}, {})
: inactiveTokens
return filteredInactive
}
export function useUnsupportedTokens(): { [address: string]: Token } {
const unsupportedTokensMap = useUnsupportedTokenList()
return useTokensFromMap(unsupportedTokensMap, false)
}
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 = 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()
@@ -85,21 +95,6 @@ export function useIsTokenActive(token: Token | undefined | null): boolean {
return !!activeTokens[token.address]
}
// used to detect extra search results
export function useFoundOnInactiveList(searchQuery: string): Token[] | undefined {
const { chainId } = useActiveWeb3React()
const inactiveTokens = useAllInactiveTokens()
return useMemo(() => {
if (!chainId || searchQuery === '') {
return undefined
} else {
const tokens = filterTokens(Object.values(inactiveTokens), searchQuery)
return tokens
}
}, [chainId, inactiveTokens, searchQuery])
}
// Check if currency is included in custom list from user storage
export function useIsUserAddedToken(currency: Currency | undefined | null): boolean {
const userAddedTokens = useUserAddedTokens()

View File

@@ -12,16 +12,13 @@ function computeAllRoutes(
pools: Pool[],
chainId: ChainId,
currentPath: Pool[] = [],
allPaths: Route[] = [],
allPaths: Route<Currency, Currency>[] = [],
startCurrencyIn: Currency = currencyIn,
maxHops = 2
): Route[] {
): Route<Currency, Currency>[] {
const tokenIn = wrappedCurrency(currencyIn, chainId)
const tokenOut = wrappedCurrency(currencyOut, chainId)
if (!tokenIn || !tokenOut) {
throw new Error('Could not wrap currencies')
}
if (!tokenIn || !tokenOut) throw new Error('Missing tokenIn/tokenOut')
for (const pool of pools) {
if (currentPath.indexOf(pool) !== -1 || !pool.involvesToken(tokenIn)) continue
@@ -51,7 +48,10 @@ function computeAllRoutes(
* @param currencyIn the input currency
* @param currencyOut the output currency
*/
export function useAllV3Routes(currencyIn?: Currency, currencyOut?: Currency): { loading: boolean; routes: Route[] } {
export function useAllV3Routes(
currencyIn?: Currency,
currencyOut?: Currency
): { loading: boolean; routes: Route<Currency, Currency>[] } {
const { chainId } = useActiveWeb3React()
const { pools, loading: poolsLoading } = useV3SwapPools(currencyIn, currencyOut)

View File

@@ -0,0 +1,22 @@
import { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import { AppDispatch } from 'state'
import { updateUserExpertMode } from '../state/user/actions'
import useParsedQueryString from './useParsedQueryString'
export default function ApeModeQueryParamReader(): null {
useApeModeQueryParamReader()
return null
}
function useApeModeQueryParamReader() {
const dispatch = useDispatch<AppDispatch>()
const { ape } = useParsedQueryString()
useEffect(() => {
if (typeof ape !== 'string') return
if (ape === '' || ape.toLowerCase() === 'true') {
dispatch(updateUserExpertMode({ userExpertMode: true }))
}
})
}

View File

@@ -1,6 +1,6 @@
import { MaxUint256 } from '@ethersproject/constants'
import { TransactionResponse } from '@ethersproject/providers'
import { TokenAmount, CurrencyAmount, ETHER, ChainId, Percent } from '@uniswap/sdk-core'
import { CurrencyAmount, ChainId, Percent, Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { useCallback, useMemo } from 'react'
@@ -21,18 +21,18 @@ export enum ApprovalState {
// returns a variable indicating the state of the approval and a function which approves if necessary or early returns
export function useApproveCallback(
amountToApprove?: CurrencyAmount,
amountToApprove?: CurrencyAmount<Currency>,
spender?: string
): [ApprovalState, () => Promise<void>] {
const { account } = useActiveWeb3React()
const token = amountToApprove instanceof TokenAmount ? amountToApprove.token : undefined
const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined
const currentAllowance = useTokenAllowance(token, account ?? undefined, spender)
const pendingApproval = useHasPendingApproval(token?.address, spender)
// check the current approval status
const approvalState: ApprovalState = useMemo(() => {
if (!amountToApprove || !spender) return ApprovalState.UNKNOWN
if (amountToApprove.currency === ETHER) return ApprovalState.APPROVED
if (amountToApprove.currency.isEther) return ApprovalState.APPROVED
// we might not have enough data to know whether or not we need to approve
if (!currentAllowance) return ApprovalState.UNKNOWN
@@ -76,11 +76,11 @@ export function useApproveCallback(
const estimatedGas = await tokenContract.estimateGas.approve(spender, MaxUint256).catch(() => {
// general fallback for tokens who restrict approval amounts
useExact = true
return tokenContract.estimateGas.approve(spender, amountToApprove.raw.toString())
return tokenContract.estimateGas.approve(spender, amountToApprove.quotient.toString())
})
return tokenContract
.approve(spender, useExact ? amountToApprove.raw.toString() : MaxUint256, {
.approve(spender, useExact ? amountToApprove.quotient.toString() : MaxUint256, {
gasLimit: calculateGasMargin(estimatedGas),
})
.then((response: TransactionResponse) => {
@@ -99,13 +99,16 @@ export function useApproveCallback(
}
// wraps useApproveCallback in the context of a swap
export function useApproveCallbackFromTrade(trade: V2Trade | V3Trade | undefined, allowedSlippage: Percent) {
export function useApproveCallbackFromTrade(
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
) {
const { chainId } = useActiveWeb3React()
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
const amountToApprove = useMemo(() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined), [
trade,
allowedSlippage,
])
const amountToApprove = useMemo(
() => (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
[trade, allowedSlippage]
)
return useApproveCallback(
amountToApprove,
trade instanceof V2Trade ? V2_ROUTER_ADDRESS : trade instanceof V3Trade ? swapRouterAddress : undefined

View File

@@ -1,4 +1,4 @@
import { Token, Currency, CurrencyAmount, TokenAmount, TradeType } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { encodeRouteToPath, Route, Trade } from '@uniswap/v3-sdk'
import { BigNumber } from 'ethers'
import { useMemo } from 'react'
@@ -20,16 +20,16 @@ export enum V3TradeState {
* @param currencyOut the desired output currency
*/
export function useBestV3TradeExactIn(
amountIn?: CurrencyAmount,
amountIn?: CurrencyAmount<Currency>,
currencyOut?: Currency
): { state: V3TradeState; trade: Trade | null } {
): { state: V3TradeState; trade: Trade<Currency, Currency, TradeType.EXACT_INPUT> | null } {
const quoter = useV3Quoter()
const { routes, loading: routesLoading } = useAllV3Routes(amountIn?.currency, currencyOut)
const quoteExactInInputs = useMemo(() => {
return routes.map((route) => [
encodeRouteToPath(route, false),
amountIn ? `0x${amountIn.raw.toString(16)}` : undefined,
amountIn ? `0x${amountIn.quotient.toString(16)}` : undefined,
])
}, [amountIn, routes])
@@ -51,7 +51,7 @@ export function useBestV3TradeExactIn(
}
const { bestRoute, amountOut } = quotesResults.reduce(
(currentBest: { bestRoute: Route | null; amountOut: BigNumber | null }, { result }, i) => {
(currentBest: { bestRoute: Route<Currency, Currency> | null; amountOut: BigNumber | null }, { result }, i) => {
if (!result) return currentBest
if (currentBest.amountOut === null) {
@@ -89,10 +89,7 @@ export function useBestV3TradeExactIn(
route: bestRoute,
tradeType: TradeType.EXACT_INPUT,
inputAmount: amountIn,
outputAmount:
currencyOut instanceof Token
? new TokenAmount(currencyOut, amountOut.toString())
: CurrencyAmount.ether(amountOut.toString()),
outputAmount: CurrencyAmount.fromRawAmount(currencyOut, amountOut.toString()),
}),
}
}, [amountIn, currencyOut, quotesResults, routes, routesLoading])
@@ -105,15 +102,15 @@ export function useBestV3TradeExactIn(
*/
export function useBestV3TradeExactOut(
currencyIn?: Currency,
amountOut?: CurrencyAmount
): { state: V3TradeState; trade: Trade | null } {
amountOut?: CurrencyAmount<Currency>
): { state: V3TradeState; trade: Trade<Currency, Currency, TradeType.EXACT_OUTPUT> | null } {
const quoter = useV3Quoter()
const { routes, loading: routesLoading } = useAllV3Routes(currencyIn, amountOut?.currency)
const quoteExactOutInputs = useMemo(() => {
return routes.map((route) => [
encodeRouteToPath(route, true),
amountOut ? `0x${amountOut.raw.toString(16)}` : undefined,
amountOut ? `0x${amountOut.quotient.toString(16)}` : undefined,
])
}, [amountOut, routes])
@@ -135,7 +132,7 @@ export function useBestV3TradeExactOut(
}
const { bestRoute, amountIn } = quotesResults.reduce(
(currentBest: { bestRoute: Route | null; amountIn: BigNumber | null }, { result }, i) => {
(currentBest: { bestRoute: Route<Currency, Currency> | null; amountIn: BigNumber | null }, { result }, i) => {
if (!result) return currentBest
if (currentBest.amountIn === null) {
@@ -172,10 +169,7 @@ export function useBestV3TradeExactOut(
trade: Trade.createUncheckedTrade({
route: bestRoute,
tradeType: TradeType.EXACT_OUTPUT,
inputAmount:
currencyIn instanceof Token
? new TokenAmount(currencyIn, amountIn.toString())
: CurrencyAmount.ether(amountIn.toString()),
inputAmount: CurrencyAmount.fromRawAmount(currencyIn, amountIn.toString()),
outputAmount: amountOut,
}),
}

View File

@@ -1,5 +1,5 @@
import JSBI from 'jsbi'
import { ChainId, CurrencyAmount, Percent, TokenAmount } from '@uniswap/sdk-core'
import { ChainId, Percent, CurrencyAmount, Currency, TradeType, Token } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { splitSignature } from 'ethers/lib/utils'
@@ -115,7 +115,7 @@ const PERMIT_ALLOWED_TYPE = [
]
export function useERC20Permit(
currencyAmount: CurrencyAmount | null | undefined,
currencyAmount: CurrencyAmount<Currency> | null | undefined,
spender: string | null | undefined,
overridePermitInfo: PermitInfo | undefined | null
): {
@@ -125,7 +125,7 @@ export function useERC20Permit(
} {
const { account, chainId, library } = useActiveWeb3React()
const transactionDeadline = useTransactionDeadline()
const tokenAddress = currencyAmount instanceof TokenAmount ? currencyAmount.token.address : undefined
const tokenAddress = currencyAmount?.currency?.isToken ? currencyAmount.currency.address : undefined
const eip2612Contract = useEIP2612Contract(tokenAddress)
const isArgentWallet = useIsArgentWallet()
const nonceInputs = useMemo(() => [account ?? undefined], [account])
@@ -172,7 +172,7 @@ export function useERC20Permit(
signatureData.tokenAddress === tokenAddress &&
signatureData.nonce === nonceNumber &&
signatureData.spender === spender &&
('allowed' in signatureData || JSBI.equal(JSBI.BigInt(signatureData.amount), currencyAmount.raw))
('allowed' in signatureData || JSBI.equal(JSBI.BigInt(signatureData.amount), currencyAmount.quotient))
return {
state: isSignatureDataValid ? UseERC20PermitState.SIGNED : UseERC20PermitState.NOT_SIGNED,
@@ -180,7 +180,7 @@ export function useERC20Permit(
gatherPermitSignature: async function gatherPermitSignature() {
const allowed = permitInfo.type === PermitType.ALLOWED
const signatureDeadline = transactionDeadline.toNumber() + PERMIT_VALIDITY_BUFFER
const value = currencyAmount.raw.toString()
const value = currencyAmount.quotient.toString()
const message = allowed
? {
@@ -264,13 +264,16 @@ const REMOVE_V2_LIQUIDITY_PERMIT_INFO: PermitInfo = {
}
export function useV2LiquidityTokenPermit(
liquidityAmount: TokenAmount | null | undefined,
liquidityAmount: CurrencyAmount<Token> | null | undefined,
spender: string | null | undefined
) {
return useERC20Permit(liquidityAmount, spender, REMOVE_V2_LIQUIDITY_PERMIT_INFO)
}
export function useERC20PermitFromTrade(trade: V2Trade | V3Trade | undefined, allowedSlippage: Percent) {
export function useERC20PermitFromTrade(
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
) {
const { chainId } = useActiveWeb3React()
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
const amountToApprove = useMemo(() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined), [

View File

@@ -14,8 +14,8 @@ export function useIsSwapUnsupported(currencyIn?: Currency, currencyOut?: Curren
// if unsupported list loaded & either token on list, mark as unsupported
return Boolean(
unsupportedTokens &&
((currencyIn && currencyIn instanceof Token && unsupportedTokens[currencyIn.address]) ||
(currencyOut && currencyOut instanceof Token && unsupportedTokens[currencyOut.address]))
((currencyIn?.isToken && unsupportedTokens[currencyIn.address]) ||
(currencyOut?.isToken && unsupportedTokens[currencyOut.address]))
)
}, [currencyIn, currencyOut, unsupportedTokens])
}

Some files were not shown because too many files have changed in this diff Show More