Merge branch 'main' of https://github.com/Uniswap/v3-interface into main
This commit is contained in:
commit
699bcc25b6
@ -49,7 +49,7 @@
|
|||||||
"@uniswap/v2-sdk": "^1.0.9",
|
"@uniswap/v2-sdk": "^1.0.9",
|
||||||
"@uniswap/v3-core": "1.0.0",
|
"@uniswap/v3-core": "1.0.0",
|
||||||
"@uniswap/v3-periphery": "1.0.0",
|
"@uniswap/v3-periphery": "1.0.0",
|
||||||
"@uniswap/v3-sdk": "^1.0.1",
|
"@uniswap/v3-sdk": "^1.0.3",
|
||||||
"@web3-react/core": "^6.0.9",
|
"@web3-react/core": "^6.0.9",
|
||||||
"@web3-react/fortmatic-connector": "^6.0.9",
|
"@web3-react/fortmatic-connector": "^6.0.9",
|
||||||
"@web3-react/injected-connector": "^6.0.7",
|
"@web3-react/injected-connector": "^6.0.7",
|
||||||
|
@ -260,7 +260,7 @@ export default function CurrencyInputPanel({
|
|||||||
{!hideInput && !hideBalance && (
|
{!hideInput && !hideBalance && (
|
||||||
<FiatRow>
|
<FiatRow>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
{account && (
|
{account ? (
|
||||||
<RowFixed style={{ height: '17px' }}>
|
<RowFixed style={{ height: '17px' }}>
|
||||||
<TYPE.body
|
<TYPE.body
|
||||||
onClick={onMax}
|
onClick={onMax}
|
||||||
@ -280,6 +280,8 @@ export default function CurrencyInputPanel({
|
|||||||
<StyledBalanceMax onClick={onMax}>(Max)</StyledBalanceMax>
|
<StyledBalanceMax onClick={onMax}>(Max)</StyledBalanceMax>
|
||||||
) : null}
|
) : null}
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
|
) : (
|
||||||
|
'-'
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
||||||
|
@ -4,7 +4,7 @@ import { Text } from 'rebass'
|
|||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { Moon, Sun } from 'react-feather'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import Logo from '../../assets/svg/logo.svg'
|
import Logo from '../../assets/svg/logo.svg'
|
||||||
@ -272,7 +272,7 @@ export const StyledMenuButton = styled.button`
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
background-color: ${({ theme }) => theme.bg3};
|
background-color: ${({ theme }) => theme.bg2};
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
padding: 0.15rem 0.5rem;
|
padding: 0.15rem 0.5rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
@ -305,7 +305,7 @@ export default function Header() {
|
|||||||
|
|
||||||
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
|
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
|
||||||
// const [isDark] = useDarkModeManager()
|
// const [isDark] = useDarkModeManager()
|
||||||
const [darkMode] = useDarkModeManager()
|
const [darkMode, toggleDarkMode] = useDarkModeManager()
|
||||||
|
|
||||||
const toggleClaimModal = useToggleSelfClaimModal()
|
const toggleClaimModal = useToggleSelfClaimModal()
|
||||||
|
|
||||||
@ -381,6 +381,9 @@ export default function Header() {
|
|||||||
</AccountElement>
|
</AccountElement>
|
||||||
</HeaderElement>
|
</HeaderElement>
|
||||||
<HeaderElementWrap>
|
<HeaderElementWrap>
|
||||||
|
<StyledMenuButton onClick={() => toggleDarkMode()}>
|
||||||
|
{darkMode ? <Moon size={20} /> : <Sun size={20} />}
|
||||||
|
</StyledMenuButton>
|
||||||
<Menu />
|
<Menu />
|
||||||
</HeaderElementWrap>
|
</HeaderElementWrap>
|
||||||
</HeaderControls>
|
</HeaderControls>
|
||||||
|
@ -6,7 +6,6 @@ import { NavLink, Link as HistoryLink } from 'react-router-dom'
|
|||||||
|
|
||||||
import { ArrowLeft } from 'react-feather'
|
import { ArrowLeft } from 'react-feather'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
// import QuestionHelper from '../QuestionHelper'
|
|
||||||
import Settings from '../Settings'
|
import Settings from '../Settings'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
import { AppDispatch } from 'state'
|
import { AppDispatch } from 'state'
|
||||||
@ -86,7 +85,15 @@ export function FindPoolTabs({ origin }: { origin: string }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating: boolean }) {
|
export function AddRemoveTabs({
|
||||||
|
adding,
|
||||||
|
creating,
|
||||||
|
positionID,
|
||||||
|
}: {
|
||||||
|
adding: boolean
|
||||||
|
creating: boolean
|
||||||
|
positionID?: string | undefined
|
||||||
|
}) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
// reset states on back
|
// reset states on back
|
||||||
@ -96,7 +103,7 @@ export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating:
|
|||||||
<Tabs>
|
<Tabs>
|
||||||
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
|
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
|
||||||
<HistoryLink
|
<HistoryLink
|
||||||
to="/pool"
|
to={'/pool' + (!!positionID ? `/${positionID.toString()}` : '')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
adding && dispatch(resetMintState())
|
adding && dispatch(resetMintState())
|
||||||
}}
|
}}
|
||||||
|
@ -213,12 +213,12 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
|
|||||||
>
|
>
|
||||||
{showMore ? (
|
{showMore ? (
|
||||||
<>
|
<>
|
||||||
Manage
|
Migrate
|
||||||
<ChevronUp size="20" style={{ marginLeft: '10px' }} />
|
<ChevronUp size="20" style={{ marginLeft: '10px' }} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
Manage
|
Migrate
|
||||||
<ChevronDown size="20" style={{ marginLeft: '10px' }} />
|
<ChevronDown size="20" style={{ marginLeft: '10px' }} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -283,6 +283,7 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
|||||||
<>
|
<>
|
||||||
<RangeLineItem
|
<RangeLineItem
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setManuallyInverted(!manuallyInverted)
|
setManuallyInverted(!manuallyInverted)
|
||||||
}}
|
}}
|
||||||
|
@ -42,6 +42,7 @@ export const PositionPreview = ({
|
|||||||
: currency0
|
: currency0
|
||||||
: currency0
|
: currency0
|
||||||
)
|
)
|
||||||
|
|
||||||
const sorted = baseCurrency === currency0
|
const sorted = baseCurrency === currency0
|
||||||
const quoteCurrency = sorted ? currency1 : currency0
|
const quoteCurrency = sorted ? currency1 : currency0
|
||||||
|
|
||||||
@ -113,13 +114,14 @@ export const PositionPreview = ({
|
|||||||
<LightCard width="48%" padding="8px">
|
<LightCard width="48%" padding="8px">
|
||||||
<AutoColumn gap="4px" justify="center">
|
<AutoColumn gap="4px" justify="center">
|
||||||
<TYPE.main fontSize="12px">Min price</TYPE.main>
|
<TYPE.main fontSize="12px">Min price</TYPE.main>
|
||||||
<TYPE.mediumHeader textAlign="center">{`${priceLower.toSignificant(4)}`}</TYPE.mediumHeader>
|
<TYPE.mediumHeader textAlign="center">{`${priceLower.toSignificant(5)}`}</TYPE.mediumHeader>
|
||||||
<TYPE.main
|
<TYPE.main
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
fontSize="12px"
|
fontSize="12px"
|
||||||
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
|
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
|
||||||
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
|
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
|
||||||
{'Position will be'} <CurrencyLogo currency={baseCurrency} size="10px" /> {' 100% at this price.'}
|
Position will be <CurrencyLogo currency={baseCurrency} size="10px" /> 100% {baseCurrency?.symbol} at
|
||||||
|
this price.
|
||||||
</TYPE.small>
|
</TYPE.small>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
@ -127,14 +129,14 @@ export const PositionPreview = ({
|
|||||||
<LightCard width="48%" padding="8px">
|
<LightCard width="48%" padding="8px">
|
||||||
<AutoColumn gap="4px" justify="center">
|
<AutoColumn gap="4px" justify="center">
|
||||||
<TYPE.main fontSize="12px">Max price</TYPE.main>
|
<TYPE.main fontSize="12px">Max price</TYPE.main>
|
||||||
<TYPE.mediumHeader textAlign="center">{`${priceUpper.toSignificant(4)}`}</TYPE.mediumHeader>
|
<TYPE.mediumHeader textAlign="center">{`${priceUpper.toSignificant(5)}`}</TYPE.mediumHeader>
|
||||||
<TYPE.main
|
<TYPE.main
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
fontSize="12px"
|
fontSize="12px"
|
||||||
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
|
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
|
||||||
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
|
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
|
||||||
{' Position will be 100% '}
|
Position will be <CurrencyLogo currency={quoteCurrency} size="10px" /> 100% {quoteCurrency?.symbol} at
|
||||||
{quoteCurrency?.symbol} {' at this price.'}
|
this price.
|
||||||
</TYPE.small>
|
</TYPE.small>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
|
@ -2,10 +2,13 @@ import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
|||||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
|
import { useUserSlippageTolerance } from '../../state/user/hooks'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
|
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
|
||||||
import { computeRealizedLPFeeAmount } from '../../utils/prices'
|
import { computeRealizedLPFeeAmount } from '../../utils/prices'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { RowBetween, RowFixed } from '../Row'
|
import { RowBetween, RowFixed } from '../Row'
|
||||||
|
import FormattedPriceImpact from './FormattedPriceImpact'
|
||||||
import SwapRoute from './SwapRoute'
|
import SwapRoute from './SwapRoute'
|
||||||
|
|
||||||
export interface AdvancedSwapDetailsProps {
|
export interface AdvancedSwapDetailsProps {
|
||||||
@ -16,6 +19,7 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
|
|||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
|
|
||||||
const realizedLPFee = computeRealizedLPFeeAmount(trade)
|
const realizedLPFee = computeRealizedLPFeeAmount(trade)
|
||||||
|
const [allowedSlippage] = useUserSlippageTolerance()
|
||||||
|
|
||||||
return !trade ? null : (
|
return !trade ? null : (
|
||||||
<AutoColumn gap="8px">
|
<AutoColumn gap="8px">
|
||||||
@ -40,6 +44,17 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
|
|||||||
<SwapRoute trade={trade} />
|
<SwapRoute trade={trade} />
|
||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
|
|
||||||
|
<RowBetween>
|
||||||
|
<RowFixed>
|
||||||
|
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
|
||||||
|
Execution price vs. spot price
|
||||||
|
</TYPE.black>
|
||||||
|
</RowFixed>
|
||||||
|
<TYPE.black fontSize={12} color={theme.text1}>
|
||||||
|
<FormattedPriceImpact priceImpact={computePriceImpactWithMaximumSlippage(trade, allowedSlippage)} />
|
||||||
|
</TYPE.black>
|
||||||
|
</RowBetween>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@ import styled, { ThemeContext } from 'styled-components'
|
|||||||
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { ButtonPrimary } from '../Button'
|
import { ButtonPrimary } from '../Button'
|
||||||
import { computeFiatValuePriceImpact, isAddress, shortenAddress } from '../../utils'
|
import { isAddress, shortenAddress } from '../../utils'
|
||||||
|
import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { FiatValue } from '../CurrencyInputPanel/FiatValue'
|
import { FiatValue } from '../CurrencyInputPanel/FiatValue'
|
||||||
import CurrencyLogo from '../CurrencyLogo'
|
import CurrencyLogo from '../CurrencyLogo'
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
import { Percent } from '@uniswap/sdk-core'
|
|
||||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||||
import { Trade as V3Trade, FeeAmount } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade, FeeAmount } from '@uniswap/v3-sdk'
|
||||||
import React, { Fragment, memo, useContext } from 'react'
|
import React, { Fragment, memo, useContext } from 'react'
|
||||||
import { ChevronLeft, ChevronRight } from 'react-feather'
|
import { ChevronRight } from 'react-feather'
|
||||||
import { Flex } from 'rebass'
|
import { Flex } from 'rebass'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||||
|
|
||||||
function LabeledArrow({ fee }: { fee: FeeAmount }) {
|
function LabeledArrow({}: { fee: FeeAmount }) {
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
|
|
||||||
// todo: improve the rendering of this labeled arrow
|
// todo: render the fee in the label
|
||||||
return (
|
return <ChevronRight size={12} color={theme.text2} />
|
||||||
<>
|
|
||||||
<ChevronLeft size={12} color={theme.text2} />
|
|
||||||
<span style={{ fontSize: 12, marginTop: 2 }}>{new Percent(fee, 1_000_000).toSignificant()}%</span>
|
|
||||||
<ChevronRight size={12} color={theme.text2} />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(function SwapRoute({ trade }: { trade: V2Trade | V3Trade }) {
|
export default memo(function SwapRoute({ trade }: { trade: V2Trade | V3Trade }) {
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"v3CoreFactoryAddress": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
||||||
"weth9Address": "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6",
|
|
||||||
"multicall2Address": "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696",
|
|
||||||
"proxyAdminAddress": "0xB753548F6E010e7e680BA186F9Ca1BdAB2E90cf2",
|
|
||||||
"tickLensAddress": "0xbfd8137f7d1516D3ea5cA83523914859ec47F573",
|
|
||||||
"quoterAddress": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
|
|
||||||
"swapRouter": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
||||||
"nftDescriptorLibraryAddress": "0x42B24A95702b9986e82d421cC3568932790A48Ec",
|
|
||||||
"nonfungibleTokenPositionDescriptorAddress": "0x91ae842A5Ffd8d12023116943e72A606179294f3",
|
|
||||||
"descriptorProxyAddress": "0xEe6A57eC80ea46401049E92587E52f5Ec1c24785",
|
|
||||||
"nonfungibleTokenPositionManagerAddress": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
|
||||||
"v3MigratorAddress": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
|
|
||||||
}
|
|
@ -1,30 +1,26 @@
|
|||||||
import { ChainId } from '@uniswap/sdk-core'
|
import { ChainId } from '@uniswap/sdk-core'
|
||||||
import goerli from './goerli.json'
|
import { FACTORY_ADDRESS } from '@uniswap/v3-sdk'
|
||||||
import ropsten from './ropsten.json'
|
|
||||||
import rinkeby from './rinkeby.json'
|
|
||||||
import kovan from './kovan.json'
|
|
||||||
import mainnet from './mainnet.json'
|
|
||||||
|
|
||||||
function constructAddressMap(
|
function constructSameAddressMap(address: string): { [chainId in ChainId]: string } {
|
||||||
key: keyof typeof goerli | keyof typeof ropsten | keyof typeof rinkeby | keyof typeof mainnet
|
|
||||||
): { [chainId in ChainId]: string } {
|
|
||||||
return {
|
return {
|
||||||
[ChainId.MAINNET]: mainnet[key],
|
[ChainId.MAINNET]: address,
|
||||||
[ChainId.ROPSTEN]: ropsten[key],
|
[ChainId.ROPSTEN]: address,
|
||||||
[ChainId.KOVAN]: kovan[key],
|
[ChainId.KOVAN]: address,
|
||||||
[ChainId.RINKEBY]: rinkeby[key],
|
[ChainId.RINKEBY]: address,
|
||||||
[ChainId.GÖRLI]: goerli[key],
|
[ChainId.GÖRLI]: address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const V3_CORE_FACTORY_ADDRESSES = constructAddressMap('v3CoreFactoryAddress')
|
export const V3_CORE_FACTORY_ADDRESSES = constructSameAddressMap(FACTORY_ADDRESS)
|
||||||
|
|
||||||
export const QUOTER_ADDRESSES = constructAddressMap('quoterAddress')
|
export const QUOTER_ADDRESSES = constructSameAddressMap('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')
|
||||||
|
|
||||||
export const TICK_LENS_ADDRESSES = constructAddressMap('tickLensAddress')
|
export const TICK_LENS_ADDRESSES = constructSameAddressMap('0xbfd8137f7d1516D3ea5cA83523914859ec47F573')
|
||||||
|
|
||||||
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = constructAddressMap('nonfungibleTokenPositionManagerAddress')
|
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = constructSameAddressMap(
|
||||||
|
'0xC36442b4a4522E871399CD717aBDD847Ab11FE88'
|
||||||
|
)
|
||||||
|
|
||||||
export const SWAP_ROUTER_ADDRESSES = constructAddressMap('swapRouter')
|
export const SWAP_ROUTER_ADDRESSES = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564')
|
||||||
|
|
||||||
export const V3_MIGRATOR_ADDRESSES = constructAddressMap('v3MigratorAddress')
|
export const V3_MIGRATOR_ADDRESSES = constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34')
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"v3CoreFactoryAddress": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
||||||
"weth9Address": "0xd0A1E359811322d97991E03f863a0C30C2cF029C",
|
|
||||||
"multicall2Address": "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696",
|
|
||||||
"proxyAdminAddress": "0xB753548F6E010e7e680BA186F9Ca1BdAB2E90cf2",
|
|
||||||
"tickLensAddress": "0xbfd8137f7d1516D3ea5cA83523914859ec47F573",
|
|
||||||
"quoterAddress": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
|
|
||||||
"swapRouter": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
||||||
"nftDescriptorLibraryAddress": "0x42B24A95702b9986e82d421cC3568932790A48Ec",
|
|
||||||
"nonfungibleTokenPositionDescriptorAddress": "0x91ae842A5Ffd8d12023116943e72A606179294f3",
|
|
||||||
"descriptorProxyAddress": "0xEe6A57eC80ea46401049E92587E52f5Ec1c24785",
|
|
||||||
"nonfungibleTokenPositionManagerAddress": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
|
||||||
"v3MigratorAddress": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"v3CoreFactoryAddress": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
||||||
"weth9Address": "0xc778417E063141139Fce010982780140Aa0cD5Ab",
|
|
||||||
"multicall2Address": "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696",
|
|
||||||
"proxyAdminAddress": "0xB753548F6E010e7e680BA186F9Ca1BdAB2E90cf2",
|
|
||||||
"tickLensAddress": "0xbfd8137f7d1516D3ea5cA83523914859ec47F573",
|
|
||||||
"quoterAddress": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
|
|
||||||
"swapRouter": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
||||||
"nftDescriptorLibraryAddress": "0x42B24A95702b9986e82d421cC3568932790A48Ec",
|
|
||||||
"nonfungibleTokenPositionDescriptorAddress": "0x91ae842A5Ffd8d12023116943e72A606179294f3",
|
|
||||||
"descriptorProxyAddress": "0xEe6A57eC80ea46401049E92587E52f5Ec1c24785",
|
|
||||||
"nonfungibleTokenPositionManagerAddress": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
|
||||||
"v3MigratorAddress": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"v3CoreFactoryAddress": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
||||||
"weth9Address": "0xc778417E063141139Fce010982780140Aa0cD5Ab",
|
|
||||||
"multicall2Address": "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696",
|
|
||||||
"proxyAdminAddress": "0xB753548F6E010e7e680BA186F9Ca1BdAB2E90cf2",
|
|
||||||
"tickLensAddress": "0xbfd8137f7d1516D3ea5cA83523914859ec47F573",
|
|
||||||
"quoterAddress": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
|
|
||||||
"swapRouter": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
||||||
"nftDescriptorLibraryAddress": "0x42B24A95702b9986e82d421cC3568932790A48Ec",
|
|
||||||
"nonfungibleTokenPositionDescriptorAddress": "0x91ae842A5Ffd8d12023116943e72A606179294f3",
|
|
||||||
"descriptorProxyAddress": "0xEe6A57eC80ea46401049E92587E52f5Ec1c24785",
|
|
||||||
"nonfungibleTokenPositionManagerAddress": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
|
||||||
"v3MigratorAddress": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"v3CoreFactoryAddress": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
||||||
"weth9Address": "0xc778417E063141139Fce010982780140Aa0cD5Ab",
|
|
||||||
"multicall2Address": "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696",
|
|
||||||
"proxyAdminAddress": "0xB753548F6E010e7e680BA186F9Ca1BdAB2E90cf2",
|
|
||||||
"tickLensAddress": "0xbfd8137f7d1516D3ea5cA83523914859ec47F573",
|
|
||||||
"quoterAddress": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
|
|
||||||
"swapRouter": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
||||||
"nftDescriptorLibraryAddress": "0x42B24A95702b9986e82d421cC3568932790A48Ec",
|
|
||||||
"nonfungibleTokenPositionDescriptorAddress": "0x91ae842A5Ffd8d12023116943e72A606179294f3",
|
|
||||||
"descriptorProxyAddress": "0xEe6A57eC80ea46401049E92587E52f5Ec1c24785",
|
|
||||||
"nonfungibleTokenPositionManagerAddress": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
|
||||||
"v3MigratorAddress": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
|
|
||||||
}
|
|
@ -34,7 +34,7 @@ const PERMITTABLE_TOKENS: {
|
|||||||
}
|
}
|
||||||
} = {
|
} = {
|
||||||
[ChainId.MAINNET]: {
|
[ChainId.MAINNET]: {
|
||||||
[USDC.address]: { type: PermitType.AMOUNT, name: 'USD Coin', version: '1' },
|
[USDC.address]: { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
|
||||||
[DAI.address]: { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
|
[DAI.address]: { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
|
||||||
[UNI[ChainId.MAINNET].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
[UNI[ChainId.MAINNET].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||||
},
|
},
|
||||||
@ -44,6 +44,7 @@ const PERMITTABLE_TOKENS: {
|
|||||||
},
|
},
|
||||||
[ChainId.ROPSTEN]: {
|
[ChainId.ROPSTEN]: {
|
||||||
[UNI[ChainId.ROPSTEN].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
[UNI[ChainId.ROPSTEN].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||||
|
['0x07865c6E87B9F70255377e024ace6630C1Eaa37F']: { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
|
||||||
},
|
},
|
||||||
[ChainId.GÖRLI]: {
|
[ChainId.GÖRLI]: {
|
||||||
[UNI[ChainId.GÖRLI].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
[UNI[ChainId.GÖRLI].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useContext, useMemo, useState } from 'react'
|
import React, { useCallback, useContext, useMemo, useState, useEffect } from 'react'
|
||||||
import { TransactionResponse } from '@ethersproject/providers'
|
import { TransactionResponse } from '@ethersproject/providers'
|
||||||
import { Currency, TokenAmount, ETHER, currencyEquals } from '@uniswap/sdk-core'
|
import { Currency, TokenAmount, ETHER, currencyEquals } from '@uniswap/sdk-core'
|
||||||
import { WETH9 } from '@uniswap/sdk-core'
|
import { WETH9 } from '@uniswap/sdk-core'
|
||||||
@ -89,6 +89,13 @@ export default function AddLiquidity({
|
|||||||
[currencyA, currencyB, baseCurrency]
|
[currencyA, currencyB, baseCurrency]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setBaseCurrency(currencyA)
|
||||||
|
return () => {
|
||||||
|
setBaseCurrency(undefined)
|
||||||
|
}
|
||||||
|
}, [currencyA, currencyB])
|
||||||
|
|
||||||
// mint state
|
// mint state
|
||||||
const { independentField, typedValue, startPriceTypedValue } = useMintState()
|
const { independentField, typedValue, startPriceTypedValue } = useMintState()
|
||||||
|
|
||||||
@ -371,7 +378,7 @@ export default function AddLiquidity({
|
|||||||
pendingText={pendingText}
|
pendingText={pendingText}
|
||||||
/>
|
/>
|
||||||
<AppBody>
|
<AppBody>
|
||||||
<AddRemoveTabs creating={false} adding={true} />
|
<AddRemoveTabs creating={false} adding={true} positionID={tokenId} />
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<AutoColumn gap="32px">
|
<AutoColumn gap="32px">
|
||||||
{!hasExistingPosition && (
|
{!hasExistingPosition && (
|
||||||
@ -383,7 +390,6 @@ export default function AddLiquidity({
|
|||||||
<TYPE.blue fontSize="12px">Clear All</TYPE.blue>
|
<TYPE.blue fontSize="12px">Clear All</TYPE.blue>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
|
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<CurrencyDropdown
|
<CurrencyDropdown
|
||||||
value={formattedAmounts[Field.CURRENCY_A]}
|
value={formattedAmounts[Field.CURRENCY_A]}
|
||||||
@ -565,7 +571,6 @@ export default function AddLiquidity({
|
|||||||
onMax={() => {
|
onMax={() => {
|
||||||
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
|
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
|
||||||
}}
|
}}
|
||||||
onCurrencySelect={handleCurrencyASelect}
|
|
||||||
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
|
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
|
||||||
currency={currencies[Field.CURRENCY_A]}
|
currency={currencies[Field.CURRENCY_A]}
|
||||||
id="add-liquidity-input-tokena"
|
id="add-liquidity-input-tokena"
|
||||||
@ -576,7 +581,6 @@ export default function AddLiquidity({
|
|||||||
<CurrencyInputPanel
|
<CurrencyInputPanel
|
||||||
value={formattedAmounts[Field.CURRENCY_B]}
|
value={formattedAmounts[Field.CURRENCY_B]}
|
||||||
onUserInput={onFieldBInput}
|
onUserInput={onFieldBInput}
|
||||||
onCurrencySelect={handleCurrencyBSelect}
|
|
||||||
onMax={() => {
|
onMax={() => {
|
||||||
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
|
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
|
||||||
}}
|
}}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { Fraction, Price, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
import { Fraction, Price, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
||||||
import { FACTORY_ADDRESS, JSBI } from '@uniswap/v2-sdk'
|
import { FACTORY_ADDRESS, JSBI } from '@uniswap/v2-sdk'
|
||||||
import { Redirect, RouteComponentProps } from 'react-router'
|
import { Redirect, RouteComponentProps } from 'react-router'
|
||||||
@ -113,7 +113,7 @@ function V2PairMigration({
|
|||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
const pairFactory = useSingleCallResult(pair, 'factory')
|
const pairFactory = useSingleCallResult(pair, 'factory')
|
||||||
const isNotUniswap = pairFactory.result?.[0] !== FACTORY_ADDRESS
|
const isNotUniswap = pairFactory.result?.[0] !== FACTORY_ADDRESS ?? false
|
||||||
|
|
||||||
const deadline = useTransactionDeadline() // custom from users settings
|
const deadline = useTransactionDeadline() // custom from users settings
|
||||||
const blockTimestamp = useCurrentBlockTimestamp()
|
const blockTimestamp = useCurrentBlockTimestamp()
|
||||||
@ -163,6 +163,11 @@ function V2PairMigration({
|
|||||||
baseToken
|
baseToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// reset the initial state, dont need cleanup token always defined
|
||||||
|
useEffect(() => {
|
||||||
|
setBaseToken(token0)
|
||||||
|
}, [baseToken, token0])
|
||||||
|
|
||||||
// get value and prices at ticks
|
// get value and prices at ticks
|
||||||
const { [Bound.LOWER]: tickLower, [Bound.UPPER]: tickUpper } = ticks
|
const { [Bound.LOWER]: tickLower, [Bound.UPPER]: tickUpper } = ticks
|
||||||
const { [Bound.LOWER]: priceLower, [Bound.UPPER]: priceUpper } = pricesAtTicks
|
const { [Bound.LOWER]: priceLower, [Bound.UPPER]: priceUpper } = pricesAtTicks
|
||||||
@ -218,12 +223,12 @@ function V2PairMigration({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const refund0 = useMemo(
|
const refund0 = useMemo(
|
||||||
() => v3Amount0Min && new TokenAmount(token0, JSBI.subtract(token0Value.raw, v3Amount0Min.raw)),
|
() => position && new TokenAmount(token0, JSBI.subtract(token0Value.raw, position.amount0.raw)),
|
||||||
[token0Value, v3Amount0Min, token0]
|
[token0Value, position, token0]
|
||||||
)
|
)
|
||||||
const refund1 = useMemo(
|
const refund1 = useMemo(
|
||||||
() => v3Amount1Min && new TokenAmount(token1, JSBI.subtract(token1Value.raw, v3Amount1Min.raw)),
|
() => position && new TokenAmount(token1, JSBI.subtract(token1Value.raw, position.amount1.raw)),
|
||||||
[token1Value, v3Amount1Min, token1]
|
[token1Value, position, token1]
|
||||||
)
|
)
|
||||||
|
|
||||||
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
|
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
|
||||||
@ -516,13 +521,13 @@ function V2PairMigration({
|
|||||||
</YellowCard>
|
</YellowCard>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{v3Amount0Min && v3Amount1Min ? (
|
{position ? (
|
||||||
<DarkGreyCard>
|
<DarkGreyCard>
|
||||||
<AutoColumn gap="md">
|
<AutoColumn gap="md">
|
||||||
<LiquidityInfo token0Amount={v3Amount0Min} token1Amount={v3Amount1Min} />
|
<LiquidityInfo token0Amount={position.amount0} token1Amount={position.amount1} />
|
||||||
{chainId && refund0 && refund1 ? (
|
{chainId && refund0 && refund1 ? (
|
||||||
<TYPE.black fontSize={12}>
|
<TYPE.black fontSize={12}>
|
||||||
{formatTokenAmount(refund0, 4)} {token0.equals(WETH9[chainId]) ? 'ETH' : token0.symbol} and{' '}
|
At least {formatTokenAmount(refund0, 4)} {token0.equals(WETH9[chainId]) ? 'ETH' : token0.symbol} and{' '}
|
||||||
{formatTokenAmount(refund1, 4)} {token1.equals(WETH9[chainId]) ? 'ETH' : token1.symbol} will be
|
{formatTokenAmount(refund1, 4)} {token1.equals(WETH9[chainId]) ? 'ETH' : token1.symbol} will be
|
||||||
refunded to your wallet due to selected price range.
|
refunded to your wallet due to selected price range.
|
||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
|
@ -21,15 +21,15 @@ const CTASection = styled.section`
|
|||||||
|
|
||||||
const CTA1 = styled(ExternalLink)`
|
const CTA1 = styled(ExternalLink)`
|
||||||
background-size: 40px 40px;
|
background-size: 40px 40px;
|
||||||
background-image: linear-gradient(to right, #2d2d2d 1px, transparent 1px),
|
background-image: linear-gradient(to right, ${({ theme }) => theme.bg3} 1px, transparent 1px),
|
||||||
linear-gradient(to bottom, #2d2d2d 1px, transparent 1px);
|
linear-gradient(to bottom, ${({ theme }) => theme.bg3} 1px, transparent 1px);
|
||||||
background-color: ${({ theme }) => theme.bg1};
|
background-color: ${({ theme }) => theme.bg2};
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border: 1px solid ${({ theme }) => theme.bg4};
|
border: 1px solid ${({ theme }) => theme.bg3};
|
||||||
|
|
||||||
* {
|
* {
|
||||||
color: ${({ theme }) => theme.text1};
|
color: ${({ theme }) => theme.text1};
|
||||||
|
@ -12,9 +12,9 @@ import styled from 'styled-components'
|
|||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
import { RowBetween, RowFixed } from 'components/Row'
|
import { RowBetween, RowFixed } from 'components/Row'
|
||||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||||
import { HideExtraSmall, TYPE } from 'theme'
|
import { ExternalLink, HideExtraSmall, TYPE } from 'theme'
|
||||||
import Badge from 'components/Badge'
|
import Badge from 'components/Badge'
|
||||||
import { calculateGasMargin } from 'utils'
|
import { calculateGasMargin, getEtherscanLink } from 'utils'
|
||||||
import { ButtonConfirmed, ButtonPrimary, ButtonGray } from 'components/Button'
|
import { ButtonConfirmed, ButtonPrimary, ButtonGray } from 'components/Button'
|
||||||
import { DarkCard, DarkGreyCard, LightCard } from 'components/Card'
|
import { DarkCard, DarkGreyCard, LightCard } from 'components/Card'
|
||||||
import CurrencyLogo from 'components/CurrencyLogo'
|
import CurrencyLogo from 'components/CurrencyLogo'
|
||||||
@ -131,16 +131,12 @@ function CurrentPriceCard({
|
|||||||
pool,
|
pool,
|
||||||
currencyQuote,
|
currencyQuote,
|
||||||
currencyBase,
|
currencyBase,
|
||||||
ratio,
|
|
||||||
}: {
|
}: {
|
||||||
inverted?: boolean
|
inverted?: boolean
|
||||||
pool?: Pool | null
|
pool?: Pool | null
|
||||||
currencyQuote?: Currency
|
currencyQuote?: Currency
|
||||||
currencyBase?: Currency
|
currencyBase?: Currency
|
||||||
ratio?: number
|
|
||||||
}) {
|
}) {
|
||||||
const theme = useTheme()
|
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
if (!pool || !currencyQuote || !currencyBase) {
|
if (!pool || !currencyQuote || !currencyBase) {
|
||||||
return null
|
return null
|
||||||
@ -155,26 +151,23 @@ function CurrentPriceCard({
|
|||||||
</TYPE.mediumHeader>
|
</TYPE.mediumHeader>
|
||||||
<ExtentsText>{currencyQuote?.symbol + ' / ' + currencyBase?.symbol}</ExtentsText>
|
<ExtentsText>{currencyQuote?.symbol + ' / ' + currencyBase?.symbol}</ExtentsText>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
|
|
||||||
{typeof ratio === 'number' && (
|
|
||||||
<TYPE.small color={theme.text3} textAlign="center" style={{ marginTop: '8px' }}>
|
|
||||||
Your position is currently {ratio}% {currencyBase?.symbol} and {100 - ratio}% {currencyQuote?.symbol}
|
|
||||||
</TYPE.small>
|
|
||||||
)}
|
|
||||||
</LightCard>
|
</LightCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRatio(lower: Price, current: Price, upper: Price) {
|
function getRatio(lower: Price, current: Price, upper: Price) {
|
||||||
try {
|
try {
|
||||||
|
if (!current.greaterThan(lower)) {
|
||||||
|
return 100
|
||||||
|
} else if (!current.lessThan(upper)) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
const a = Number.parseFloat(lower.toSignificant(15))
|
const a = Number.parseFloat(lower.toSignificant(15))
|
||||||
const b = Number.parseFloat(upper.toSignificant(15))
|
const b = Number.parseFloat(upper.toSignificant(15))
|
||||||
const c = Number.parseFloat(current.toSignificant(15))
|
const c = Number.parseFloat(current.toSignificant(15))
|
||||||
|
|
||||||
let ratio = Math.floor(((Math.sqrt(a * b) - Math.sqrt(b * c)) / (c - Math.sqrt(b * c))) * 100)
|
const ratio = Math.floor((1 / ((Math.sqrt(a * b) - Math.sqrt(b * c)) / (c - Math.sqrt(b * c)) + 1)) * 100)
|
||||||
if (ratio > 100) {
|
|
||||||
ratio -= 100
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ratio < 0 || ratio > 100) {
|
if (ratio < 0 || ratio > 100) {
|
||||||
throw Error('Out of range')
|
throw Error('Out of range')
|
||||||
@ -243,6 +236,9 @@ export function PositionPage({
|
|||||||
: undefined
|
: undefined
|
||||||
}, [inverted, pool, priceLower, priceUpper])
|
}, [inverted, pool, priceLower, priceUpper])
|
||||||
|
|
||||||
|
// really can't figure out why i have to do this, getting conditional hook call errors otherwise
|
||||||
|
const WORKAROUND = typeof ratio === 'number' ? (inverted ? 100 - ratio : ratio) : undefined
|
||||||
|
|
||||||
// fees
|
// fees
|
||||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails)
|
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails)
|
||||||
|
|
||||||
@ -460,6 +456,9 @@ export function PositionPage({
|
|||||||
<div style={{ marginRight: 12 }}>
|
<div style={{ marginRight: 12 }}>
|
||||||
<img height="400px" src={metadata.result.image} />
|
<img height="400px" src={metadata.result.image} />
|
||||||
</div>
|
</div>
|
||||||
|
{typeof chainId === 'number' && owner && !ownsNFT ? (
|
||||||
|
<ExternalLink href={getEtherscanLink(chainId, owner, 'address')}>Owner</ExternalLink>
|
||||||
|
) : null}
|
||||||
</DarkCard>
|
</DarkCard>
|
||||||
) : (
|
) : (
|
||||||
<DarkCard
|
<DarkCard
|
||||||
@ -497,12 +496,12 @@ export function PositionPage({
|
|||||||
</RowFixed>
|
</RowFixed>
|
||||||
<RowFixed>
|
<RowFixed>
|
||||||
<TYPE.main>
|
<TYPE.main>
|
||||||
{inverted ? position?.amount0.toSignificant(4) : position?.amount1.toSignificant(4)} (
|
{inverted ? position?.amount0.toSignificant(4) : position?.amount1.toSignificant(4)}
|
||||||
</TYPE.main>
|
</TYPE.main>
|
||||||
{typeof ratio === 'number' && (
|
{typeof ratio === 'number' && (
|
||||||
<DarkGreyCard padding="4px 6px" style={{ width: 'fit-content', marginLeft: '8px' }}>
|
<DarkGreyCard padding="4px 6px" style={{ width: 'fit-content', marginLeft: '8px' }}>
|
||||||
<TYPE.main color={theme.text2} fontSize={11}>
|
<TYPE.main color={theme.text2} fontSize={11}>
|
||||||
{100 - ratio}%
|
{inverted ? ratio : 100 - ratio}%
|
||||||
</TYPE.main>
|
</TYPE.main>
|
||||||
</DarkGreyCard>
|
</DarkGreyCard>
|
||||||
)}
|
)}
|
||||||
@ -515,12 +514,12 @@ export function PositionPage({
|
|||||||
</RowFixed>
|
</RowFixed>
|
||||||
<RowFixed>
|
<RowFixed>
|
||||||
<TYPE.main>
|
<TYPE.main>
|
||||||
{inverted ? position?.amount1.toSignificant(4) : position?.amount0.toSignificant(4)} (
|
{inverted ? position?.amount1.toSignificant(4) : position?.amount0.toSignificant(4)}
|
||||||
</TYPE.main>
|
</TYPE.main>
|
||||||
{typeof ratio === 'number' && (
|
{typeof ratio === 'number' && (
|
||||||
<DarkGreyCard padding="4px 6px" style={{ width: 'fit-content', marginLeft: '8px' }}>
|
<DarkGreyCard padding="4px 6px" style={{ width: 'fit-content', marginLeft: '8px' }}>
|
||||||
<TYPE.main color={theme.text2} fontSize={11}>
|
<TYPE.main color={theme.text2} fontSize={11}>
|
||||||
{ratio}%
|
{WORKAROUND}%
|
||||||
</TYPE.main>
|
</TYPE.main>
|
||||||
</DarkGreyCard>
|
</DarkGreyCard>
|
||||||
)}
|
)}
|
||||||
@ -546,7 +545,7 @@ export function PositionPage({
|
|||||||
</TYPE.largeHeader>
|
</TYPE.largeHeader>
|
||||||
)}
|
)}
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
{feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) || !!collectMigrationHash ? (
|
{ownsNFT && (feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) || !!collectMigrationHash) ? (
|
||||||
<ButtonConfirmed
|
<ButtonConfirmed
|
||||||
disabled={collecting || !!collectMigrationHash}
|
disabled={collecting || !!collectMigrationHash}
|
||||||
confirmed={!!collectMigrationHash && !isCollectPending}
|
confirmed={!!collectMigrationHash && !isCollectPending}
|
||||||
@ -644,10 +643,12 @@ export function PositionPage({
|
|||||||
<ExtentsText>Min price</ExtentsText>
|
<ExtentsText>Min price</ExtentsText>
|
||||||
<TYPE.mediumHeader textAlign="center">{priceLower?.toSignificant(4)}</TYPE.mediumHeader>
|
<TYPE.mediumHeader textAlign="center">{priceLower?.toSignificant(4)}</TYPE.mediumHeader>
|
||||||
<ExtentsText> {currencyQuote?.symbol + ' / ' + currencyBase?.symbol}</ExtentsText>
|
<ExtentsText> {currencyQuote?.symbol + ' / ' + currencyBase?.symbol}</ExtentsText>
|
||||||
<TYPE.small color={theme.text3}>
|
|
||||||
{' Your position is will be 100% '}
|
{inRange && (
|
||||||
{currencyBase?.symbol} {' at this price.'}
|
<TYPE.small color={theme.text3}>
|
||||||
</TYPE.small>
|
Your position will be 100% {currencyBase?.symbol} at this price.
|
||||||
|
</TYPE.small>
|
||||||
|
)}
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
|
|
||||||
@ -657,10 +658,12 @@ export function PositionPage({
|
|||||||
<ExtentsText>Max price</ExtentsText>
|
<ExtentsText>Max price</ExtentsText>
|
||||||
<TYPE.mediumHeader textAlign="center">{priceUpper?.toSignificant(4)}</TYPE.mediumHeader>
|
<TYPE.mediumHeader textAlign="center">{priceUpper?.toSignificant(4)}</TYPE.mediumHeader>
|
||||||
<ExtentsText> {currencyQuote?.symbol + ' / ' + currencyBase?.symbol}</ExtentsText>
|
<ExtentsText> {currencyQuote?.symbol + ' / ' + currencyBase?.symbol}</ExtentsText>
|
||||||
<TYPE.small color={theme.text3}>
|
|
||||||
{' Your position is will be 100% '}
|
{inRange && (
|
||||||
{currencyQuote?.symbol} {' at this price.'}
|
<TYPE.small color={theme.text3}>
|
||||||
</TYPE.small>
|
Your position will be 100% {currencyQuote?.symbol} at this price.
|
||||||
|
</TYPE.small>
|
||||||
|
)}
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
@ -669,7 +672,6 @@ export function PositionPage({
|
|||||||
pool={pool}
|
pool={pool}
|
||||||
currencyQuote={currencyQuote}
|
currencyQuote={currencyQuote}
|
||||||
currencyBase={currencyBase}
|
currencyBase={currencyBase}
|
||||||
ratio={typeof ratio === 'number' && inRange ? (inverted ? 100 - ratio : ratio) : undefined}
|
|
||||||
/>
|
/>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</DarkCard>
|
</DarkCard>
|
||||||
|
@ -272,7 +272,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
|||||||
pendingText={pendingText}
|
pendingText={pendingText}
|
||||||
/>
|
/>
|
||||||
<AppBody>
|
<AppBody>
|
||||||
<AddRemoveTabs creating={false} adding={false} />
|
<AddRemoveTabs creating={false} adding={false} positionID={tokenId.toString()} />
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{position ? (
|
{position ? (
|
||||||
<AutoColumn gap="lg">
|
<AutoColumn gap="lg">
|
||||||
|
@ -48,7 +48,7 @@ import {
|
|||||||
} from '../../state/swap/hooks'
|
} from '../../state/swap/hooks'
|
||||||
import { useExpertModeManager, useUserSingleHopOnly, useUserSlippageTolerance } from '../../state/user/hooks'
|
import { useExpertModeManager, useUserSingleHopOnly, useUserSlippageTolerance } from '../../state/user/hooks'
|
||||||
import { LinkStyledButton, TYPE } from '../../theme'
|
import { LinkStyledButton, TYPE } from '../../theme'
|
||||||
import { computeFiatValuePriceImpact } from '../../utils'
|
import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact'
|
||||||
import { getTradeVersion } from '../../utils/getTradeVersion'
|
import { getTradeVersion } from '../../utils/getTradeVersion'
|
||||||
import { isTradeBetter } from '../../utils/isTradeBetter'
|
import { isTradeBetter } from '../../utils/isTradeBetter'
|
||||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||||
|
18
src/utils/computePriceImpactWithMaximumSlippage.tsx
Normal file
18
src/utils/computePriceImpactWithMaximumSlippage.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { CurrencyAmount, Percent, Price } 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 {
|
||||||
|
return computePriceImpact(
|
||||||
|
trade.route.midPrice,
|
||||||
|
trade.maximumAmountIn(allowedSlippage),
|
||||||
|
trade.minimumAmountOut(allowedSlippage)
|
||||||
|
)
|
||||||
|
}
|
@ -119,4 +119,3 @@ export function supportedChainId(chainId: number): ChainId | undefined {
|
|||||||
export function formattedFeeAmount(feeAmount: FeeAmount): number {
|
export function formattedFeeAmount(feeAmount: FeeAmount): number {
|
||||||
return feeAmount / 10000
|
return feeAmount / 10000
|
||||||
}
|
}
|
||||||
export { computeFiatValuePriceImpact } from './computeFiatValuePriceImpact'
|
|
||||||
|
@ -41,7 +41,7 @@ export function computeRealizedLPFeeAmount(trade?: V2Trade | V3Trade | null): Cu
|
|||||||
: ONE_HUNDRED_PERCENT.subtract(
|
: ONE_HUNDRED_PERCENT.subtract(
|
||||||
trade.route.pools.reduce<Fraction>(
|
trade.route.pools.reduce<Fraction>(
|
||||||
(currentFee: Fraction, pool): Fraction =>
|
(currentFee: Fraction, pool): Fraction =>
|
||||||
currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(pool.fee, 10_000))),
|
currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(pool.fee, 1_000_000))),
|
||||||
ONE_HUNDRED_PERCENT
|
ONE_HUNDRED_PERCENT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -4149,10 +4149,10 @@
|
|||||||
"@uniswap/v3-core" "1.0.0"
|
"@uniswap/v3-core" "1.0.0"
|
||||||
base64-sol "1.0.1"
|
base64-sol "1.0.1"
|
||||||
|
|
||||||
"@uniswap/v3-sdk@^1.0.1":
|
"@uniswap/v3-sdk@^1.0.3":
|
||||||
version "1.0.1"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-1.0.1.tgz#a44f7de0fff2964dcd7bb848ccd55716c78d088e"
|
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-1.0.3.tgz#8f47b5f8cc8997992811a242ef202f9a8c4797cf"
|
||||||
integrity sha512-5oOJKnAInJq3uTHNjKj2tw/YQndNW6I4bQglEjGyi8te7IO75lJunMtqwjAKVIDMyoKT7iIR25p4t1ZZLEgiHQ==
|
integrity sha512-izIrHTAXCeMhfye0nHntoAS0UTbpa8HyGSD++Zmy+kROeb2gSAcpXvnLHzRDIPxq0G4rOH0h05Y5fhHAxaXj5w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ethersproject/abi" "^5.0.12"
|
"@ethersproject/abi" "^5.0.12"
|
||||||
"@ethersproject/solidity" "^5.0.9"
|
"@ethersproject/solidity" "^5.0.9"
|
||||||
|
Loading…
Reference in New Issue
Block a user