Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54f59e02fd | ||
|
|
7950e5c083 | ||
|
|
dd33205bf6 | ||
|
|
397a20b9ec | ||
|
|
0aac0b43aa | ||
|
|
702500794d | ||
|
|
8bea95fab2 | ||
|
|
27094c87f2 | ||
|
|
bede9171c3 | ||
|
|
251d7c0bc2 | ||
|
|
285e4f28f5 | ||
|
|
3aa045303a | ||
|
|
e0a7c3794e | ||
|
|
f5fc5da341 | ||
|
|
bea5c0484b | ||
|
|
27960532ca | ||
|
|
37a4e2f6e3 | ||
|
|
19a3b12ca8 |
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,4 +1,4 @@
|
||||
blank_issues_enabled: false
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Support
|
||||
url: https://discord.gg/FCfyBSbCU5
|
||||
|
||||
13
package.json
13
package.json
@@ -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",
|
||||
@@ -20,7 +21,7 @@
|
||||
"@storybook/react": "^6.1.17",
|
||||
"@storybook/theming": "^6.1.17",
|
||||
"@styled-system/css": "^5.1.5",
|
||||
"@typechain/ethers-v5": "^6.0.5",
|
||||
"@typechain/ethers-v5": "^7.0.0",
|
||||
"@types/jest": "^25.2.1",
|
||||
"@types/lodash.flatmap": "^4.5.6",
|
||||
"@types/luxon": "^1.24.4",
|
||||
@@ -47,10 +48,10 @@
|
||||
"@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.1",
|
||||
"@web3-react/core": "^6.0.9",
|
||||
"@web3-react/fortmatic-connector": "^6.0.9",
|
||||
"@web3-react/injected-connector": "^6.0.7",
|
||||
@@ -104,7 +105,7 @@
|
||||
"start-server-and-test": "^1.11.0",
|
||||
"styled-components": "^4.2.0",
|
||||
"styled-system": "^5.1.5",
|
||||
"typechain": "^4.0.3",
|
||||
"typechain": "^5.0.0",
|
||||
"typescript": "^4.2.3",
|
||||
"ua-parser-js": "^0.7.28",
|
||||
"use-count-up": "^2.2.5",
|
||||
@@ -117,8 +118,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
|
||||
"compile-external-abi-types": "npx typechain --target ethers-v5 --outDir src/abis/types './src/abis/**/*.json'",
|
||||
"compile-v3-contract-types": "npx typechain --target ethers-v5 --outDir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
|
||||
"compile-external-abi-types": "npx typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
|
||||
"compile-v3-contract-types": "npx typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
|
||||
"build": "yarn compile-contract-types && react-scripts build",
|
||||
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
|
||||
"postinstall": "yarn compile-contract-types",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.2 MiB |
@@ -1,14 +1,15 @@
|
||||
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'
|
||||
import { warningSeverity } from '../../utils/prices'
|
||||
import HoverInlineText from 'components/HoverInlineText'
|
||||
|
||||
export function FiatValue({
|
||||
fiatValue,
|
||||
priceImpact,
|
||||
}: {
|
||||
fiatValue: CurrencyAmount | null | undefined
|
||||
fiatValue: CurrencyAmount<Currency> | null | undefined
|
||||
priceImpact?: Percent
|
||||
}) {
|
||||
const theme = useTheme()
|
||||
@@ -23,9 +24,10 @@ export function FiatValue({
|
||||
|
||||
return (
|
||||
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
|
||||
{fiatValue ? '~' : ''}${fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'}
|
||||
{fiatValue ? '~' : ''}$
|
||||
<HoverInlineText text={fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'} />{' '}
|
||||
{priceImpact ? (
|
||||
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-100).toSignificant(3)}%)</span>
|
||||
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-1).toSignificant(3)}%)</span>
|
||||
) : null}
|
||||
</TYPE.body>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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 { darken } from 'polished'
|
||||
@@ -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>
|
||||
|
||||
@@ -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 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} />
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { AutoColumn } from '../Column'
|
||||
import styled from 'styled-components'
|
||||
import ReactGA from 'react-ga'
|
||||
import { getUserAgent } from '../../utils/getUserAgent'
|
||||
import { AutoRow } from '../Row'
|
||||
|
||||
const FallbackWrapper = styled.div`
|
||||
display: flex;
|
||||
@@ -14,14 +15,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 +81,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>
|
||||
@@ -112,7 +126,11 @@ App crashed
|
||||
1. Go to ...
|
||||
2. Click on ...
|
||||
...
|
||||
|
||||
|
||||
**URL**
|
||||
|
||||
${window.location.href}
|
||||
|
||||
${
|
||||
error.name &&
|
||||
`**Error**
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
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'
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
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'
|
||||
@@ -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} />
|
||||
|
||||
@@ -2,7 +2,7 @@ import Tooltip from 'components/Tooltip'
|
||||
import React, { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const TextWrapper = styled.div<{ margin: boolean; link: boolean; fontSize?: string; adjustSize?: boolean }>`
|
||||
const TextWrapper = styled.span<{ margin: boolean; link: boolean; fontSize?: string; adjustSize?: boolean }>`
|
||||
position: relative;
|
||||
margin-left: ${({ margin }) => margin && '4px'};
|
||||
color: ${({ theme, link }) => (link ? theme.blue1 : theme.text1)};
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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'
|
||||
@@ -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"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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'
|
||||
@@ -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"
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import { DAI, USDC, USDT, WBTC } from '../../constants'
|
||||
import RangeBadge from 'components/Badge/RangeBadge'
|
||||
import { RowFixed } from 'components/Row'
|
||||
import HoverInlineText from 'components/HoverInlineText'
|
||||
|
||||
const Row = styled(Link)`
|
||||
align-items: center;
|
||||
@@ -120,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
|
||||
} {
|
||||
@@ -129,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]
|
||||
@@ -244,8 +245,10 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
||||
>
|
||||
<RangeText>
|
||||
<ExtentsText>Min: </ExtentsText>
|
||||
{formatPrice(priceLower, 5)} {manuallyInverted ? currencyQuote?.symbol : currencyBase?.symbol} {' per '}{' '}
|
||||
{manuallyInverted ? currencyBase?.symbol : currencyQuote?.symbol}
|
||||
{formatPrice(priceLower, 5)}{' '}
|
||||
<HoverInlineText text={manuallyInverted ? currencyQuote?.symbol ?? '' : currencyBase?.symbol ?? ''} />{' '}
|
||||
{' per '}{' '}
|
||||
<HoverInlineText text={manuallyInverted ? currencyBase?.symbol ?? '' : currencyQuote?.symbol ?? ''} />
|
||||
</RangeText>{' '}
|
||||
<HideSmall>
|
||||
<DoubleArrow>⟷</DoubleArrow>{' '}
|
||||
@@ -255,8 +258,13 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
||||
</SmallOnly>
|
||||
<RangeText>
|
||||
<ExtentsText>Max:</ExtentsText>
|
||||
{formatPrice(priceUpper, 5)} {manuallyInverted ? currencyQuote?.symbol : currencyBase?.symbol} {' per '}{' '}
|
||||
{manuallyInverted ? currencyBase?.symbol : currencyQuote?.symbol}
|
||||
{formatPrice(priceUpper, 5)}{' '}
|
||||
<HoverInlineText text={manuallyInverted ? currencyQuote?.symbol ?? '' : currencyBase?.symbol ?? ''} />{' '}
|
||||
{' per '}{' '}
|
||||
<HoverInlineText
|
||||
maxCharacters={10}
|
||||
text={manuallyInverted ? currencyBase?.symbol ?? '' : currencyQuote?.symbol ?? ''}
|
||||
/>
|
||||
</RangeText>{' '}
|
||||
</RangeLineItem>
|
||||
</>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }} />
|
||||
|
||||
@@ -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 { 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
|
||||
|
||||
@@ -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'
|
||||
@@ -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}
|
||||
|
||||
@@ -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 { 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' }} />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { TokenList } from '@uniswap/token-lists/dist/types'
|
||||
import React from 'react'
|
||||
import { Token, Currency } from '@uniswap/sdk-core'
|
||||
import styled from 'styled-components'
|
||||
@@ -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}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
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[] {
|
||||
export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: string): T[] {
|
||||
if (search.length === 0) return tokens
|
||||
|
||||
const searchingAddress = isAddress(search)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -94,6 +94,8 @@ const MenuFlyout = styled.span`
|
||||
${({ theme }) => theme.mediaWidth.upToMedium`
|
||||
min-width: 18.125rem;
|
||||
`};
|
||||
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
const Break = styled.div`
|
||||
|
||||
@@ -5,8 +5,8 @@ import Popover, { PopoverProps } from '../Popover'
|
||||
const TooltipContainer = styled.div`
|
||||
width: 256px;
|
||||
padding: 0.6rem 1rem;
|
||||
/* line-height: 150%; */
|
||||
font-weight: 400;
|
||||
word-break: break-word;
|
||||
`
|
||||
|
||||
interface TooltipProps extends Omit<PopoverProps, 'content'> {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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'
|
||||
@@ -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>
|
||||
|
||||
@@ -4,8 +4,8 @@ import { RowBetween } from '../Row'
|
||||
import styled from 'styled-components'
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ 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: '}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.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.toFixed(2)}%)` : '-'}
|
||||
</ErrorPill>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 }>`
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 { filterTokens } 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,32 @@ 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()
|
||||
return useMemo(() => {
|
||||
if (!search || search.trim().length === 0) return []
|
||||
let result: WrappedTokenInfo[] = []
|
||||
for (const url of inactiveUrls) {
|
||||
const list = lists[url].current
|
||||
if (!list) continue
|
||||
const matching = filterTokens(
|
||||
list.tokens.filter((token) => token.chainId === chainId),
|
||||
search
|
||||
)
|
||||
result = [...result, ...matching.map((tokenInfo) => new WrappedTokenInfo(tokenInfo, list))]
|
||||
if (result.length >= minResults) return result
|
||||
}
|
||||
return result
|
||||
}, [chainId, inactiveUrls, lists, minResults, search])
|
||||
}
|
||||
|
||||
export function useIsTokenActive(token: Token | undefined | null): boolean {
|
||||
const activeTokens = useAllTokens()
|
||||
|
||||
@@ -85,21 +88,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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -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), [
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { useMemo } from 'react'
|
||||
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
|
||||
import { useActiveWeb3React } from './index'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Router, Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { ChainId, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { ChainId, Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/v3'
|
||||
import { getTradeVersion } from '../utils/getTradeVersion'
|
||||
@@ -49,7 +49,7 @@ interface FailedCall extends SwapCallEstimate {
|
||||
* @param signatureData the signature data of the permit of the input token amount, if available
|
||||
*/
|
||||
function useSwapCallArguments(
|
||||
trade: V2Trade | V3Trade | undefined, // trade to execute, required
|
||||
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined, // trade to execute, required
|
||||
allowedSlippage: Percent, // in bips
|
||||
recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
|
||||
signatureData: SignatureData | null | undefined
|
||||
@@ -136,7 +136,7 @@ function useSwapCallArguments(
|
||||
// returns a function that will execute a swap, if the parameters are all valid
|
||||
// and the user has approved the slippage adjusted input amount for the trade
|
||||
export function useSwapCallback(
|
||||
trade: V2Trade | V3Trade | undefined, // trade to execute, required
|
||||
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined, // trade to execute, required
|
||||
allowedSlippage: Percent, // in bips
|
||||
recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
|
||||
signatureData: SignatureData | undefined | null
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { useMemo } from 'react'
|
||||
@@ -8,7 +8,9 @@ const V2_SWAP_DEFAULT_SLIPPAGE = new Percent(50, 10_000) // .50%
|
||||
const V3_SWAP_DEFAULT_SLIPPAGE = new Percent(50, 10_000) // .50%
|
||||
const ONE_TENTHS_PERCENT = new Percent(10, 10_000) // .10%
|
||||
|
||||
export default function useSwapSlippageTolerance(trade: V2Trade | V3Trade | undefined): Percent {
|
||||
export default function useSwapSlippageTolerance(
|
||||
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
|
||||
): Percent {
|
||||
const defaultSlippageTolerance = useMemo(() => {
|
||||
if (!trade) return ONE_TENTHS_PERCENT
|
||||
if (trade instanceof V2Trade) return V2_SWAP_DEFAULT_SLIPPAGE
|
||||
|
||||
@@ -5,7 +5,7 @@ export function getTickToPrice(
|
||||
baseToken: Token | undefined,
|
||||
quoteToken: Token | undefined,
|
||||
tick: number | undefined
|
||||
): Price | undefined {
|
||||
): Price<Token, Token> | undefined {
|
||||
if (!baseToken || !quoteToken || !tick) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { Token, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { useSingleCallResult } from '../state/multicall/hooks'
|
||||
import { useTokenContract } from './useContract'
|
||||
|
||||
export function useTokenAllowance(token?: Token, owner?: string, spender?: string): TokenAmount | undefined {
|
||||
export function useTokenAllowance(token?: Token, owner?: string, spender?: string): CurrencyAmount<Token> | undefined {
|
||||
const contract = useTokenContract(token?.address, false)
|
||||
|
||||
const inputs = useMemo(() => [owner, spender], [owner, spender])
|
||||
const allowance = useSingleCallResult(contract, 'allowance', inputs).result
|
||||
|
||||
return useMemo(() => (token && allowance ? new TokenAmount(token, allowance.toString()) : undefined), [
|
||||
return useMemo(() => (token && allowance ? CurrencyAmount.fromRawAmount(token, allowance.toString()) : undefined), [
|
||||
token,
|
||||
allowance,
|
||||
])
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Token, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { Token, CurrencyAmount, Currency } from '@uniswap/sdk-core'
|
||||
import { useTokenContract } from './useContract'
|
||||
import { useSingleCallResult } from '../state/multicall/hooks'
|
||||
|
||||
// returns undefined if input token is undefined, or fails to get token contract,
|
||||
// or contract total supply cannot be fetched
|
||||
export function useTotalSupply(token?: Token): TokenAmount | undefined {
|
||||
const contract = useTokenContract(token?.address, false)
|
||||
export function useTotalSupply(token?: Currency): CurrencyAmount<Token> | undefined {
|
||||
const contract = useTokenContract(token?.isToken ? token.address : undefined, false)
|
||||
|
||||
const totalSupply: BigNumber = useSingleCallResult(contract, 'totalSupply')?.result?.[0]
|
||||
|
||||
return token && totalSupply ? new TokenAmount(token, totalSupply.toString()) : undefined
|
||||
return token?.isToken && totalSupply ? CurrencyAmount.fromRawAmount(token, totalSupply.toString()) : undefined
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChainId, Currency, CurrencyAmount, currencyEquals, Price, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { useMemo } from 'react'
|
||||
import { USDC } from '../constants'
|
||||
import { PairState, useV2Pairs } from './useV2Pairs'
|
||||
@@ -10,7 +10,7 @@ import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
* Returns the price in USDC of the input currency
|
||||
* @param currency currency to compute the USDC price of
|
||||
*/
|
||||
export default function useUSDCPrice(currency?: Currency): Price | undefined {
|
||||
export default function useUSDCPrice(currency?: Currency): Price<Currency, Token> | undefined {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const wrapped = wrappedCurrency(currency, chainId)
|
||||
const weth = WETH9[chainId as ChainId]
|
||||
@@ -56,7 +56,7 @@ export default function useUSDCPrice(currency?: Currency): Price | undefined {
|
||||
|
||||
const ethPairETHAmount = ethPair?.reserveOf(weth)
|
||||
const ethPairETHUSDCValue: JSBI =
|
||||
ethPairETHAmount && usdcEthPair ? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).raw : JSBI.BigInt(0)
|
||||
ethPairETHAmount && usdcEthPair ? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).quotient : JSBI.BigInt(0)
|
||||
|
||||
// all other tokens
|
||||
// first try the usdc pair
|
||||
@@ -76,7 +76,7 @@ export default function useUSDCPrice(currency?: Currency): Price | undefined {
|
||||
}, [chainId, currency, ethPair, ethPairState, usdcEthPair, usdcEthPairState, usdcPair, usdcPairState, weth, wrapped])
|
||||
}
|
||||
|
||||
export function useUSDCValue(currencyAmount: CurrencyAmount | undefined | null) {
|
||||
export function useUSDCValue(currencyAmount: CurrencyAmount<Currency> | undefined | null) {
|
||||
const price = useUSDCPrice(currencyAmount?.currency)
|
||||
|
||||
return useMemo(() => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Interface } from '@ethersproject/abi'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useMultipleContractSingleData } from '../state/multicall/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { Currency, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
|
||||
const PAIR_INTERFACE = new Interface(IUniswapV2PairABI)
|
||||
|
||||
@@ -51,7 +51,10 @@ export function useV2Pairs(currencies: [Currency | undefined, Currency | undefin
|
||||
const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
|
||||
return [
|
||||
PairState.EXISTS,
|
||||
new Pair(new TokenAmount(token0, reserve0.toString()), new TokenAmount(token1, reserve1.toString())),
|
||||
new Pair(
|
||||
CurrencyAmount.fromRawAmount(token0, reserve0.toString()),
|
||||
CurrencyAmount.fromRawAmount(token1, reserve1.toString())
|
||||
),
|
||||
]
|
||||
})
|
||||
}, [results, tokens])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { Pair, Trade } from '@uniswap/v2-sdk'
|
||||
import { useMemo } from 'react'
|
||||
import { useUserSingleHopOnly } from 'state/user/hooks'
|
||||
@@ -34,7 +34,10 @@ const MAX_HOPS = 3
|
||||
/**
|
||||
* Returns the best trade for the exact amount of tokens in to the given token out
|
||||
*/
|
||||
export function useV2TradeExactIn(currencyAmountIn?: CurrencyAmount, currencyOut?: Currency): Trade | null {
|
||||
export function useV2TradeExactIn(
|
||||
currencyAmountIn?: CurrencyAmount<Currency>,
|
||||
currencyOut?: Currency
|
||||
): Trade<Currency, Currency, TradeType.EXACT_INPUT> | null {
|
||||
const allowedPairs = useAllCommonPairs(currencyAmountIn?.currency, currencyOut)
|
||||
|
||||
const [singleHopOnly] = useUserSingleHopOnly()
|
||||
@@ -48,9 +51,9 @@ export function useV2TradeExactIn(currencyAmountIn?: CurrencyAmount, currencyOut
|
||||
)
|
||||
}
|
||||
// search through trades with varying hops, find best trade out of them
|
||||
let bestTradeSoFar: Trade | null = null
|
||||
let bestTradeSoFar: Trade<Currency, Currency, TradeType.EXACT_INPUT> | null = null
|
||||
for (let i = 1; i <= MAX_HOPS; i++) {
|
||||
const currentTrade: Trade | null =
|
||||
const currentTrade: Trade<Currency, Currency, TradeType.EXACT_INPUT> | null =
|
||||
Trade.bestTradeExactIn(allowedPairs, currencyAmountIn, currencyOut, { maxHops: i, maxNumResults: 1 })[0] ??
|
||||
null
|
||||
// if current trade is best yet, save it
|
||||
@@ -68,7 +71,10 @@ export function useV2TradeExactIn(currencyAmountIn?: CurrencyAmount, currencyOut
|
||||
/**
|
||||
* Returns the best trade for the token in to the exact amount of token out
|
||||
*/
|
||||
export function useV2TradeExactOut(currencyIn?: Currency, currencyAmountOut?: CurrencyAmount): Trade | null {
|
||||
export function useV2TradeExactOut(
|
||||
currencyIn?: Currency,
|
||||
currencyAmountOut?: CurrencyAmount<Currency>
|
||||
): Trade<Currency, Currency, TradeType.EXACT_OUTPUT> | null {
|
||||
const allowedPairs = useAllCommonPairs(currencyIn, currencyAmountOut?.currency)
|
||||
|
||||
const [singleHopOnly] = useUserSingleHopOnly()
|
||||
@@ -82,7 +88,7 @@ export function useV2TradeExactOut(currencyIn?: Currency, currencyAmountOut?: Cu
|
||||
)
|
||||
}
|
||||
// search through trades with varying hops, find best trade out of them
|
||||
let bestTradeSoFar: Trade | null = null
|
||||
let bestTradeSoFar: Trade<Currency, Currency, TradeType.EXACT_OUTPUT> | null = null
|
||||
for (let i = 1; i <= MAX_HOPS; i++) {
|
||||
const currentTrade =
|
||||
Trade.bestTradeExactOut(allowedPairs, currencyIn, currencyAmountOut, { maxHops: i, maxNumResults: 1 })[0] ??
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useSingleCallResult } from 'state/multicall/hooks'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { PositionDetails } from 'types/position'
|
||||
import { useV3NFTPositionManagerContract } from './useContract'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Pool } from '@uniswap/v3-sdk'
|
||||
import { TokenAmount } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { useBlockNumber } from 'state/application/hooks'
|
||||
|
||||
const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)
|
||||
@@ -12,26 +11,24 @@ const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)
|
||||
// compute current + counterfactual fees for a v3 position
|
||||
export function useV3PositionFees(
|
||||
pool?: Pool,
|
||||
positionDetails?: PositionDetails
|
||||
): [TokenAmount, TokenAmount] | [undefined, undefined] {
|
||||
tokenId?: BigNumber
|
||||
): [CurrencyAmount<Token>, CurrencyAmount<Token>] | [undefined, undefined] {
|
||||
const positionManager = useV3NFTPositionManagerContract(false)
|
||||
const owner = useSingleCallResult(positionDetails?.tokenId ? positionManager : null, 'ownerOf', [
|
||||
positionDetails?.tokenId,
|
||||
]).result?.[0]
|
||||
const owner = useSingleCallResult(tokenId ? positionManager : null, 'ownerOf', [tokenId]).result?.[0]
|
||||
|
||||
const tokenId = positionDetails?.tokenId?.toHexString()
|
||||
const tokenIdHexString = tokenId?.toHexString()
|
||||
const latestBlockNumber = useBlockNumber()
|
||||
|
||||
// TODO find a way to get this into multicall
|
||||
// because fees don't ever go down, we don't actually need to clear this state
|
||||
// latestBlockNumber is included to ensure data stays up-to-date fresh
|
||||
// because these amounts don't ever go down, we don't actually need to clear this state
|
||||
// latestBlockNumber is included to ensure data stays up-to-date every block
|
||||
const [amounts, setAmounts] = useState<[BigNumber, BigNumber]>()
|
||||
useEffect(() => {
|
||||
if (positionManager && tokenId && owner && typeof latestBlockNumber === 'number') {
|
||||
if (positionManager && tokenIdHexString && owner && typeof latestBlockNumber === 'number') {
|
||||
positionManager.callStatic
|
||||
.collect(
|
||||
{
|
||||
tokenId,
|
||||
tokenId: tokenIdHexString,
|
||||
recipient: owner, // some tokens might fail if transferred to address(0)
|
||||
amount0Max: MAX_UINT128,
|
||||
amount1Max: MAX_UINT128,
|
||||
@@ -42,12 +39,12 @@ export function useV3PositionFees(
|
||||
setAmounts([results.amount0, results.amount1])
|
||||
})
|
||||
}
|
||||
}, [positionManager, tokenId, owner, latestBlockNumber])
|
||||
}, [positionManager, tokenIdHexString, owner, latestBlockNumber])
|
||||
|
||||
if (pool && positionDetails && amounts) {
|
||||
if (pool && amounts) {
|
||||
return [
|
||||
new TokenAmount(pool.token0, positionDetails.tokensOwed0.add(amounts[0]).toString()),
|
||||
new TokenAmount(pool.token1, positionDetails.tokensOwed1.add(amounts[1]).toString()),
|
||||
CurrencyAmount.fromRawAmount(pool.token0, amounts[0].toString()),
|
||||
CurrencyAmount.fromRawAmount(pool.token1, amounts[1].toString()),
|
||||
]
|
||||
} else {
|
||||
return [undefined, undefined]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Currency, currencyEquals, ETHER, WETH9 } from '@uniswap/sdk-core'
|
||||
import { Currency, currencyEquals, WETH9 } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { tryParseAmount } from '../state/swap/hooks'
|
||||
import { useTransactionAdder } from '../state/transactions/hooks'
|
||||
@@ -37,14 +37,14 @@ export default function useWrapCallback(
|
||||
const hasInputAmount = Boolean(inputAmount?.greaterThan('0'))
|
||||
const sufficientBalance = inputAmount && balance && !balance.lessThan(inputAmount)
|
||||
|
||||
if (inputCurrency === ETHER && currencyEquals(WETH9[chainId], outputCurrency)) {
|
||||
if (inputCurrency.isEther && currencyEquals(WETH9[chainId], outputCurrency)) {
|
||||
return {
|
||||
wrapType: WrapType.WRAP,
|
||||
execute:
|
||||
sufficientBalance && inputAmount
|
||||
? async () => {
|
||||
try {
|
||||
const txReceipt = await wethContract.deposit({ value: `0x${inputAmount.raw.toString(16)}` })
|
||||
const txReceipt = await wethContract.deposit({ value: `0x${inputAmount.quotient.toString(16)}` })
|
||||
addTransaction(txReceipt, { summary: `Wrap ${inputAmount.toSignificant(6)} ETH to WETH` })
|
||||
} catch (error) {
|
||||
console.error('Could not deposit', error)
|
||||
@@ -53,14 +53,14 @@ export default function useWrapCallback(
|
||||
: undefined,
|
||||
inputError: sufficientBalance ? undefined : hasInputAmount ? 'Insufficient ETH balance' : 'Enter ETH amount',
|
||||
}
|
||||
} else if (currencyEquals(WETH9[chainId], inputCurrency) && outputCurrency === ETHER) {
|
||||
} else if (currencyEquals(WETH9[chainId], inputCurrency) && outputCurrency.isEther) {
|
||||
return {
|
||||
wrapType: WrapType.UNWRAP,
|
||||
execute:
|
||||
sufficientBalance && inputAmount
|
||||
? async () => {
|
||||
try {
|
||||
const txReceipt = await wethContract.withdraw(`0x${inputAmount.raw.toString(16)}`)
|
||||
const txReceipt = await wethContract.withdraw(`0x${inputAmount.quotient.toString(16)}`)
|
||||
addTransaction(txReceipt, { summary: `Unwrap ${inputAmount.toSignificant(6)} WETH to ETH` })
|
||||
} catch (error) {
|
||||
console.error('Could not withdraw', error)
|
||||
|
||||
@@ -17,7 +17,7 @@ export function PoolPriceBar({
|
||||
currencies: { [field in Field]?: Currency }
|
||||
noLiquidity?: boolean
|
||||
poolTokenPercentage?: Percent
|
||||
price?: Price
|
||||
price?: Price<Currency, Currency>
|
||||
}) {
|
||||
const theme = useContext(ThemeContext)
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Field } from '../../state/mint/v3/actions'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import Card from 'components/Card'
|
||||
import styled from 'styled-components'
|
||||
import { CurrencyAmount, Price } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import { PositionPreview } from 'components/PositionPreview'
|
||||
|
||||
@@ -26,9 +26,9 @@ export function Review({
|
||||
}: {
|
||||
position?: Position
|
||||
existingPosition?: Position
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount }
|
||||
priceLower?: Price
|
||||
priceUpper?: Price
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
priceLower?: Price<Currency, Currency>
|
||||
priceUpper?: Price<Currency, Currency>
|
||||
outOfRange: boolean
|
||||
}) {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useContext, useMemo, useState, useEffect } from 'react'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, TokenAmount, ETHER, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { WETH9 } from '@uniswap/sdk-core'
|
||||
import { AlertTriangle, AlertCircle } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
@@ -167,7 +167,7 @@ export default function AddLiquidity({
|
||||
}
|
||||
|
||||
// get the max amounts user can add
|
||||
const maxAmounts: { [field in Field]?: TokenAmount } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
const maxAmounts: { [field in Field]?: CurrencyAmount<Currency> } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
(accumulator, field) => {
|
||||
return {
|
||||
...accumulator,
|
||||
@@ -177,7 +177,7 @@ export default function AddLiquidity({
|
||||
{}
|
||||
)
|
||||
|
||||
const atMaxAmounts: { [field in Field]?: TokenAmount } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
const atMaxAmounts: { [field in Field]?: CurrencyAmount<Currency> } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
(accumulator, field) => {
|
||||
return {
|
||||
...accumulator,
|
||||
@@ -215,13 +215,13 @@ export default function AddLiquidity({
|
||||
tokenId,
|
||||
slippageTolerance: allowedSlippage,
|
||||
deadline: deadline.toString(),
|
||||
useEther: currencyA === ETHER || currencyB === ETHER,
|
||||
useEther: currencyA.isEther || currencyB.isEther,
|
||||
})
|
||||
: NonfungiblePositionManager.addCallParameters(position, {
|
||||
slippageTolerance: allowedSlippage,
|
||||
recipient: account,
|
||||
deadline: deadline.toString(),
|
||||
useEther: currencyA === ETHER || currencyB === ETHER,
|
||||
useEther: currencyA.isEther || currencyB.isEther,
|
||||
createPool: noLiquidity,
|
||||
})
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export function ConfirmAddModalBottom({
|
||||
noLiquidity?: boolean
|
||||
price?: Fraction
|
||||
currencies: { [field in Field]?: Currency }
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount }
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
poolTokenPercentage?: Percent
|
||||
onAdd: () => void
|
||||
}) {
|
||||
|
||||
@@ -17,7 +17,7 @@ export function PoolPriceBar({
|
||||
currencies: { [field in Field]?: Currency }
|
||||
noLiquidity?: boolean
|
||||
poolTokenPercentage?: Percent
|
||||
price?: Price
|
||||
price?: Price<Currency, Currency>
|
||||
}) {
|
||||
const theme = useContext(ThemeContext)
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, currencyEquals, ETHER, Percent, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, currencyEquals, Percent, WETH9 } from '@uniswap/sdk-core'
|
||||
import React, { useCallback, useContext, useState } from 'react'
|
||||
import { Plus } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
@@ -102,7 +102,7 @@ export default function AddLiquidity({
|
||||
}
|
||||
|
||||
// get the max amounts user can add
|
||||
const maxAmounts: { [field in Field]?: TokenAmount } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
const maxAmounts: { [field in Field]?: CurrencyAmount<Currency> } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
(accumulator, field) => {
|
||||
return {
|
||||
...accumulator,
|
||||
@@ -112,7 +112,7 @@ export default function AddLiquidity({
|
||||
{}
|
||||
)
|
||||
|
||||
const atMaxAmounts: { [field in Field]?: TokenAmount } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
const atMaxAmounts: { [field in Field]?: CurrencyAmount<Currency> } = [Field.CURRENCY_A, Field.CURRENCY_B].reduce(
|
||||
(accumulator, field) => {
|
||||
return {
|
||||
...accumulator,
|
||||
@@ -147,27 +147,27 @@ export default function AddLiquidity({
|
||||
method: (...args: any) => Promise<TransactionResponse>,
|
||||
args: Array<string | string[] | number>,
|
||||
value: BigNumber | null
|
||||
if (currencyA === ETHER || currencyB === ETHER) {
|
||||
const tokenBIsETH = currencyB === ETHER
|
||||
if (currencyA.isEther || currencyB.isEther) {
|
||||
const tokenBIsETH = currencyB.isEther
|
||||
estimate = router.estimateGas.addLiquidityETH
|
||||
method = router.addLiquidityETH
|
||||
args = [
|
||||
wrappedCurrency(tokenBIsETH ? currencyA : currencyB, chainId)?.address ?? '', // token
|
||||
(tokenBIsETH ? parsedAmountA : parsedAmountB).raw.toString(), // token desired
|
||||
(tokenBIsETH ? parsedAmountA : parsedAmountB).quotient.toString(), // token desired
|
||||
amountsMin[tokenBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B].toString(), // token min
|
||||
amountsMin[tokenBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A].toString(), // eth min
|
||||
account,
|
||||
deadline.toHexString(),
|
||||
]
|
||||
value = BigNumber.from((tokenBIsETH ? parsedAmountB : parsedAmountA).raw.toString())
|
||||
value = BigNumber.from((tokenBIsETH ? parsedAmountB : parsedAmountA).quotient.toString())
|
||||
} else {
|
||||
estimate = router.estimateGas.addLiquidity
|
||||
method = router.addLiquidity
|
||||
args = [
|
||||
wrappedCurrency(currencyA, chainId)?.address ?? '',
|
||||
wrappedCurrency(currencyB, chainId)?.address ?? '',
|
||||
parsedAmountA.raw.toString(),
|
||||
parsedAmountB.raw.toString(),
|
||||
parsedAmountA.quotient.toString(),
|
||||
parsedAmountB.quotient.toString(),
|
||||
amountsMin[Field.CURRENCY_A].toString(),
|
||||
amountsMin[Field.CURRENCY_B].toString(),
|
||||
account,
|
||||
|
||||
@@ -5,7 +5,6 @@ import GoogleAnalyticsReporter from '../components/analytics/GoogleAnalyticsRepo
|
||||
import AddressClaimModal from '../components/claim/AddressClaimModal'
|
||||
import Header from '../components/Header'
|
||||
import Polling from '../components/Header/Polling'
|
||||
// import URLWarning from '../components/Header/URLWarning'
|
||||
import Popups from '../components/Popups'
|
||||
import Web3ReactManager from '../components/Web3ReactManager'
|
||||
import ErrorBoundary from '../components/ErrorBoundary'
|
||||
|
||||
@@ -2,9 +2,8 @@ import React, { useCallback, useState } from 'react'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import styled from 'styled-components'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import { TokenAmount, ETHER } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { RouteComponentProps } from 'react-router-dom'
|
||||
import DoubleCurrencyLogo from '../../components/DoubleLogo'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
@@ -104,7 +103,7 @@ export default function Manage({
|
||||
const stakingInfo = useStakingInfo(stakingTokenPair)?.[0]
|
||||
|
||||
// detect existing unstaked LP position to show add button if none found
|
||||
const userLiquidityUnstaked = useTokenBalance(account ?? undefined, stakingInfo?.stakedAmount?.token)
|
||||
const userLiquidityUnstaked = useTokenBalance(account ?? undefined, stakingInfo?.stakedAmount?.currency)
|
||||
const showAddLiquidityButton = Boolean(stakingInfo?.stakedAmount?.equalTo('0') && userLiquidityUnstaked?.equalTo('0'))
|
||||
|
||||
// toggle for staking modal and unstaking modal
|
||||
@@ -115,23 +114,23 @@ export default function Manage({
|
||||
// fade cards if nothing staked or nothing earned yet
|
||||
const disableTop = !stakingInfo?.stakedAmount || stakingInfo.stakedAmount.equalTo(JSBI.BigInt(0))
|
||||
|
||||
const token = currencyA === ETHER ? tokenB : tokenA
|
||||
const WETH = currencyA === ETHER ? tokenA : tokenB
|
||||
const token = currencyA?.isEther ? tokenB : tokenA
|
||||
const WETH = currencyA?.isEther ? tokenA : tokenB
|
||||
const backgroundColor = useColor(token)
|
||||
|
||||
// get WETH value of staked LP tokens
|
||||
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo?.stakedAmount?.token)
|
||||
let valueOfTotalStakedAmountInWETH: TokenAmount | undefined
|
||||
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo?.stakedAmount?.currency)
|
||||
let valueOfTotalStakedAmountInWETH: CurrencyAmount<Token> | undefined
|
||||
if (totalSupplyOfStakingToken && stakingTokenPair && stakingInfo && WETH) {
|
||||
// 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
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -269,7 +268,7 @@ export default function Manage({
|
||||
<div>
|
||||
<TYPE.black>Your unclaimed UNI</TYPE.black>
|
||||
</div>
|
||||
{stakingInfo?.earnedAmount && JSBI.notEqual(BIG_INT_ZERO, stakingInfo?.earnedAmount?.raw) && (
|
||||
{stakingInfo?.earnedAmount && JSBI.notEqual(BIG_INT_ZERO, stakingInfo?.earnedAmount?.quotient) && (
|
||||
<ButtonEmpty
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import JSBI from 'jsbi'
|
||||
import React from 'react'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import styled from 'styled-components'
|
||||
@@ -9,7 +10,6 @@ import { CardSection, DataCard, CardNoise, CardBGImage } from '../../components/
|
||||
import { Countdown } from './Countdown'
|
||||
import Loader from '../../components/Loader'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import { BIG_INT_ZERO } from '../../constants'
|
||||
import { OutlineCard } from '../../components/Card'
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function Earn() {
|
||||
* only show staking cards with balance
|
||||
* @todo only account for this if rewards are inactive
|
||||
*/
|
||||
const stakingInfosWithBalance = stakingInfos?.filter((s) => JSBI.greaterThan(s.stakedAmount.raw, BIG_INT_ZERO))
|
||||
const stakingInfosWithBalance = stakingInfos?.filter((s) => JSBI.greaterThan(s.stakedAmount.quotient, BIG_INT_ZERO))
|
||||
|
||||
// toggle copy if rewards are inactive
|
||||
const stakingRewardsExist = Boolean(typeof chainId === 'number' && (STAKING_REWARDS_INFO[chainId]?.length ?? 0) > 0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import JSBI from 'jsbi'
|
||||
import React, { useCallback, useMemo, useState, useEffect } from 'react'
|
||||
import { Fraction, Percent, Price, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
||||
import { FACTORY_ADDRESS, JSBI } from '@uniswap/v2-sdk'
|
||||
import { Fraction, Percent, Price, Token, CurrencyAmount, WETH9 } from '@uniswap/sdk-core'
|
||||
import { FACTORY_ADDRESS } from '@uniswap/v2-sdk'
|
||||
import { Redirect, RouteComponentProps } from 'react-router'
|
||||
import { Text } from 'rebass'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
@@ -59,9 +60,15 @@ function EmptyState({ message }: { message: string }) {
|
||||
)
|
||||
}
|
||||
|
||||
function LiquidityInfo({ token0Amount, token1Amount }: { token0Amount: TokenAmount; token1Amount: TokenAmount }) {
|
||||
const currency0 = unwrappedToken(token0Amount.token)
|
||||
const currency1 = unwrappedToken(token1Amount.token)
|
||||
function LiquidityInfo({
|
||||
token0Amount,
|
||||
token1Amount,
|
||||
}: {
|
||||
token0Amount: CurrencyAmount<Token>
|
||||
token1Amount: CurrencyAmount<Token>
|
||||
}) {
|
||||
const currency0 = unwrappedToken(token0Amount.currency)
|
||||
const currency1 = unwrappedToken(token1Amount.currency)
|
||||
|
||||
return (
|
||||
<AutoColumn gap="8px">
|
||||
@@ -105,10 +112,10 @@ function V2PairMigration({
|
||||
token1,
|
||||
}: {
|
||||
pair: Contract
|
||||
pairBalance: TokenAmount
|
||||
totalSupply: TokenAmount
|
||||
reserve0: TokenAmount
|
||||
reserve1: TokenAmount
|
||||
pairBalance: CurrencyAmount<Token>
|
||||
totalSupply: CurrencyAmount<Token>
|
||||
reserve0: CurrencyAmount<Token>
|
||||
reserve1: CurrencyAmount<Token>
|
||||
token0: Token
|
||||
token1: Token
|
||||
}) {
|
||||
@@ -128,11 +135,19 @@ function V2PairMigration({
|
||||
|
||||
// this is just getLiquidityValue with the fee off, but for the passed pair
|
||||
const token0Value = useMemo(
|
||||
() => new TokenAmount(token0, JSBI.divide(JSBI.multiply(pairBalance.raw, reserve0.raw), totalSupply.raw)),
|
||||
() =>
|
||||
CurrencyAmount.fromRawAmount(
|
||||
token0,
|
||||
JSBI.divide(JSBI.multiply(pairBalance.quotient, reserve0.quotient), totalSupply.quotient)
|
||||
),
|
||||
[token0, pairBalance, reserve0, totalSupply]
|
||||
)
|
||||
const token1Value = useMemo(
|
||||
() => new TokenAmount(token1, JSBI.divide(JSBI.multiply(pairBalance.raw, reserve1.raw), totalSupply.raw)),
|
||||
() =>
|
||||
CurrencyAmount.fromRawAmount(
|
||||
token1,
|
||||
JSBI.divide(JSBI.multiply(pairBalance.quotient, reserve1.quotient), totalSupply.quotient)
|
||||
),
|
||||
[token1, pairBalance, reserve1, totalSupply]
|
||||
)
|
||||
|
||||
@@ -142,7 +157,7 @@ function V2PairMigration({
|
||||
const noLiquidity = poolState === PoolState.NOT_EXISTS
|
||||
|
||||
// get spot prices + price difference
|
||||
const v2SpotPrice = useMemo(() => new Price(token0, token1, reserve0.raw, reserve1.raw), [
|
||||
const v2SpotPrice = useMemo(() => new Price(token0, token1, reserve0.quotient, reserve1.quotient), [
|
||||
token0,
|
||||
token1,
|
||||
reserve0,
|
||||
@@ -191,18 +206,18 @@ function V2PairMigration({
|
||||
pool: pool ?? new Pool(token0, token1, feeAmount, sqrtPrice, 0, tick, []),
|
||||
tickLower,
|
||||
tickUpper,
|
||||
amount0: token0Value.raw,
|
||||
amount1: token1Value.raw,
|
||||
amount0: token0Value.quotient,
|
||||
amount1: token1Value.quotient,
|
||||
})
|
||||
: undefined
|
||||
|
||||
const v3Amount0Min = useMemo(
|
||||
() =>
|
||||
position &&
|
||||
new TokenAmount(
|
||||
CurrencyAmount.fromRawAmount(
|
||||
token0,
|
||||
JSBI.divide(
|
||||
JSBI.multiply(position.amount0.raw, JSBI.BigInt(10000 - JSBI.toNumber(allowedSlippage.numerator))),
|
||||
JSBI.multiply(position.amount0.quotient, JSBI.BigInt(10000 - JSBI.toNumber(allowedSlippage.numerator))),
|
||||
JSBI.BigInt(10000)
|
||||
)
|
||||
),
|
||||
@@ -211,10 +226,10 @@ function V2PairMigration({
|
||||
const v3Amount1Min = useMemo(
|
||||
() =>
|
||||
position &&
|
||||
new TokenAmount(
|
||||
CurrencyAmount.fromRawAmount(
|
||||
token1,
|
||||
JSBI.divide(
|
||||
JSBI.multiply(position.amount1.raw, JSBI.BigInt(10000 - JSBI.toNumber(allowedSlippage.numerator))),
|
||||
JSBI.multiply(position.amount1.quotient, JSBI.BigInt(10000 - JSBI.toNumber(allowedSlippage.numerator))),
|
||||
JSBI.BigInt(10000)
|
||||
)
|
||||
),
|
||||
@@ -222,11 +237,13 @@ function V2PairMigration({
|
||||
)
|
||||
|
||||
const refund0 = useMemo(
|
||||
() => position && new TokenAmount(token0, JSBI.subtract(token0Value.raw, position.amount0.raw)),
|
||||
() =>
|
||||
position && CurrencyAmount.fromRawAmount(token0, JSBI.subtract(token0Value.quotient, position.amount0.quotient)),
|
||||
[token0Value, position, token0]
|
||||
)
|
||||
const refund1 = useMemo(
|
||||
() => position && new TokenAmount(token1, JSBI.subtract(token1Value.raw, position.amount1.raw)),
|
||||
() =>
|
||||
position && CurrencyAmount.fromRawAmount(token1, JSBI.subtract(token1Value.quotient, position.amount1.quotient)),
|
||||
[token1Value, position, token1]
|
||||
)
|
||||
|
||||
@@ -283,7 +300,7 @@ function V2PairMigration({
|
||||
data.push(
|
||||
migrator.interface.encodeFunctionData('selfPermit', [
|
||||
pair.address,
|
||||
`0x${pairBalance.raw.toString(16)}`,
|
||||
`0x${pairBalance.quotient.toString(16)}`,
|
||||
deadlineToUse,
|
||||
signatureData.v,
|
||||
signatureData.r,
|
||||
@@ -309,15 +326,15 @@ function V2PairMigration({
|
||||
migrator.interface.encodeFunctionData('migrate', [
|
||||
{
|
||||
pair: pair.address,
|
||||
liquidityToMigrate: `0x${pairBalance.raw.toString(16)}`,
|
||||
liquidityToMigrate: `0x${pairBalance.quotient.toString(16)}`,
|
||||
percentageToMigrate,
|
||||
token0: token0.address,
|
||||
token1: token1.address,
|
||||
fee: feeAmount,
|
||||
tickLower,
|
||||
tickUpper,
|
||||
amount0Min: `0x${v3Amount0Min.raw.toString(16)}`,
|
||||
amount1Min: `0x${v3Amount1Min.raw.toString(16)}`,
|
||||
amount0Min: `0x${v3Amount0Min.quotient.toString(16)}`,
|
||||
amount1Min: `0x${v3Amount1Min.quotient.toString(16)}`,
|
||||
recipient: account,
|
||||
deadline: deadlineToUse,
|
||||
refundAsETH: true, // hard-code this for now
|
||||
@@ -371,7 +388,7 @@ function V2PairMigration({
|
||||
currency1,
|
||||
])
|
||||
|
||||
const isSuccessfullyMigrated = !!pendingMigrationHash && JSBI.equal(pairBalance.raw, ZERO)
|
||||
const isSuccessfullyMigrated = !!pendingMigrationHash && JSBI.equal(pairBalance.quotient, ZERO)
|
||||
|
||||
return (
|
||||
<AutoColumn gap="20px">
|
||||
@@ -646,14 +663,14 @@ export default function MigrateV2Pair({
|
||||
const pairBalance = useTokenBalance(account ?? undefined, liquidityToken)
|
||||
const totalSupply = useTotalSupply(liquidityToken)
|
||||
const [reserve0Raw, reserve1Raw] = useSingleCallResult(pair, 'getReserves')?.result ?? []
|
||||
const reserve0 = useMemo(() => (token0 && reserve0Raw ? new TokenAmount(token0, reserve0Raw) : undefined), [
|
||||
token0,
|
||||
reserve0Raw,
|
||||
])
|
||||
const reserve1 = useMemo(() => (token1 && reserve1Raw ? new TokenAmount(token1, reserve1Raw) : undefined), [
|
||||
token1,
|
||||
reserve1Raw,
|
||||
])
|
||||
const reserve0 = useMemo(
|
||||
() => (token0 && reserve0Raw ? CurrencyAmount.fromRawAmount(token0, reserve0Raw) : undefined),
|
||||
[token0, reserve0Raw]
|
||||
)
|
||||
const reserve1 = useMemo(
|
||||
() => (token1 && reserve1Raw ? CurrencyAmount.fromRawAmount(token1, reserve1Raw) : undefined),
|
||||
[token1, reserve1Raw]
|
||||
)
|
||||
|
||||
// redirect for invalid url params
|
||||
if (
|
||||
|
||||
@@ -109,6 +109,7 @@ const ResponsiveColumn = styled(AutoColumn)`
|
||||
`
|
||||
|
||||
const StyledImage = styled.img`
|
||||
height: 114px;
|
||||
margin-top: -28px;
|
||||
${({ theme }) => theme.mediaWidth.upToMedium`
|
||||
height: 80px;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import React, { SyntheticEvent, useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
||||
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
@@ -23,7 +23,7 @@ import { currencyId } from 'utils/currencyId'
|
||||
import { formatTokenAmount } from 'utils/formatTokenAmount'
|
||||
import { useV3PositionFees } from 'hooks/useV3PositionFees'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { WETH9, Currency, CurrencyAmount, Percent, Fraction, Price } from '@uniswap/sdk-core'
|
||||
import { Token, WETH9, Currency, CurrencyAmount, Percent, Fraction, Price, currencyEquals } from '@uniswap/sdk-core'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
@@ -126,6 +126,23 @@ const ResponsiveButtonPrimary = styled(ButtonPrimary)`
|
||||
`};
|
||||
`
|
||||
|
||||
const NFTGrid = styled.div`
|
||||
display: grid;
|
||||
grid-template: 'overlap';
|
||||
min-height: 400px;
|
||||
`
|
||||
|
||||
const NFTCanvas = styled.canvas`
|
||||
grid-area: overlap;
|
||||
`
|
||||
|
||||
const NFTImage = styled.img`
|
||||
grid-area: overlap;
|
||||
height: 400px;
|
||||
/* Ensures SVG appears on top of canvas. */
|
||||
z-index: 1;
|
||||
`
|
||||
|
||||
function CurrentPriceCard({
|
||||
inverted,
|
||||
pool,
|
||||
@@ -155,7 +172,11 @@ function CurrentPriceCard({
|
||||
)
|
||||
}
|
||||
|
||||
function getRatio(lower: Price, current: Price, upper: Price) {
|
||||
function getRatio(
|
||||
lower: Price<Currency, Currency>,
|
||||
current: Price<Currency, Currency>,
|
||||
upper: Price<Currency, Currency>
|
||||
) {
|
||||
try {
|
||||
if (!current.greaterThan(lower)) {
|
||||
return 100
|
||||
@@ -179,6 +200,50 @@ function getRatio(lower: Price, current: Price, upper: Price) {
|
||||
}
|
||||
}
|
||||
|
||||
function NFT({ image, height: targetHeight }: { image: string; height: number }) {
|
||||
const [animate, setAnimate] = useState(false)
|
||||
|
||||
const canvasRef = useRef<HTMLCanvasElement>()
|
||||
const imageRef = useRef<HTMLImageElement>()
|
||||
|
||||
const getSnapshot = (src: HTMLImageElement) => {
|
||||
if (!canvasRef.current) return
|
||||
|
||||
const { current: canvas } = canvasRef
|
||||
const context = canvas.getContext('2d')
|
||||
|
||||
if (!context) return
|
||||
|
||||
let { width, height } = src
|
||||
|
||||
// src may be hidden and not have the target dimensions
|
||||
const ratio = width / height
|
||||
height = targetHeight
|
||||
width = Math.round(ratio * targetHeight)
|
||||
|
||||
// Ensure crispness at high DPIs
|
||||
canvas.width = width * devicePixelRatio
|
||||
canvas.height = height * devicePixelRatio
|
||||
canvas.style.width = width + 'px'
|
||||
canvas.style.height = height + 'px'
|
||||
context.scale(devicePixelRatio, devicePixelRatio)
|
||||
|
||||
context.clearRect(0, 0, width, height)
|
||||
context.drawImage(src, 0, 0, width, height)
|
||||
}
|
||||
|
||||
const onLoad = (e: SyntheticEvent<HTMLImageElement>) => {
|
||||
getSnapshot(e.target as HTMLImageElement)
|
||||
}
|
||||
|
||||
return (
|
||||
<NFTGrid onMouseEnter={() => setAnimate(true)} onMouseLeave={() => setAnimate(false)}>
|
||||
<NFTCanvas ref={canvasRef as any} />
|
||||
<NFTImage src={image} hidden={!animate} onLoad={onLoad} ref={imageRef as any} />
|
||||
</NFTGrid>
|
||||
)
|
||||
}
|
||||
|
||||
export function PositionPage({
|
||||
match: {
|
||||
params: { tokenId: tokenIdFromUrl },
|
||||
@@ -239,7 +304,7 @@ export function PositionPage({
|
||||
}, [inverted, pool, priceLower, priceUpper])
|
||||
|
||||
// fees
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails)
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails?.tokenId)
|
||||
|
||||
const [collecting, setCollecting] = useState<boolean>(false)
|
||||
const [collectMigrationHash, setCollectMigrationHash] = useState<string | null>(null)
|
||||
@@ -255,8 +320,12 @@ export function PositionPage({
|
||||
|
||||
const { calldata, value } = NonfungiblePositionManager.collectCallParameters({
|
||||
tokenId: tokenId.toString(),
|
||||
expectedCurrencyOwed0: feeValue0.token.equals(WETH9[chainId]) ? CurrencyAmount.ether(feeValue0.raw) : feeValue0,
|
||||
expectedCurrencyOwed1: feeValue1.token.equals(WETH9[chainId]) ? CurrencyAmount.ether(feeValue1.raw) : feeValue1,
|
||||
expectedCurrencyOwed0: currencyEquals(feeValue0.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue0.quotient)
|
||||
: feeValue0,
|
||||
expectedCurrencyOwed1: currencyEquals(feeValue1.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue1.quotient)
|
||||
: feeValue1,
|
||||
recipient: account,
|
||||
})
|
||||
|
||||
@@ -285,11 +354,11 @@ export function PositionPage({
|
||||
ReactGA.event({
|
||||
category: 'Liquidity',
|
||||
action: 'CollectV3',
|
||||
label: [feeValue0.token.symbol, feeValue1.token.symbol].join('/'),
|
||||
label: [feeValue0.currency.symbol, feeValue1.currency.symbol].join('/'),
|
||||
})
|
||||
|
||||
addTransaction(response, {
|
||||
summary: `Collect ${feeValue0.token.symbol}/${feeValue1.token.symbol} fees`,
|
||||
summary: `Collect ${feeValue0.currency.symbol}/${feeValue1.currency.symbol} fees`,
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -305,14 +374,14 @@ export function PositionPage({
|
||||
const price0 = useUSDCPrice(token0 ?? undefined)
|
||||
const price1 = useUSDCPrice(token1 ?? undefined)
|
||||
|
||||
const fiatValueOfFees: CurrencyAmount | null = useMemo(() => {
|
||||
const fiatValueOfFees: CurrencyAmount<Token> | null = useMemo(() => {
|
||||
if (!price0 || !price1 || !feeValue0 || !feeValue1) return null
|
||||
const amount0 = price0.quote(feeValue0)
|
||||
const amount1 = price1.quote(feeValue1)
|
||||
return amount0.add(amount1)
|
||||
}, [price0, price1, feeValue0, feeValue1])
|
||||
|
||||
const fiatValueOfLiquidity: CurrencyAmount | null = useMemo(() => {
|
||||
const fiatValueOfLiquidity: CurrencyAmount<Token> | null = useMemo(() => {
|
||||
if (!price0 || !price1 || !position) return null
|
||||
const amount0 = price0.quote(position.amount0)
|
||||
const amount1 = price1.quote(position.amount1)
|
||||
@@ -453,7 +522,7 @@ export function PositionPage({
|
||||
}}
|
||||
>
|
||||
<div style={{ marginRight: 12 }}>
|
||||
<img height="400px" src={metadata.result.image} />
|
||||
<NFT image={metadata.result.image} height={400} />
|
||||
</div>
|
||||
{typeof chainId === 'number' && owner && !ownsNFT ? (
|
||||
<ExternalLink href={getEtherscanLink(chainId, owner, 'address')}>Owner</ExternalLink>
|
||||
|
||||
@@ -110,7 +110,9 @@ export default function Pool() {
|
||||
|
||||
// show liquidity even if its deposited in rewards contract
|
||||
const stakingInfo = useStakingInfo()
|
||||
const stakingInfosWithBalance = stakingInfo?.filter((pool) => JSBI.greaterThan(pool.stakedAmount.raw, BIG_INT_ZERO))
|
||||
const stakingInfosWithBalance = stakingInfo?.filter((pool) =>
|
||||
JSBI.greaterThan(pool.stakedAmount.quotient, BIG_INT_ZERO)
|
||||
)
|
||||
const stakingPairs = useV2Pairs(stakingInfosWithBalance?.map((stakingInfo) => stakingInfo.tokens))
|
||||
|
||||
// remove any pairs that also are included in pairs with stake in mining pool
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Currency, ETHER, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import { Currency, ETHER, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { Plus } from 'react-feather'
|
||||
import { Text } from 'rebass'
|
||||
@@ -56,12 +56,12 @@ export default function PoolFinder() {
|
||||
Boolean(
|
||||
pairState === PairState.EXISTS &&
|
||||
pair &&
|
||||
JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0)) &&
|
||||
JSBI.equal(pair.reserve1.raw, JSBI.BigInt(0))
|
||||
JSBI.equal(pair.reserve0.quotient, JSBI.BigInt(0)) &&
|
||||
JSBI.equal(pair.reserve1.quotient, JSBI.BigInt(0))
|
||||
)
|
||||
|
||||
const position: TokenAmount | undefined = useTokenBalance(account ?? undefined, pair?.liquidityToken)
|
||||
const hasPosition = Boolean(position && JSBI.greaterThan(position.raw, JSBI.BigInt(0)))
|
||||
const position: CurrencyAmount<Token> | undefined = useTokenBalance(account ?? undefined, pair?.liquidityToken)
|
||||
const hasPosition = Boolean(position && JSBI.greaterThan(position.quotient, JSBI.BigInt(0)))
|
||||
|
||||
const handleCurrencySelect = useCallback(
|
||||
(currency: Currency) => {
|
||||
|
||||
@@ -21,7 +21,7 @@ import ReactGA from 'react-ga'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from 'state/transactions/hooks'
|
||||
import { WETH9, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { WETH9, CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { TYPE } from 'theme'
|
||||
import { Wrapper, SmallMaxButton, ResponsiveHeaderText } from './styled'
|
||||
import Loader from 'components/Loader'
|
||||
@@ -122,11 +122,11 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
slippageTolerance: allowedSlippage,
|
||||
deadline: deadline.toString(),
|
||||
collectOptions: {
|
||||
expectedCurrencyOwed0: liquidityValue0.token.equals(WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue0.raw)
|
||||
expectedCurrencyOwed0: currencyEquals(liquidityValue0.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue0.quotient)
|
||||
: feeValue0,
|
||||
expectedCurrencyOwed1: liquidityValue1.token.equals(WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue1.raw)
|
||||
expectedCurrencyOwed1: currencyEquals(liquidityValue1.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue1.quotient)
|
||||
: feeValue1,
|
||||
recipient: account,
|
||||
},
|
||||
@@ -154,12 +154,12 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
ReactGA.event({
|
||||
category: 'Liquidity',
|
||||
action: 'RemoveV3',
|
||||
label: [liquidityValue0.token.symbol, liquidityValue1.token.symbol].join('/'),
|
||||
label: [liquidityValue0.currency.symbol, liquidityValue1.currency.symbol].join('/'),
|
||||
})
|
||||
setTxnHash(response.hash)
|
||||
setAttemptingTxn(false)
|
||||
addTransaction(response, {
|
||||
summary: `Remove ${liquidityValue0.token.symbol}/${liquidityValue1.token.symbol} V3 liquidity`,
|
||||
summary: `Remove ${liquidityValue0.currency.symbol}/${liquidityValue1.currency.symbol} V3 liquidity`,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, currencyEquals, ETHER, Percent, WETH9 } from '@uniswap/sdk-core'
|
||||
import { Currency, currencyEquals, Percent, WETH9 } from '@uniswap/sdk-core'
|
||||
import React, { useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { ArrowDown, Plus } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
@@ -163,8 +163,8 @@ export default function RemoveLiquidity({
|
||||
const liquidityAmount = parsedAmounts[Field.LIQUIDITY]
|
||||
if (!liquidityAmount) throw new Error('missing liquidity amount')
|
||||
|
||||
const currencyBIsETH = currencyB === ETHER
|
||||
const oneCurrencyIsETH = currencyA === ETHER || currencyBIsETH
|
||||
const currencyBIsETH = currencyB.isEther
|
||||
const oneCurrencyIsETH = currencyA.isEther || currencyBIsETH
|
||||
|
||||
if (!tokenA || !tokenB) throw new Error('could not wrap')
|
||||
|
||||
@@ -176,7 +176,7 @@ export default function RemoveLiquidity({
|
||||
methodNames = ['removeLiquidityETH', 'removeLiquidityETHSupportingFeeOnTransferTokens']
|
||||
args = [
|
||||
currencyBIsETH ? tokenA.address : tokenB.address,
|
||||
liquidityAmount.raw.toString(),
|
||||
liquidityAmount.quotient.toString(),
|
||||
amountsMin[currencyBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B].toString(),
|
||||
amountsMin[currencyBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A].toString(),
|
||||
account,
|
||||
@@ -189,7 +189,7 @@ export default function RemoveLiquidity({
|
||||
args = [
|
||||
tokenA.address,
|
||||
tokenB.address,
|
||||
liquidityAmount.raw.toString(),
|
||||
liquidityAmount.quotient.toString(),
|
||||
amountsMin[Field.CURRENCY_A].toString(),
|
||||
amountsMin[Field.CURRENCY_B].toString(),
|
||||
account,
|
||||
@@ -204,7 +204,7 @@ export default function RemoveLiquidity({
|
||||
methodNames = ['removeLiquidityETHWithPermit', 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens']
|
||||
args = [
|
||||
currencyBIsETH ? tokenA.address : tokenB.address,
|
||||
liquidityAmount.raw.toString(),
|
||||
liquidityAmount.quotient.toString(),
|
||||
amountsMin[currencyBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B].toString(),
|
||||
amountsMin[currencyBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A].toString(),
|
||||
account,
|
||||
@@ -221,7 +221,7 @@ export default function RemoveLiquidity({
|
||||
args = [
|
||||
tokenA.address,
|
||||
tokenB.address,
|
||||
liquidityAmount.raw.toString(),
|
||||
liquidityAmount.quotient.toString(),
|
||||
amountsMin[Field.CURRENCY_A].toString(),
|
||||
amountsMin[Field.CURRENCY_B].toString(),
|
||||
account,
|
||||
@@ -383,7 +383,7 @@ export default function RemoveLiquidity({
|
||||
[onUserInput]
|
||||
)
|
||||
|
||||
const oneCurrencyIsETH = currencyA === ETHER || currencyB === ETHER
|
||||
const oneCurrencyIsETH = currencyA?.isEther || currencyB?.isEther
|
||||
const oneCurrencyIsWETH = Boolean(
|
||||
chainId &&
|
||||
((currencyA && currencyEquals(WETH9[chainId], currencyA)) ||
|
||||
@@ -526,8 +526,8 @@ export default function RemoveLiquidity({
|
||||
<RowBetween style={{ justifyContent: 'flex-end' }}>
|
||||
{oneCurrencyIsETH ? (
|
||||
<StyledInternalLink
|
||||
to={`/remove/v2/${currencyA === ETHER ? WETH9[chainId].address : currencyIdA}/${
|
||||
currencyB === ETHER ? WETH9[chainId].address : currencyIdB
|
||||
to={`/remove/v2/${currencyA?.isEther ? WETH9[chainId].address : currencyIdA}/${
|
||||
currencyB?.isEther ? WETH9[chainId].address : currencyIdB
|
||||
}`}
|
||||
>
|
||||
Receive WETH
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { AdvancedSwapDetails } from 'components/swap/AdvancedSwapDetails'
|
||||
@@ -76,7 +76,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
]
|
||||
const [dismissTokenWarning, setDismissTokenWarning] = useState<boolean>(false)
|
||||
const urlLoadedTokens: Token[] = useMemo(
|
||||
() => [loadedInputCurrency, loadedOutputCurrency]?.filter((c): c is Token => c instanceof Token) ?? [],
|
||||
() => [loadedInputCurrency, loadedOutputCurrency]?.filter((c): c is Token => c?.isToken ?? false) ?? [],
|
||||
[loadedInputCurrency, loadedOutputCurrency]
|
||||
)
|
||||
const handleConfirmTokenWarning = useCallback(() => {
|
||||
@@ -168,7 +168,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
// modal and loading
|
||||
const [{ showConfirm, tradeToConfirm, swapErrorMessage, attemptingTxn, txHash }, setSwapState] = useState<{
|
||||
showConfirm: boolean
|
||||
tradeToConfirm: V2Trade | V3Trade | undefined
|
||||
tradeToConfirm: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
|
||||
attemptingTxn: boolean
|
||||
swapErrorMessage: string | undefined
|
||||
txHash: string | undefined
|
||||
@@ -225,7 +225,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
}
|
||||
}, [approvalState, approvalSubmitted])
|
||||
|
||||
const maxInputAmount: CurrencyAmount | undefined = maxAmountSpend(currencyBalances[Field.INPUT])
|
||||
const maxInputAmount: CurrencyAmount<Currency> | undefined = maxAmountSpend(currencyBalances[Field.INPUT])
|
||||
const showMaxButton = Boolean(maxInputAmount?.greaterThan(0) && !parsedAmounts[Field.INPUT]?.equalTo(maxInputAmount))
|
||||
|
||||
// the callback to execute the swap
|
||||
|
||||
@@ -19,8 +19,8 @@ import {
|
||||
import { DateTime } from 'luxon'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import VoteModal from '../../components/vote/VoteModal'
|
||||
import { TokenAmount } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { AVERAGE_BLOCK_TIME_IN_SECS, COMMON_CONTRACT_NAMES, UNI, ZERO_ADDRESS } from '../../constants'
|
||||
import { getEtherscanLink, isAddress } from '../../utils'
|
||||
@@ -152,21 +152,24 @@ export default function VotePage({
|
||||
proposalData && totalVotes ? ((proposalData.againstCount * 100) / totalVotes).toFixed(0) + '%' : '0%'
|
||||
|
||||
// only count available votes as of the proposal start block
|
||||
const availableVotes: TokenAmount | undefined = useUserVotesAsOfBlock(proposalData?.startBlock ?? undefined)
|
||||
const availableVotes: CurrencyAmount<Token> | undefined = useUserVotesAsOfBlock(proposalData?.startBlock ?? undefined)
|
||||
|
||||
// only show voting if user has > 0 votes at proposal start block and proposal is active,
|
||||
const showVotingButtons =
|
||||
availableVotes &&
|
||||
JSBI.greaterThan(availableVotes.raw, JSBI.BigInt(0)) &&
|
||||
JSBI.greaterThan(availableVotes.quotient, JSBI.BigInt(0)) &&
|
||||
proposalData &&
|
||||
proposalData.status === ProposalState.Active
|
||||
|
||||
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, chainId ? UNI[chainId] : undefined)
|
||||
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(
|
||||
account ?? undefined,
|
||||
chainId ? UNI[chainId] : undefined
|
||||
)
|
||||
const userDelegatee: string | undefined = useUserDelegatee()
|
||||
|
||||
// in blurb link to home page if they are able to unlock
|
||||
const showLinkForUnlock = Boolean(
|
||||
uniBalance && JSBI.notEqual(uniBalance.raw, JSBI.BigInt(0)) && userDelegatee === ZERO_ADDRESS
|
||||
uniBalance && JSBI.notEqual(uniBalance.quotient, JSBI.BigInt(0)) && userDelegatee === ZERO_ADDRESS
|
||||
)
|
||||
|
||||
// show links in propsoal details if content is an address
|
||||
|
||||
@@ -20,8 +20,8 @@ import DelegateModal from '../../components/vote/DelegateModal'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { UNI, ZERO_ADDRESS } from '../../constants'
|
||||
import { TokenAmount, ChainId } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import { Token, CurrencyAmount, ChainId } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { shortenAddress, getEtherscanLink } from '../../utils'
|
||||
import Loader from '../../components/Loader'
|
||||
import FormattedCurrencyAmount from '../../components/FormattedCurrencyAmount'
|
||||
@@ -119,13 +119,16 @@ export default function Vote() {
|
||||
const allProposals: ProposalData[] = useAllProposalData()
|
||||
|
||||
// user data
|
||||
const availableVotes: TokenAmount | undefined = useUserVotes()
|
||||
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, chainId ? UNI[chainId] : undefined)
|
||||
const availableVotes: CurrencyAmount<Token> | undefined = useUserVotes()
|
||||
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(
|
||||
account ?? undefined,
|
||||
chainId ? UNI[chainId] : undefined
|
||||
)
|
||||
const userDelegatee: string | undefined = useUserDelegatee()
|
||||
|
||||
// show delegation option if they have have a balance, but have not delegated
|
||||
const showUnlockVoting = Boolean(
|
||||
uniBalance && JSBI.notEqual(uniBalance.raw, JSBI.BigInt(0)) && userDelegatee === ZERO_ADDRESS
|
||||
uniBalance && JSBI.notEqual(uniBalance.quotient, JSBI.BigInt(0)) && userDelegatee === ZERO_ADDRESS
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -176,14 +179,14 @@ export default function Vote() {
|
||||
>
|
||||
Unlock Voting
|
||||
</ButtonPrimary>
|
||||
) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.raw) ? (
|
||||
) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? (
|
||||
<TYPE.body fontWeight={500} mr="6px">
|
||||
<FormattedCurrencyAmount currencyAmount={availableVotes} /> Votes
|
||||
</TYPE.body>
|
||||
) : uniBalance &&
|
||||
userDelegatee &&
|
||||
userDelegatee !== ZERO_ADDRESS &&
|
||||
JSBI.notEqual(JSBI.BigInt(0), uniBalance?.raw) ? (
|
||||
JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? (
|
||||
<TYPE.body fontWeight={500} mr="6px">
|
||||
<FormattedCurrencyAmount currencyAmount={uniBalance} /> Votes
|
||||
</TYPE.body>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Currency, CurrencyAmount, Percent, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { JSBI, Pair } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { Token, Currency, Percent, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import { useCallback } from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { useV2Pair } from '../../hooks/useV2Pairs'
|
||||
@@ -23,9 +24,9 @@ export function useDerivedBurnInfo(
|
||||
pair?: Pair | null
|
||||
parsedAmounts: {
|
||||
[Field.LIQUIDITY_PERCENT]: Percent
|
||||
[Field.LIQUIDITY]?: TokenAmount
|
||||
[Field.CURRENCY_A]?: CurrencyAmount
|
||||
[Field.CURRENCY_B]?: CurrencyAmount
|
||||
[Field.LIQUIDITY]?: CurrencyAmount<Token>
|
||||
[Field.CURRENCY_A]?: CurrencyAmount<Currency>
|
||||
[Field.CURRENCY_B]?: CurrencyAmount<Currency>
|
||||
}
|
||||
error?: string
|
||||
} {
|
||||
@@ -38,7 +39,7 @@ export function useDerivedBurnInfo(
|
||||
|
||||
// balances
|
||||
const relevantTokenBalances = useTokenBalances(account ?? undefined, [pair?.liquidityToken])
|
||||
const userLiquidity: undefined | TokenAmount = relevantTokenBalances?.[pair?.liquidityToken?.address ?? '']
|
||||
const userLiquidity: undefined | CurrencyAmount<Token> = relevantTokenBalances?.[pair?.liquidityToken?.address ?? '']
|
||||
|
||||
const [tokenA, tokenB] = [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
|
||||
const tokens = {
|
||||
@@ -55,8 +56,8 @@ export function useDerivedBurnInfo(
|
||||
userLiquidity &&
|
||||
tokenA &&
|
||||
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
||||
JSBI.greaterThanOrEqual(totalSupply.raw, userLiquidity.raw)
|
||||
? new TokenAmount(tokenA, pair.getLiquidityValue(tokenA, totalSupply, userLiquidity, false).raw)
|
||||
JSBI.greaterThanOrEqual(totalSupply.quotient, userLiquidity.quotient)
|
||||
? CurrencyAmount.fromRawAmount(tokenA, pair.getLiquidityValue(tokenA, totalSupply, userLiquidity, false).quotient)
|
||||
: undefined
|
||||
const liquidityValueB =
|
||||
pair &&
|
||||
@@ -64,10 +65,10 @@ export function useDerivedBurnInfo(
|
||||
userLiquidity &&
|
||||
tokenB &&
|
||||
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
||||
JSBI.greaterThanOrEqual(totalSupply.raw, userLiquidity.raw)
|
||||
? new TokenAmount(tokenB, pair.getLiquidityValue(tokenB, totalSupply, userLiquidity, false).raw)
|
||||
JSBI.greaterThanOrEqual(totalSupply.quotient, userLiquidity.quotient)
|
||||
? CurrencyAmount.fromRawAmount(tokenB, pair.getLiquidityValue(tokenB, totalSupply, userLiquidity, false).quotient)
|
||||
: undefined
|
||||
const liquidityValues: { [Field.CURRENCY_A]?: TokenAmount; [Field.CURRENCY_B]?: TokenAmount } = {
|
||||
const liquidityValues: { [Field.CURRENCY_A]?: CurrencyAmount<Token>; [Field.CURRENCY_B]?: CurrencyAmount<Token> } = {
|
||||
[Field.CURRENCY_A]: liquidityValueA,
|
||||
[Field.CURRENCY_B]: liquidityValueB,
|
||||
}
|
||||
@@ -82,7 +83,7 @@ export function useDerivedBurnInfo(
|
||||
if (pair?.liquidityToken) {
|
||||
const independentAmount = tryParseAmount(typedValue, pair.liquidityToken)
|
||||
if (independentAmount && userLiquidity && !independentAmount.greaterThan(userLiquidity)) {
|
||||
percentToRemove = new Percent(independentAmount.raw, userLiquidity.raw)
|
||||
percentToRemove = new Percent(independentAmount.quotient, userLiquidity.quotient)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,29 +93,32 @@ export function useDerivedBurnInfo(
|
||||
const independentAmount = tryParseAmount(typedValue, tokens[independentField])
|
||||
const liquidityValue = liquidityValues[independentField]
|
||||
if (independentAmount && liquidityValue && !independentAmount.greaterThan(liquidityValue)) {
|
||||
percentToRemove = new Percent(independentAmount.raw, liquidityValue.raw)
|
||||
percentToRemove = new Percent(independentAmount.quotient, liquidityValue.quotient)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const parsedAmounts: {
|
||||
[Field.LIQUIDITY_PERCENT]: Percent
|
||||
[Field.LIQUIDITY]?: TokenAmount
|
||||
[Field.CURRENCY_A]?: TokenAmount
|
||||
[Field.CURRENCY_B]?: TokenAmount
|
||||
[Field.LIQUIDITY]?: CurrencyAmount<Token>
|
||||
[Field.CURRENCY_A]?: CurrencyAmount<Currency>
|
||||
[Field.CURRENCY_B]?: CurrencyAmount<Currency>
|
||||
} = {
|
||||
[Field.LIQUIDITY_PERCENT]: percentToRemove,
|
||||
[Field.LIQUIDITY]:
|
||||
userLiquidity && percentToRemove && percentToRemove.greaterThan('0')
|
||||
? new TokenAmount(userLiquidity.token, percentToRemove.multiply(userLiquidity.raw).quotient)
|
||||
? CurrencyAmount.fromRawAmount(
|
||||
userLiquidity.currency,
|
||||
percentToRemove.multiply(userLiquidity.quotient).quotient
|
||||
)
|
||||
: undefined,
|
||||
[Field.CURRENCY_A]:
|
||||
tokenA && percentToRemove && percentToRemove.greaterThan('0') && liquidityValueA
|
||||
? new TokenAmount(tokenA, percentToRemove.multiply(liquidityValueA.raw).quotient)
|
||||
? CurrencyAmount.fromRawAmount(tokenA, percentToRemove.multiply(liquidityValueA.quotient).quotient)
|
||||
: undefined,
|
||||
[Field.CURRENCY_B]:
|
||||
tokenB && percentToRemove && percentToRemove.greaterThan('0') && liquidityValueB
|
||||
? new TokenAmount(tokenB, percentToRemove.multiply(liquidityValueB.raw).quotient)
|
||||
? CurrencyAmount.fromRawAmount(tokenB, percentToRemove.multiply(liquidityValueB.quotient).quotient)
|
||||
: undefined,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TokenAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { Token, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import { usePool } from 'hooks/usePools'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
@@ -20,10 +20,10 @@ export function useDerivedV3BurnInfo(
|
||||
): {
|
||||
position?: Position
|
||||
liquidityPercentage?: Percent
|
||||
liquidityValue0?: TokenAmount
|
||||
liquidityValue1?: TokenAmount
|
||||
feeValue0?: TokenAmount
|
||||
feeValue1?: TokenAmount
|
||||
liquidityValue0?: CurrencyAmount<Token>
|
||||
liquidityValue1?: CurrencyAmount<Token>
|
||||
feeValue0?: CurrencyAmount<Token>
|
||||
feeValue1?: CurrencyAmount<Token>
|
||||
outOfRange: boolean
|
||||
error?: string
|
||||
} {
|
||||
@@ -52,12 +52,18 @@ export function useDerivedV3BurnInfo(
|
||||
|
||||
const liquidityValue0 =
|
||||
positionSDK &&
|
||||
new TokenAmount(positionSDK.amount0.token, liquidityPercentage.multiply(positionSDK.amount0.raw).quotient)
|
||||
CurrencyAmount.fromRawAmount(
|
||||
positionSDK.amount0.currency,
|
||||
liquidityPercentage.multiply(positionSDK.amount0.quotient).quotient
|
||||
)
|
||||
const liquidityValue1 =
|
||||
positionSDK &&
|
||||
new TokenAmount(positionSDK.amount1.token, liquidityPercentage.multiply(positionSDK.amount1.raw).quotient)
|
||||
CurrencyAmount.fromRawAmount(
|
||||
positionSDK.amount1.currency,
|
||||
liquidityPercentage.multiply(positionSDK.amount1.quotient).quotient
|
||||
)
|
||||
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, position)
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, position?.tokenId)
|
||||
|
||||
const outOfRange =
|
||||
pool && position ? pool.tickCurrent < position.tickLower || pool.tickCurrent > position.tickUpper : false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UNI } from './../../constants/index'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import { TokenAmount, ChainId } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { CurrencyAmount, ChainId, Token } from '@uniswap/sdk-core'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
@@ -74,7 +74,7 @@ export function useUserHasAvailableClaim(account: string | null | undefined): bo
|
||||
return Boolean(userClaimData && !isClaimedResult.loading && isClaimedResult.result?.[0] === false)
|
||||
}
|
||||
|
||||
export function useUserUnclaimedAmount(account: string | null | undefined): TokenAmount | undefined {
|
||||
export function useUserUnclaimedAmount(account: string | null | undefined): CurrencyAmount<Token> | undefined {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const userClaimData = useUserClaimData(account)
|
||||
const canClaim = useUserHasAvailableClaim(account)
|
||||
@@ -82,9 +82,9 @@ export function useUserUnclaimedAmount(account: string | null | undefined): Toke
|
||||
const uni = chainId ? UNI[chainId] : undefined
|
||||
if (!uni) return undefined
|
||||
if (!canClaim || !userClaimData) {
|
||||
return new TokenAmount(uni, JSBI.BigInt(0))
|
||||
return CurrencyAmount.fromRawAmount(uni, JSBI.BigInt(0))
|
||||
}
|
||||
return new TokenAmount(uni, JSBI.BigInt(userClaimData.amount))
|
||||
return CurrencyAmount.fromRawAmount(uni, JSBI.BigInt(userClaimData.amount))
|
||||
}
|
||||
|
||||
export function useClaimCallback(
|
||||
@@ -97,7 +97,7 @@ export function useClaimCallback(
|
||||
const claimData = useUserClaimData(account)
|
||||
|
||||
// used for popup summary
|
||||
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
|
||||
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
|
||||
const addTransaction = useTransactionAdder()
|
||||
const distributorContract = useMerkleDistributorContract()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UNI, PRELOADED_PROPOSALS } from './../../constants/index'
|
||||
import { TokenAmount } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
import { useGovernanceContract, useUniContract } from '../../hooks/useContract'
|
||||
import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
|
||||
@@ -164,18 +164,18 @@ export function useUserDelegatee(): string {
|
||||
}
|
||||
|
||||
// gets the users current votes
|
||||
export function useUserVotes(): TokenAmount | undefined {
|
||||
export function useUserVotes(): CurrencyAmount<Token> | undefined {
|
||||
const { account, chainId } = useActiveWeb3React()
|
||||
const uniContract = useUniContract()
|
||||
|
||||
// check for available votes
|
||||
const uni = chainId ? UNI[chainId] : undefined
|
||||
const votes = useSingleCallResult(uniContract, 'getCurrentVotes', [account ?? undefined])?.result?.[0]
|
||||
return votes && uni ? new TokenAmount(uni, votes) : undefined
|
||||
return votes && uni ? CurrencyAmount.fromRawAmount(uni, votes) : undefined
|
||||
}
|
||||
|
||||
// fetch available votes as of block (usually proposal start block)
|
||||
export function useUserVotesAsOfBlock(block: number | undefined): TokenAmount | undefined {
|
||||
export function useUserVotesAsOfBlock(block: number | undefined): CurrencyAmount<Token> | undefined {
|
||||
const { account, chainId } = useActiveWeb3React()
|
||||
const uniContract = useUniContract()
|
||||
|
||||
@@ -183,7 +183,7 @@ export function useUserVotesAsOfBlock(block: number | undefined): TokenAmount |
|
||||
const uni = chainId ? UNI[chainId] : undefined
|
||||
const votes = useSingleCallResult(uniContract, 'getPriorVotes', [account ?? undefined, block ?? undefined])
|
||||
?.result?.[0]
|
||||
return votes && uni ? new TokenAmount(uni, votes) : undefined
|
||||
return votes && uni ? CurrencyAmount.fromRawAmount(uni, votes) : undefined
|
||||
}
|
||||
|
||||
export function useDelegateCallback(): (delegatee: string | undefined) => undefined | Promise<string> {
|
||||
|
||||
@@ -1,33 +1,13 @@
|
||||
import { UNSUPPORTED_LIST_URLS } from './../../constants/lists'
|
||||
import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list'
|
||||
import { ChainId, Token } from '@uniswap/sdk-core'
|
||||
import { Tags, TokenInfo, TokenList } from '@uniswap/token-lists'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { TokenList } from '@uniswap/token-lists'
|
||||
import { useMemo } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { AppState } from '../index'
|
||||
import sortByListPriority from 'utils/listSort'
|
||||
import UNSUPPORTED_TOKEN_LIST from '../../constants/tokenLists/uniswap-v2-unsupported.tokenlist.json'
|
||||
|
||||
type TagDetails = Tags[keyof Tags]
|
||||
export interface TagInfo extends TagDetails {
|
||||
id: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Token instances created from token info.
|
||||
*/
|
||||
export class WrappedTokenInfo extends Token {
|
||||
public readonly tokenInfo: TokenInfo
|
||||
public readonly tags: TagInfo[]
|
||||
constructor(tokenInfo: TokenInfo, tags: TagInfo[]) {
|
||||
super(tokenInfo.chainId, tokenInfo.address, tokenInfo.decimals, tokenInfo.symbol, tokenInfo.name)
|
||||
this.tokenInfo = tokenInfo
|
||||
this.tags = tags
|
||||
}
|
||||
public get logoURI(): string | undefined {
|
||||
return this.tokenInfo.logoURI
|
||||
}
|
||||
}
|
||||
import { AppState } from '../index'
|
||||
import { UNSUPPORTED_LIST_URLS } from './../../constants/lists'
|
||||
import { WrappedTokenInfo } from './wrappedTokenInfo'
|
||||
|
||||
export type TokenAddressMap = Readonly<
|
||||
{ [chainId in ChainId | number]: Readonly<{ [tokenAddress: string]: { token: WrappedTokenInfo; list: TokenList } }> }
|
||||
@@ -53,14 +33,7 @@ export function listToTokenMap(list: TokenList): TokenAddressMap {
|
||||
|
||||
const map = list.tokens.reduce<TokenAddressMap>(
|
||||
(tokenMap, tokenInfo) => {
|
||||
const tags: TagInfo[] =
|
||||
tokenInfo.tags
|
||||
?.map((tagId) => {
|
||||
if (!list.tags?.[tagId]) return undefined
|
||||
return { ...list.tags[tagId], id: tagId }
|
||||
})
|
||||
?.filter((x): x is TagInfo => Boolean(x)) ?? []
|
||||
const token = new WrappedTokenInfo(tokenInfo, tags)
|
||||
const token = new WrappedTokenInfo(tokenInfo, list)
|
||||
if (tokenMap[token.chainId][token.address] !== undefined) {
|
||||
console.error(new Error(`Duplicate token! ${token.address}`))
|
||||
return tokenMap
|
||||
@@ -71,7 +44,7 @@ export function listToTokenMap(list: TokenList): TokenAddressMap {
|
||||
...tokenMap[token.chainId as ChainId],
|
||||
[token.address]: {
|
||||
token,
|
||||
list: list,
|
||||
list,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -84,14 +57,7 @@ export function listToTokenMap(list: TokenList): TokenAddressMap {
|
||||
|
||||
const TRANSFORMED_DEFAULT_TOKEN_LIST = listToTokenMap(DEFAULT_TOKEN_LIST)
|
||||
|
||||
export function useAllLists(): {
|
||||
readonly [url: string]: {
|
||||
readonly current: TokenList | null
|
||||
readonly pendingUpdate: TokenList | null
|
||||
readonly loadingRequestId: string | null
|
||||
readonly error: string | null
|
||||
}
|
||||
} {
|
||||
export function useAllLists(): AppState['lists']['byUrl'] {
|
||||
return useSelector<AppState, AppState['lists']['byUrl']>((state) => state.lists.byUrl)
|
||||
}
|
||||
|
||||
@@ -119,8 +85,7 @@ function useCombinedTokenMapFromUrls(urls: string[] | undefined): TokenAddressMa
|
||||
const current = lists[currentUrl]?.current
|
||||
if (!current) return allTokens
|
||||
try {
|
||||
const newTokens = Object.assign(listToTokenMap(current))
|
||||
return combineMaps(allTokens, newTokens)
|
||||
return combineMaps(allTokens, listToTokenMap(current))
|
||||
} catch (error) {
|
||||
console.error('Could not show token list due to error', error)
|
||||
return allTokens
|
||||
@@ -150,12 +115,6 @@ export function useCombinedActiveList(): TokenAddressMap {
|
||||
return combineMaps(activeTokens, TRANSFORMED_DEFAULT_TOKEN_LIST)
|
||||
}
|
||||
|
||||
// all tokens from inactive lists
|
||||
export function useCombinedInactiveList(): TokenAddressMap {
|
||||
const allInactiveListUrls: string[] = useInactiveListUrls()
|
||||
return useCombinedTokenMapFromUrls(allInactiveListUrls)
|
||||
}
|
||||
|
||||
// list of tokens not supported on interface, used to show warnings and prevent swaps and adds
|
||||
export function useUnsupportedTokenList(): TokenAddressMap {
|
||||
// get hard coded unsupported tokens
|
||||
@@ -165,7 +124,10 @@ export function useUnsupportedTokenList(): TokenAddressMap {
|
||||
const loadedUnsupportedListMap = useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS)
|
||||
|
||||
// format into one token address map
|
||||
return combineMaps(localUnsupportedListMap, loadedUnsupportedListMap)
|
||||
return useMemo(() => combineMaps(localUnsupportedListMap, loadedUnsupportedListMap), [
|
||||
localUnsupportedListMap,
|
||||
loadedUnsupportedListMap,
|
||||
])
|
||||
}
|
||||
|
||||
export function useIsListActive(url: string): boolean {
|
||||
|
||||
@@ -9,7 +9,6 @@ import useIsWindowVisible from '../../hooks/useIsWindowVisible'
|
||||
import { AppDispatch } from '../index'
|
||||
import { acceptListUpdate } from './actions'
|
||||
import { useActiveListUrls } from './hooks'
|
||||
import { useAllInactiveTokens } from 'hooks/Tokens'
|
||||
import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
|
||||
|
||||
export default function Updater(): null {
|
||||
@@ -21,9 +20,6 @@ export default function Updater(): null {
|
||||
const lists = useAllLists()
|
||||
const activeListUrls = useActiveListUrls()
|
||||
|
||||
// initiate loading
|
||||
useAllInactiveTokens()
|
||||
|
||||
const fetchList = useFetchListCallback()
|
||||
const fetchAllListsCallback = useCallback(() => {
|
||||
if (!isWindowVisible) return
|
||||
|
||||
77
src/state/lists/wrappedTokenInfo.ts
Normal file
77
src/state/lists/wrappedTokenInfo.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { ChainId, Token } from '@uniswap/sdk-core'
|
||||
import { Tags, TokenInfo } from '@uniswap/token-lists'
|
||||
import { TokenList } from '@uniswap/token-lists/dist/types'
|
||||
import { isAddress } from '../../utils'
|
||||
|
||||
type TagDetails = Tags[keyof Tags]
|
||||
export interface TagInfo extends TagDetails {
|
||||
id: string
|
||||
}
|
||||
/**
|
||||
* Token instances created from token info on a token list.
|
||||
*/
|
||||
export class WrappedTokenInfo implements Token {
|
||||
public readonly isEther: false = false
|
||||
public readonly isToken: true = true
|
||||
public readonly list: TokenList
|
||||
|
||||
public readonly tokenInfo: TokenInfo
|
||||
|
||||
constructor(tokenInfo: TokenInfo, list: TokenList) {
|
||||
this.tokenInfo = tokenInfo
|
||||
this.list = list
|
||||
}
|
||||
|
||||
private _checksummedAddress: string | null = null
|
||||
|
||||
public get address(): string {
|
||||
if (this._checksummedAddress) return this._checksummedAddress
|
||||
const checksummedAddress = isAddress(this.tokenInfo.address)
|
||||
if (!checksummedAddress) throw new Error(`Invalid token address: ${this.tokenInfo.address}`)
|
||||
return (this._checksummedAddress = checksummedAddress)
|
||||
}
|
||||
|
||||
public get chainId(): ChainId | number {
|
||||
return this.tokenInfo.chainId
|
||||
}
|
||||
|
||||
public get decimals(): number {
|
||||
return this.tokenInfo.decimals
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this.tokenInfo.name
|
||||
}
|
||||
|
||||
public get symbol(): string {
|
||||
return this.tokenInfo.symbol
|
||||
}
|
||||
|
||||
public get logoURI(): string | undefined {
|
||||
return this.tokenInfo.logoURI
|
||||
}
|
||||
|
||||
private _tags: TagInfo[] | null = null
|
||||
public get tags(): TagInfo[] {
|
||||
if (this._tags !== null) return this._tags
|
||||
if (!this.tokenInfo.tags) return (this._tags = [])
|
||||
const listTags = this.list.tags
|
||||
if (!listTags) return (this._tags = [])
|
||||
|
||||
return (this._tags = this.tokenInfo.tags.map((tagId) => {
|
||||
return {
|
||||
...listTags[tagId],
|
||||
id: tagId,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
equals(other: Token): boolean {
|
||||
return other.chainId === this.chainId && other.address.toLowerCase() === this.address.toLowerCase()
|
||||
}
|
||||
|
||||
sortsBefore(other: Token): boolean {
|
||||
if (this.equals(other)) throw new Error('Addresses should not be equal')
|
||||
return this.address.toLowerCase() < other.address.toLowerCase()
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { useDispatch, useSelector } from 'react-redux'
|
||||
import { AppDispatch, AppState } from '../index'
|
||||
import { Field, typeInput } from './actions'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import { Currency, CurrencyAmount, ETHER, Percent, Price, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { Currency, Token, Percent, Price, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { PairState, useV2Pair } from '../../hooks/useV2Pairs'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
@@ -55,11 +55,11 @@ export function useDerivedMintInfo(
|
||||
currencies: { [field in Field]?: Currency }
|
||||
pair?: Pair | null
|
||||
pairState: PairState
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount }
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount }
|
||||
price?: Price
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
price?: Price<Currency, Currency>
|
||||
noLiquidity?: boolean
|
||||
liquidityMinted?: TokenAmount
|
||||
liquidityMinted?: CurrencyAmount<Token>
|
||||
poolTokenPercentage?: Percent
|
||||
error?: string
|
||||
} {
|
||||
@@ -83,21 +83,24 @@ export function useDerivedMintInfo(
|
||||
const totalSupply = useTotalSupply(pair?.liquidityToken)
|
||||
|
||||
const noLiquidity: boolean =
|
||||
pairState === PairState.NOT_EXISTS || Boolean(totalSupply && JSBI.equal(totalSupply.raw, ZERO))
|
||||
pairState === PairState.NOT_EXISTS || Boolean(totalSupply && JSBI.equal(totalSupply.quotient, ZERO))
|
||||
|
||||
// balances
|
||||
const balances = useCurrencyBalances(account ?? undefined, [
|
||||
currencies[Field.CURRENCY_A],
|
||||
currencies[Field.CURRENCY_B],
|
||||
])
|
||||
const currencyBalances: { [field in Field]?: CurrencyAmount } = {
|
||||
const currencyBalances: { [field in Field]?: CurrencyAmount<Currency> } = {
|
||||
[Field.CURRENCY_A]: balances[0],
|
||||
[Field.CURRENCY_B]: balances[1],
|
||||
}
|
||||
|
||||
// amounts
|
||||
const independentAmount: CurrencyAmount | undefined = tryParseAmount(typedValue, currencies[independentField])
|
||||
const dependentAmount: CurrencyAmount | undefined = useMemo(() => {
|
||||
const independentAmount: CurrencyAmount<Currency> | undefined = tryParseAmount(
|
||||
typedValue,
|
||||
currencies[independentField]
|
||||
)
|
||||
const dependentAmount: CurrencyAmount<Currency> | undefined = useMemo(() => {
|
||||
if (noLiquidity) {
|
||||
if (otherTypedValue && currencies[dependentField]) {
|
||||
return tryParseAmount(otherTypedValue, currencies[dependentField])
|
||||
@@ -113,7 +116,7 @@ export function useDerivedMintInfo(
|
||||
dependentField === Field.CURRENCY_B
|
||||
? pair.priceOf(tokenA).quote(wrappedIndependentAmount)
|
||||
: pair.priceOf(tokenB).quote(wrappedIndependentAmount)
|
||||
return dependentCurrency === ETHER ? CurrencyAmount.ether(dependentTokenAmount.raw) : dependentTokenAmount
|
||||
return dependentCurrency?.isEther ? CurrencyAmount.ether(dependentTokenAmount.quotient) : dependentTokenAmount
|
||||
}
|
||||
return undefined
|
||||
} else {
|
||||
@@ -121,7 +124,7 @@ export function useDerivedMintInfo(
|
||||
}
|
||||
}, [noLiquidity, otherTypedValue, currencies, dependentField, independentAmount, currencyA, chainId, currencyB, pair])
|
||||
|
||||
const parsedAmounts: { [field in Field]: CurrencyAmount | undefined } = useMemo(() => {
|
||||
const parsedAmounts: { [field in Field]: CurrencyAmount<Currency> | undefined } = useMemo(() => {
|
||||
return {
|
||||
[Field.CURRENCY_A]: independentField === Field.CURRENCY_A ? independentAmount : dependentAmount,
|
||||
[Field.CURRENCY_B]: independentField === Field.CURRENCY_A ? dependentAmount : independentAmount,
|
||||
@@ -132,7 +135,12 @@ export function useDerivedMintInfo(
|
||||
if (noLiquidity) {
|
||||
const { [Field.CURRENCY_A]: currencyAAmount, [Field.CURRENCY_B]: currencyBAmount } = parsedAmounts
|
||||
if (currencyAAmount && currencyBAmount) {
|
||||
return new Price(currencyAAmount.currency, currencyBAmount.currency, currencyAAmount.raw, currencyBAmount.raw)
|
||||
return new Price(
|
||||
currencyAAmount.currency,
|
||||
currencyBAmount.currency,
|
||||
currencyAAmount.quotient,
|
||||
currencyBAmount.quotient
|
||||
)
|
||||
}
|
||||
return undefined
|
||||
} else {
|
||||
@@ -157,7 +165,7 @@ export function useDerivedMintInfo(
|
||||
|
||||
const poolTokenPercentage = useMemo(() => {
|
||||
if (liquidityMinted && totalSupply) {
|
||||
return new Percent(liquidityMinted.raw, totalSupply.add(liquidityMinted).raw)
|
||||
return new Percent(liquidityMinted.quotient, totalSupply.add(liquidityMinted).quotient)
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
TICK_SPACINGS,
|
||||
encodeSqrtRatioX96,
|
||||
} from '@uniswap/v3-sdk/dist/'
|
||||
import { Currency, CurrencyAmount, ETHER, Price, Rounding } from '@uniswap/sdk-core'
|
||||
import { Currency, Token, CurrencyAmount, currencyEquals, Price, Rounding } from '@uniswap/sdk-core'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { useActiveWeb3React } from '../../../hooks'
|
||||
@@ -94,14 +94,14 @@ export function useV3DerivedMintInfo(
|
||||
pool?: Pool | null
|
||||
poolState: PoolState
|
||||
ticks: { [bound in Bound]?: number | undefined }
|
||||
price?: Price
|
||||
price?: Price<Token, Token>
|
||||
pricesAtTicks: {
|
||||
[bound in Bound]?: Price | undefined
|
||||
[bound in Bound]?: Price<Token, Token> | undefined
|
||||
}
|
||||
currencies: { [field in Field]?: Currency }
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount }
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
dependentField: Field
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount }
|
||||
parsedAmounts: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
position: Position | undefined
|
||||
noLiquidity?: boolean
|
||||
errorMessage?: string
|
||||
@@ -154,7 +154,7 @@ export function useV3DerivedMintInfo(
|
||||
currencies[Field.CURRENCY_A],
|
||||
currencies[Field.CURRENCY_B],
|
||||
])
|
||||
const currencyBalances: { [field in Field]?: CurrencyAmount } = {
|
||||
const currencyBalances: { [field in Field]?: CurrencyAmount<Currency> } = {
|
||||
[Field.CURRENCY_A]: balances[0],
|
||||
[Field.CURRENCY_B]: balances[1],
|
||||
}
|
||||
@@ -167,7 +167,7 @@ export function useV3DerivedMintInfo(
|
||||
const invertPrice = Boolean(baseToken && token0 && !baseToken.equals(token0))
|
||||
|
||||
// always returns the price with 0 as base token
|
||||
const price = useMemo(() => {
|
||||
const price: Price<Token, Token> | undefined = useMemo(() => {
|
||||
// if no liquidity use typed value
|
||||
if (noLiquidity) {
|
||||
const parsedQuoteAmount = tryParseAmount(startPriceTypedValue, invertPrice ? token0 : token1)
|
||||
@@ -175,7 +175,12 @@ export function useV3DerivedMintInfo(
|
||||
const baseAmount = tryParseAmount('1', invertPrice ? token1 : token0)
|
||||
const price =
|
||||
baseAmount && parsedQuoteAmount
|
||||
? new Price(baseAmount.currency, parsedQuoteAmount.currency, baseAmount.raw, parsedQuoteAmount.raw)
|
||||
? new Price(
|
||||
baseAmount.currency,
|
||||
parsedQuoteAmount.currency,
|
||||
baseAmount.quotient,
|
||||
parsedQuoteAmount.quotient
|
||||
)
|
||||
: undefined
|
||||
return (invertPrice ? price?.invert() : price) ?? undefined
|
||||
}
|
||||
@@ -188,7 +193,7 @@ export function useV3DerivedMintInfo(
|
||||
|
||||
// check for invalid price input (converts to invalid ratio)
|
||||
const invalidPrice = useMemo(() => {
|
||||
const sqrtRatioX96 = price ? encodeSqrtRatioX96(price.raw.numerator, price.raw.denominator) : undefined
|
||||
const sqrtRatioX96 = price ? encodeSqrtRatioX96(price.numerator, price.denominator) : undefined
|
||||
const invalid =
|
||||
price &&
|
||||
sqrtRatioX96 &&
|
||||
@@ -254,9 +259,12 @@ export function useV3DerivedMintInfo(
|
||||
)
|
||||
|
||||
// amounts
|
||||
const independentAmount: CurrencyAmount | undefined = tryParseAmount(typedValue, currencies[independentField])
|
||||
const independentAmount: CurrencyAmount<Currency> | undefined = tryParseAmount(
|
||||
typedValue,
|
||||
currencies[independentField]
|
||||
)
|
||||
|
||||
const dependentAmount: CurrencyAmount | undefined = useMemo(() => {
|
||||
const dependentAmount: CurrencyAmount<Currency> | undefined = useMemo(() => {
|
||||
// we wrap the currencies just to get the price in terms of the other token
|
||||
const wrappedIndependentAmount = wrappedCurrencyAmount(independentAmount, chainId)
|
||||
const dependentCurrency = dependentField === Field.CURRENCY_B ? currencyB : currencyA
|
||||
@@ -272,24 +280,24 @@ export function useV3DerivedMintInfo(
|
||||
return undefined
|
||||
}
|
||||
|
||||
const position: Position | undefined = wrappedIndependentAmount.token.equals(poolForPosition.token0)
|
||||
const position: Position | undefined = currencyEquals(wrappedIndependentAmount.currency, poolForPosition.token0)
|
||||
? Position.fromAmount0({
|
||||
pool: poolForPosition,
|
||||
tickLower,
|
||||
tickUpper,
|
||||
amount0: independentAmount.raw,
|
||||
amount0: independentAmount.quotient,
|
||||
})
|
||||
: Position.fromAmount1({
|
||||
pool: poolForPosition,
|
||||
tickLower,
|
||||
tickUpper,
|
||||
amount1: independentAmount.raw,
|
||||
amount1: independentAmount.quotient,
|
||||
})
|
||||
|
||||
const dependentTokenAmount = wrappedIndependentAmount.token.equals(poolForPosition.token0)
|
||||
const dependentTokenAmount = currencyEquals(wrappedIndependentAmount.currency, poolForPosition.token0)
|
||||
? position.amount1
|
||||
: position.amount0
|
||||
return dependentCurrency === ETHER ? CurrencyAmount.ether(dependentTokenAmount.raw) : dependentTokenAmount
|
||||
return dependentCurrency?.isEther ? CurrencyAmount.ether(dependentTokenAmount.quotient) : dependentTokenAmount
|
||||
}
|
||||
|
||||
return undefined
|
||||
@@ -306,7 +314,7 @@ export function useV3DerivedMintInfo(
|
||||
invalidRange,
|
||||
])
|
||||
|
||||
const parsedAmounts: { [field in Field]: CurrencyAmount | undefined } = useMemo(() => {
|
||||
const parsedAmounts: { [field in Field]: CurrencyAmount<Currency> | undefined } = useMemo(() => {
|
||||
return {
|
||||
[Field.CURRENCY_A]: independentField === Field.CURRENCY_A ? independentAmount : dependentAmount,
|
||||
[Field.CURRENCY_B]: independentField === Field.CURRENCY_A ? dependentAmount : independentAmount,
|
||||
@@ -350,10 +358,10 @@ export function useV3DerivedMintInfo(
|
||||
|
||||
// mark as 0 if disbaled because out of range
|
||||
const amount0 = !deposit0Disabled
|
||||
? parsedAmounts?.[tokenA.equals(poolForPosition.token0) ? Field.CURRENCY_A : Field.CURRENCY_B]?.raw
|
||||
? parsedAmounts?.[tokenA.equals(poolForPosition.token0) ? Field.CURRENCY_A : Field.CURRENCY_B]?.quotient
|
||||
: BIG_INT_ZERO
|
||||
const amount1 = !deposit1Disabled
|
||||
? parsedAmounts?.[tokenA.equals(poolForPosition.token0) ? Field.CURRENCY_B : Field.CURRENCY_A]?.raw
|
||||
? parsedAmounts?.[tokenA.equals(poolForPosition.token0) ? Field.CURRENCY_B : Field.CURRENCY_A]?.quotient
|
||||
: BIG_INT_ZERO
|
||||
|
||||
if (amount0 !== undefined && amount1 !== undefined) {
|
||||
|
||||
@@ -19,7 +19,7 @@ export function tryParseTick(
|
||||
if (!amount || !amountOne) return undefined
|
||||
|
||||
// parse the typed value into a price
|
||||
const price = new Price(baseToken, quoteToken, amountOne.raw, amount.raw)
|
||||
const price = new Price(baseToken, quoteToken, amountOne.quotient, amount.quotient)
|
||||
|
||||
// this function is agnostic to the base, will always return the correct tick
|
||||
const tick = priceToClosestTick(price)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChainId, CurrencyAmount, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
||||
import { ChainId, Token, CurrencyAmount, WETH9 } from '@uniswap/sdk-core'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { useMemo } from 'react'
|
||||
@@ -45,26 +45,26 @@ export interface StakingInfo {
|
||||
// the tokens involved in this pair
|
||||
tokens: [Token, Token]
|
||||
// the amount of token currently staked, or undefined if no account
|
||||
stakedAmount: TokenAmount
|
||||
stakedAmount: CurrencyAmount<Token>
|
||||
// the amount of reward token earned by the active account, or undefined if no account
|
||||
earnedAmount: TokenAmount
|
||||
earnedAmount: CurrencyAmount<Token>
|
||||
// the total amount of token staked in the contract
|
||||
totalStakedAmount: TokenAmount
|
||||
totalStakedAmount: CurrencyAmount<Token>
|
||||
// the amount of token distributed per second to all LPs, constant
|
||||
totalRewardRate: TokenAmount
|
||||
totalRewardRate: CurrencyAmount<Token>
|
||||
// the current amount of token distributed to the active account per second.
|
||||
// equivalent to percent of total supply * reward rate
|
||||
rewardRate: TokenAmount
|
||||
rewardRate: CurrencyAmount<Token>
|
||||
// when the period ends
|
||||
periodFinish: Date | undefined
|
||||
// if pool is active
|
||||
active: boolean
|
||||
// calculates a hypothetical amount of token distributed to the active account per second.
|
||||
getHypotheticalRewardRate: (
|
||||
stakedAmount: TokenAmount,
|
||||
totalStakedAmount: TokenAmount,
|
||||
totalRewardRate: TokenAmount
|
||||
) => TokenAmount
|
||||
stakedAmount: CurrencyAmount<Token>,
|
||||
totalStakedAmount: CurrencyAmount<Token>,
|
||||
totalRewardRate: CurrencyAmount<Token>
|
||||
) => CurrencyAmount<Token>
|
||||
}
|
||||
|
||||
// gets the staking info from the network for the active chain id
|
||||
@@ -154,23 +154,32 @@ export function useStakingInfo(pairToFilterBy?: Pair | null): StakingInfo[] {
|
||||
|
||||
// get the LP token
|
||||
const tokens = info[index].tokens
|
||||
const dummyPair = new Pair(new TokenAmount(tokens[0], '0'), new TokenAmount(tokens[1], '0'))
|
||||
const dummyPair = new Pair(
|
||||
CurrencyAmount.fromRawAmount(tokens[0], '0'),
|
||||
CurrencyAmount.fromRawAmount(tokens[1], '0')
|
||||
)
|
||||
|
||||
// check for account, if no account set to 0
|
||||
|
||||
const stakedAmount = new TokenAmount(dummyPair.liquidityToken, JSBI.BigInt(balanceState?.result?.[0] ?? 0))
|
||||
const totalStakedAmount = new TokenAmount(dummyPair.liquidityToken, JSBI.BigInt(totalSupplyState.result?.[0]))
|
||||
const totalRewardRate = new TokenAmount(uni, JSBI.BigInt(rewardRateState.result?.[0]))
|
||||
const stakedAmount = CurrencyAmount.fromRawAmount(
|
||||
dummyPair.liquidityToken,
|
||||
JSBI.BigInt(balanceState?.result?.[0] ?? 0)
|
||||
)
|
||||
const totalStakedAmount = CurrencyAmount.fromRawAmount(
|
||||
dummyPair.liquidityToken,
|
||||
JSBI.BigInt(totalSupplyState.result?.[0])
|
||||
)
|
||||
const totalRewardRate = CurrencyAmount.fromRawAmount(uni, JSBI.BigInt(rewardRateState.result?.[0]))
|
||||
|
||||
const getHypotheticalRewardRate = (
|
||||
stakedAmount: TokenAmount,
|
||||
totalStakedAmount: TokenAmount,
|
||||
totalRewardRate: TokenAmount
|
||||
): TokenAmount => {
|
||||
return new TokenAmount(
|
||||
stakedAmount: CurrencyAmount<Token>,
|
||||
totalStakedAmount: CurrencyAmount<Token>,
|
||||
totalRewardRate: CurrencyAmount<Token>
|
||||
): CurrencyAmount<Token> => {
|
||||
return CurrencyAmount.fromRawAmount(
|
||||
uni,
|
||||
JSBI.greaterThan(totalStakedAmount.raw, JSBI.BigInt(0))
|
||||
? JSBI.divide(JSBI.multiply(totalRewardRate.raw, stakedAmount.raw), totalStakedAmount.raw)
|
||||
JSBI.greaterThan(totalStakedAmount.quotient, JSBI.BigInt(0))
|
||||
? JSBI.divide(JSBI.multiply(totalRewardRate.quotient, stakedAmount.quotient), totalStakedAmount.quotient)
|
||||
: JSBI.BigInt(0)
|
||||
)
|
||||
}
|
||||
@@ -188,7 +197,7 @@ export function useStakingInfo(pairToFilterBy?: Pair | null): StakingInfo[] {
|
||||
stakingRewardAddress: rewardsAddress,
|
||||
tokens: info[index].tokens,
|
||||
periodFinish: periodFinishMs > 0 ? new Date(periodFinishMs) : undefined,
|
||||
earnedAmount: new TokenAmount(uni, JSBI.BigInt(earnedAmountState?.result?.[0] ?? 0)),
|
||||
earnedAmount: CurrencyAmount.fromRawAmount(uni, JSBI.BigInt(earnedAmountState?.result?.[0] ?? 0)),
|
||||
rewardRate: individualRewardRate,
|
||||
totalRewardRate: totalRewardRate,
|
||||
stakedAmount: stakedAmount,
|
||||
@@ -213,7 +222,7 @@ export function useStakingInfo(pairToFilterBy?: Pair | null): StakingInfo[] {
|
||||
])
|
||||
}
|
||||
|
||||
export function useTotalUniEarned(): TokenAmount | undefined {
|
||||
export function useTotalUniEarned(): CurrencyAmount<Token> | undefined {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const uni = chainId ? UNI[chainId] : undefined
|
||||
const stakingInfos = useStakingInfo()
|
||||
@@ -223,8 +232,8 @@ export function useTotalUniEarned(): TokenAmount | undefined {
|
||||
return (
|
||||
stakingInfos?.reduce(
|
||||
(accumulator, stakingInfo) => accumulator.add(stakingInfo.earnedAmount),
|
||||
new TokenAmount(uni, '0')
|
||||
) ?? new TokenAmount(uni, '0')
|
||||
CurrencyAmount.fromRawAmount(uni, '0')
|
||||
) ?? CurrencyAmount.fromRawAmount(uni, '0')
|
||||
)
|
||||
}, [stakingInfos, uni])
|
||||
}
|
||||
@@ -232,18 +241,18 @@ export function useTotalUniEarned(): TokenAmount | undefined {
|
||||
// based on typed value
|
||||
export function useDerivedStakeInfo(
|
||||
typedValue: string,
|
||||
stakingToken: Token,
|
||||
userLiquidityUnstaked: TokenAmount | undefined
|
||||
stakingToken: Token | undefined,
|
||||
userLiquidityUnstaked: CurrencyAmount<Token> | undefined
|
||||
): {
|
||||
parsedAmount?: CurrencyAmount
|
||||
parsedAmount?: CurrencyAmount<Token>
|
||||
error?: string
|
||||
} {
|
||||
const { account } = useActiveWeb3React()
|
||||
|
||||
const parsedInput: CurrencyAmount | undefined = tryParseAmount(typedValue, stakingToken)
|
||||
const parsedInput: CurrencyAmount<Token> | undefined = tryParseAmount(typedValue, stakingToken)
|
||||
|
||||
const parsedAmount =
|
||||
parsedInput && userLiquidityUnstaked && JSBI.lessThanOrEqual(parsedInput.raw, userLiquidityUnstaked.raw)
|
||||
parsedInput && userLiquidityUnstaked && JSBI.lessThanOrEqual(parsedInput.quotient, userLiquidityUnstaked.quotient)
|
||||
? parsedInput
|
||||
: undefined
|
||||
|
||||
@@ -264,16 +273,17 @@ export function useDerivedStakeInfo(
|
||||
// based on typed value
|
||||
export function useDerivedUnstakeInfo(
|
||||
typedValue: string,
|
||||
stakingAmount: TokenAmount
|
||||
stakingAmount: CurrencyAmount<Token>
|
||||
): {
|
||||
parsedAmount?: CurrencyAmount
|
||||
parsedAmount?: CurrencyAmount<Token>
|
||||
error?: string
|
||||
} {
|
||||
const { account } = useActiveWeb3React()
|
||||
|
||||
const parsedInput: CurrencyAmount | undefined = tryParseAmount(typedValue, stakingAmount.token)
|
||||
const parsedInput: CurrencyAmount<Token> | undefined = tryParseAmount(typedValue, stakingAmount.currency)
|
||||
|
||||
const parsedAmount = parsedInput && JSBI.lessThanOrEqual(parsedInput.raw, stakingAmount.raw) ? parsedInput : undefined
|
||||
const parsedAmount =
|
||||
parsedInput && JSBI.lessThanOrEqual(parsedInput.quotient, stakingAmount.quotient) ? parsedInput : undefined
|
||||
|
||||
let error: string | undefined
|
||||
if (!account) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import JSBI from 'jsbi'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { useBestV3TradeExactIn, useBestV3TradeExactOut, V3TradeState } from '../../hooks/useBestV3Trade'
|
||||
import useENS from '../../hooks/useENS'
|
||||
import { parseUnits } from '@ethersproject/units'
|
||||
import { Currency, CurrencyAmount, ETHER, Token, TokenAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { JSBI, Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { ParsedQs } from 'qs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
@@ -35,7 +36,7 @@ export function useSwapActionHandlers(): {
|
||||
dispatch(
|
||||
selectCurrency({
|
||||
field,
|
||||
currencyId: currency instanceof Token ? currency.address : currency === ETHER ? 'ETH' : '',
|
||||
currencyId: currency.isToken ? currency.address : currency.isEther ? 'ETH' : '',
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -69,16 +70,14 @@ export function useSwapActionHandlers(): {
|
||||
}
|
||||
|
||||
// try to parse a user entered amount for a given token
|
||||
export function tryParseAmount(value?: string, currency?: Currency): CurrencyAmount | undefined {
|
||||
export function tryParseAmount<T extends Currency>(value?: string, currency?: T): CurrencyAmount<T> | undefined {
|
||||
if (!value || !currency) {
|
||||
return undefined
|
||||
}
|
||||
try {
|
||||
const typedValueParsed = parseUnits(value, currency.decimals).toString()
|
||||
if (typedValueParsed !== '0') {
|
||||
return currency instanceof Token
|
||||
? new TokenAmount(currency, JSBI.BigInt(typedValueParsed))
|
||||
: CurrencyAmount.ether(JSBI.BigInt(typedValueParsed))
|
||||
return CurrencyAmount.fromRawAmount(currency, JSBI.BigInt(typedValueParsed))
|
||||
}
|
||||
} catch (error) {
|
||||
// should fail if the user specifies too many decimal places of precision (or maybe exceed max uint?)
|
||||
@@ -99,7 +98,10 @@ const BAD_RECIPIENT_ADDRESSES: { [address: string]: true } = {
|
||||
* @param trade to check for the given address
|
||||
* @param checksummedAddress address to check in the pairs and tokens
|
||||
*/
|
||||
function involvesAddress(trade: V2Trade | V3Trade, checksummedAddress: string): boolean {
|
||||
function involvesAddress(
|
||||
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>,
|
||||
checksummedAddress: string
|
||||
): boolean {
|
||||
const path = trade instanceof V2Trade ? trade.route.path : trade.route.tokenPath
|
||||
return (
|
||||
path.some((token) => token.address === checksummedAddress) ||
|
||||
@@ -114,12 +116,12 @@ export function useDerivedSwapInfo(
|
||||
toggledVersion: Version
|
||||
): {
|
||||
currencies: { [field in Field]?: Currency }
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount }
|
||||
parsedAmount: CurrencyAmount | undefined
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
parsedAmount: CurrencyAmount<Currency> | undefined
|
||||
inputError?: string
|
||||
v2Trade: V2Trade | undefined
|
||||
v3TradeState: { trade: V3Trade | null; state: V3TradeState }
|
||||
toggledTrade: V2Trade | V3Trade | undefined
|
||||
v2Trade: V2Trade<Currency, Currency, TradeType> | undefined
|
||||
v3TradeState: { trade: V3Trade<Currency, Currency, TradeType> | null; state: V3TradeState }
|
||||
toggledTrade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
|
||||
allowedSlippage: Percent
|
||||
} {
|
||||
const { account } = useActiveWeb3React()
|
||||
|
||||
@@ -96,7 +96,12 @@ export default createReducer(initialState, (builder) =>
|
||||
|
||||
// deadline isnt being tracked in local storage, reset to default
|
||||
// noinspection SuspiciousTypeOfGuard
|
||||
if (typeof state.userDeadline !== 'number' || !Number.isInteger(state.userDeadline) || state.userDeadline < 60) {
|
||||
if (
|
||||
typeof state.userDeadline !== 'number' ||
|
||||
!Number.isInteger(state.userDeadline) ||
|
||||
state.userDeadline < 60 ||
|
||||
state.userDeadline > 180 * 60
|
||||
) {
|
||||
state.userDeadline = DEFAULT_DEADLINE_FROM_NOW
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Currency, CurrencyAmount, ETHER, Token, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import { Currency, Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { useMemo } from 'react'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useAllTokens } from '../../hooks/Tokens'
|
||||
@@ -17,7 +17,7 @@ import { Erc20Interface } from 'abis/types/Erc20'
|
||||
*/
|
||||
export function useETHBalances(
|
||||
uncheckedAddresses?: (string | undefined)[]
|
||||
): { [address: string]: CurrencyAmount | undefined } {
|
||||
): { [address: string]: CurrencyAmount<Currency> | undefined } {
|
||||
const multicallContract = useMulticall2Contract()
|
||||
|
||||
const addresses: string[] = useMemo(
|
||||
@@ -39,7 +39,7 @@ export function useETHBalances(
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
addresses.reduce<{ [address: string]: CurrencyAmount }>((memo, address, i) => {
|
||||
addresses.reduce<{ [address: string]: CurrencyAmount<Currency> }>((memo, address, i) => {
|
||||
const value = results?.[i]?.result?.[0]
|
||||
if (value) memo[address] = CurrencyAmount.ether(JSBI.BigInt(value.toString()))
|
||||
return memo
|
||||
@@ -54,7 +54,7 @@ export function useETHBalances(
|
||||
export function useTokenBalancesWithLoadingIndicator(
|
||||
address?: string,
|
||||
tokens?: (Token | undefined)[]
|
||||
): [{ [tokenAddress: string]: TokenAmount | undefined }, boolean] {
|
||||
): [{ [tokenAddress: string]: CurrencyAmount<Token> | undefined }, boolean] {
|
||||
const validatedTokens: Token[] = useMemo(
|
||||
() => tokens?.filter((t?: Token): t is Token => isAddress(t?.address) !== false) ?? [],
|
||||
[tokens]
|
||||
@@ -77,11 +77,11 @@ export function useTokenBalancesWithLoadingIndicator(
|
||||
useMemo(
|
||||
() =>
|
||||
address && validatedTokens.length > 0
|
||||
? validatedTokens.reduce<{ [tokenAddress: string]: TokenAmount | undefined }>((memo, token, i) => {
|
||||
? validatedTokens.reduce<{ [tokenAddress: string]: CurrencyAmount<Token> | undefined }>((memo, token, i) => {
|
||||
const value = balances?.[i]?.result?.[0]
|
||||
const amount = value ? JSBI.BigInt(value.toString()) : undefined
|
||||
if (amount) {
|
||||
memo[token.address] = new TokenAmount(token, amount)
|
||||
memo[token.address] = CurrencyAmount.fromRawAmount(token, amount)
|
||||
}
|
||||
return memo
|
||||
}, {})
|
||||
@@ -95,12 +95,12 @@ export function useTokenBalancesWithLoadingIndicator(
|
||||
export function useTokenBalances(
|
||||
address?: string,
|
||||
tokens?: (Token | undefined)[]
|
||||
): { [tokenAddress: string]: TokenAmount | undefined } {
|
||||
): { [tokenAddress: string]: CurrencyAmount<Token> | undefined } {
|
||||
return useTokenBalancesWithLoadingIndicator(address, tokens)[0]
|
||||
}
|
||||
|
||||
// get the balance for a single token/account combo
|
||||
export function useTokenBalance(account?: string, token?: Token): TokenAmount | undefined {
|
||||
export function useTokenBalance(account?: string, token?: Token): CurrencyAmount<Token> | undefined {
|
||||
const tokenBalances = useTokenBalances(account, [token])
|
||||
if (!token) return undefined
|
||||
return tokenBalances[token.address]
|
||||
@@ -109,33 +109,33 @@ export function useTokenBalance(account?: string, token?: Token): TokenAmount |
|
||||
export function useCurrencyBalances(
|
||||
account?: string,
|
||||
currencies?: (Currency | undefined)[]
|
||||
): (CurrencyAmount | undefined)[] {
|
||||
const tokens = useMemo(() => currencies?.filter((currency): currency is Token => currency instanceof Token) ?? [], [
|
||||
): (CurrencyAmount<Currency> | undefined)[] {
|
||||
const tokens = useMemo(() => currencies?.filter((currency): currency is Token => currency?.isToken ?? false) ?? [], [
|
||||
currencies,
|
||||
])
|
||||
|
||||
const tokenBalances = useTokenBalances(account, tokens)
|
||||
const containsETH: boolean = useMemo(() => currencies?.some((currency) => currency === ETHER) ?? false, [currencies])
|
||||
const containsETH: boolean = useMemo(() => currencies?.some((currency) => currency?.isEther) ?? false, [currencies])
|
||||
const ethBalance = useETHBalances(containsETH ? [account] : [])
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
currencies?.map((currency) => {
|
||||
if (!account || !currency) return undefined
|
||||
if (currency instanceof Token) return tokenBalances[currency.address]
|
||||
if (currency === ETHER) return ethBalance[account]
|
||||
if (currency.isToken) return tokenBalances[currency.address]
|
||||
if (currency.isEther) return ethBalance[account]
|
||||
return undefined
|
||||
}) ?? [],
|
||||
[account, currencies, ethBalance, tokenBalances]
|
||||
)
|
||||
}
|
||||
|
||||
export function useCurrencyBalance(account?: string, currency?: Currency): CurrencyAmount | undefined {
|
||||
export function useCurrencyBalance(account?: string, currency?: Currency): CurrencyAmount<Currency> | undefined {
|
||||
return useCurrencyBalances(account, [currency])[0]
|
||||
}
|
||||
|
||||
// mimics useAllBalances
|
||||
export function useAllTokenBalances(): { [tokenAddress: string]: TokenAmount | undefined } {
|
||||
export function useAllTokenBalances(): { [tokenAddress: string]: CurrencyAmount<Token> | undefined } {
|
||||
const { account } = useActiveWeb3React()
|
||||
const allTokens = useAllTokens()
|
||||
const allTokensArray = useMemo(() => Object.values(allTokens ?? {}), [allTokens])
|
||||
@@ -144,22 +144,22 @@ export function useAllTokenBalances(): { [tokenAddress: string]: TokenAmount | u
|
||||
}
|
||||
|
||||
// get the total owned, unclaimed, and unharvested UNI for account
|
||||
export function useAggregateUniBalance(): TokenAmount | undefined {
|
||||
export function useAggregateUniBalance(): CurrencyAmount<Token> | undefined {
|
||||
const { account, chainId } = useActiveWeb3React()
|
||||
|
||||
const uni = chainId ? UNI[chainId] : undefined
|
||||
|
||||
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, uni)
|
||||
const uniUnclaimed: TokenAmount | undefined = useUserUnclaimedAmount(account)
|
||||
const uniUnHarvested: TokenAmount | undefined = useTotalUniEarned()
|
||||
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(account ?? undefined, uni)
|
||||
const uniUnclaimed: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
|
||||
const uniUnHarvested: CurrencyAmount<Token> | undefined = useTotalUniEarned()
|
||||
|
||||
if (!uni) return undefined
|
||||
|
||||
return new TokenAmount(
|
||||
return CurrencyAmount.fromRawAmount(
|
||||
uni,
|
||||
JSBI.add(
|
||||
JSBI.add(uniBalance?.raw ?? JSBI.BigInt(0), uniUnclaimed?.raw ?? JSBI.BigInt(0)),
|
||||
uniUnHarvested?.raw ?? JSBI.BigInt(0)
|
||||
JSBI.add(uniBalance?.quotient ?? JSBI.BigInt(0), uniUnclaimed?.quotient ?? JSBI.BigInt(0)),
|
||||
uniUnHarvested?.quotient ?? JSBI.BigInt(0)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { Token, CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { ONE_HUNDRED_PERCENT } from '../constants'
|
||||
|
||||
export function computeFiatValuePriceImpact(
|
||||
fiatValueInput: CurrencyAmount | undefined | null,
|
||||
fiatValueOutput: CurrencyAmount | undefined | null
|
||||
fiatValueInput: CurrencyAmount<Token> | undefined | null,
|
||||
fiatValueOutput: CurrencyAmount<Token> | undefined | null
|
||||
): Percent | undefined {
|
||||
if (!fiatValueOutput || !fiatValueInput) return undefined
|
||||
if (!currencyEquals(fiatValueInput.currency, fiatValueOutput.currency)) return undefined
|
||||
if (JSBI.equal(fiatValueInput.raw, JSBI.BigInt(0))) return undefined
|
||||
if (JSBI.equal(fiatValueInput.quotient, JSBI.BigInt(0))) return undefined
|
||||
const pct = ONE_HUNDRED_PERCENT.subtract(fiatValueOutput.divide(fiatValueInput))
|
||||
return new Percent(pct.numerator, pct.denominator)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { CurrencyAmount, Percent, Price } from '@uniswap/sdk-core'
|
||||
import { computePriceImpact, Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
|
||||
function computePriceImpact(midPrice: Price, inputAmount: CurrencyAmount, outputAmount: CurrencyAmount): Percent {
|
||||
const exactQuote = midPrice.raw.multiply(inputAmount.raw)
|
||||
// calculate slippage := (exactQuote - outputAmount) / exactQuote
|
||||
const slippage = exactQuote.subtract(outputAmount.raw).divide(exactQuote)
|
||||
return new Percent(slippage.numerator, slippage.denominator)
|
||||
}
|
||||
|
||||
export function computePriceImpactWithMaximumSlippage(trade: V2Trade | V3Trade, allowedSlippage: Percent): Percent {
|
||||
export function computePriceImpactWithMaximumSlippage(
|
||||
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>,
|
||||
allowedSlippage: Percent
|
||||
): Percent {
|
||||
return computePriceImpact(
|
||||
trade.route.midPrice,
|
||||
trade.maximumAmountIn(allowedSlippage),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChainId, Token, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { ChainId, Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { BigNumber } from 'ethers'
|
||||
import { ZERO_ADDRESS } from '../constants'
|
||||
import { computeUniCirculation } from './computeUniCirculation'
|
||||
@@ -12,7 +12,7 @@ describe('computeUniCirculation', () => {
|
||||
}
|
||||
|
||||
function tokenAmount(num: JSBI | string | number) {
|
||||
return new TokenAmount(token, expandTo18Decimals(num))
|
||||
return CurrencyAmount.fromRawAmount(token, expandTo18Decimals(num))
|
||||
}
|
||||
|
||||
it('before staking', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Token, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { JSBI } from '@uniswap/v2-sdk'
|
||||
import JSBI from 'jsbi'
|
||||
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { BigNumber } from 'ethers'
|
||||
import { STAKING_GENESIS } from '../state/stake/hooks'
|
||||
|
||||
@@ -57,8 +57,8 @@ function withVesting(before: JSBI, time: BigNumber, amount: number, start: numbe
|
||||
export function computeUniCirculation(
|
||||
uni: Token,
|
||||
blockTimestamp: BigNumber,
|
||||
unclaimedUni: TokenAmount | undefined
|
||||
): TokenAmount {
|
||||
unclaimedUni: CurrencyAmount<Token> | undefined
|
||||
): CurrencyAmount<Token> {
|
||||
let wholeAmount = JSBI.BigInt(USERS_AMOUNT)
|
||||
|
||||
// staking rewards
|
||||
@@ -108,6 +108,9 @@ export function computeUniCirculation(
|
||||
wholeAmount = withVesting(wholeAmount, blockTimestamp, TEAM_YEAR_3_AMOUNT, TREASURY_BEGIN_YEAR_3, TREASURY_END_YEAR_3)
|
||||
wholeAmount = withVesting(wholeAmount, blockTimestamp, TEAM_YEAR_4_AMOUNT, TREASURY_BEGIN_YEAR_4, TREASURY_END_YEAR_4)
|
||||
|
||||
const total = new TokenAmount(uni, JSBI.multiply(wholeAmount, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18))))
|
||||
const total = CurrencyAmount.fromRawAmount(
|
||||
uni,
|
||||
JSBI.multiply(wholeAmount, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18)))
|
||||
)
|
||||
return unclaimedUni ? total.subtract(unclaimedUni) : total
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Currency, ETHER, Token } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
|
||||
export function currencyId(currency: Currency): string {
|
||||
if (currency === ETHER) return 'ETH'
|
||||
if (currency instanceof Token) return currency.address
|
||||
if (currency.isEther) return 'ETH'
|
||||
if (currency.isToken) return currency.address
|
||||
throw new Error('invalid currency')
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import { Price, TokenAmount } from '@uniswap/sdk-core'
|
||||
import { Price, CurrencyAmount, Currency, Fraction } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
|
||||
export function formatTokenAmount(amount: TokenAmount | undefined, sigFigs: number) {
|
||||
export function formatTokenAmount(amount: CurrencyAmount<Currency> | undefined, sigFigs: number) {
|
||||
if (!amount) {
|
||||
return '-'
|
||||
}
|
||||
|
||||
if (JSBI.equal(amount.raw, JSBI.BigInt(0))) {
|
||||
if (JSBI.equal(amount.quotient, JSBI.BigInt(0))) {
|
||||
return '0'
|
||||
}
|
||||
|
||||
if (parseFloat(amount.toFixed(Math.min(sigFigs, amount.token.decimals))) < 0.0001) {
|
||||
return '<0.0001'
|
||||
if (amount.divide(amount.decimalScale).lessThan(new Fraction(1, 100000))) {
|
||||
return '<0.00001'
|
||||
}
|
||||
|
||||
return amount.toFixed(Math.min(sigFigs, amount.token.decimals))
|
||||
return amount.toSignificant(Math.min(sigFigs, amount.currency.decimals))
|
||||
}
|
||||
|
||||
export function formatPrice(price: Price | undefined, sigFigs: number) {
|
||||
export function formatPrice(price: Price<Currency, Currency> | undefined, sigFigs: number) {
|
||||
if (!price) {
|
||||
return '-'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Token, Price } from '@uniswap/sdk-core'
|
||||
import { tickToPrice } from '@uniswap/v3-sdk'
|
||||
|
||||
export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: number): Price | undefined {
|
||||
export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: number): Price<Token, Token> | undefined {
|
||||
if (!baseToken || !quoteToken || typeof tick !== 'number') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Currency, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { Version } from '../hooks/useToggledVersion'
|
||||
|
||||
export function getTradeVersion(trade?: V2Trade | V3Trade): Version | undefined {
|
||||
export function getTradeVersion(
|
||||
trade?: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
|
||||
): Version | undefined {
|
||||
if (!trade) return undefined
|
||||
if (trade instanceof V2Trade) return Version.v2
|
||||
return Version.v3
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user