Finish migration (#42)
* start migration (wip) abstract some add liquidity components bump deploy version * add slippage params
This commit is contained in:
parent
9f5584c37d
commit
9fc096d091
@ -48,8 +48,8 @@
|
|||||||
"@uniswap/v2-core": "1.0.0",
|
"@uniswap/v2-core": "1.0.0",
|
||||||
"@uniswap/v2-periphery": "^1.1.0-beta.0",
|
"@uniswap/v2-periphery": "^1.1.0-beta.0",
|
||||||
"@uniswap/v2-sdk": "^1.0.6",
|
"@uniswap/v2-sdk": "^1.0.6",
|
||||||
"@uniswap/v3-core": "^1.0.0-rc.0",
|
"@uniswap/v3-core": "^1.0.0-rc.1",
|
||||||
"@uniswap/v3-periphery": "^1.0.0-beta.17",
|
"@uniswap/v3-periphery": "^1.0.0-beta.19",
|
||||||
"@uniswap/v3-sdk": "^1.0.0-alpha.11",
|
"@uniswap/v3-sdk": "^1.0.0-alpha.11",
|
||||||
"@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",
|
||||||
|
@ -109,7 +109,6 @@
|
|||||||
"poolType": "Select a fee tier based on your preferred liquidity provider fee.",
|
"poolType": "Select a fee tier based on your preferred liquidity provider fee.",
|
||||||
"rangeWarning": "Your liquidity will only be active and earning fees when the rate of the pool is within this price range.",
|
"rangeWarning": "Your liquidity will only be active and earning fees when the rate of the pool is within this price range.",
|
||||||
"chooseLiquidityAmount": "Choose an amount of tokens to open this liquidity position. If you don’t have enough tokens you can trade for them with a Swap.",
|
"chooseLiquidityAmount": "Choose an amount of tokens to open this liquidity position. If you don’t have enough tokens you can trade for them with a Swap.",
|
||||||
"selectRange": "Select Liquidity Range",
|
|
||||||
"inputTokenDynamic": "Input {{label}}",
|
"inputTokenDynamic": "Input {{label}}",
|
||||||
"selectStartingPrice": "Select Starting Price",
|
"selectStartingPrice": "Select Starting Price",
|
||||||
"newPoolPrice": "Select the market rate for the tokens being added."
|
"newPoolPrice": "Select the market rate for the tokens being added."
|
||||||
|
@ -2,48 +2,48 @@ import { ChainId } from '@uniswap/sdk-core'
|
|||||||
|
|
||||||
export const FACTORY_ADDRESSES: { [chainId in ChainId]: string } = {
|
export const FACTORY_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||||
[ChainId.MAINNET]: '',
|
[ChainId.MAINNET]: '',
|
||||||
[ChainId.ROPSTEN]: '0xb31b9A7b331eA8993bdfC67c650eDbfc9256eC62',
|
[ChainId.ROPSTEN]: '0x5BbFe6FF864718cD1cE0F126be99e96239E3caDD',
|
||||||
[ChainId.RINKEBY]: '0xD8A6adFB40Ba3B3CdA9F985BF1fdbDc0c1d7591e',
|
[ChainId.RINKEBY]: '0x7ba6C6345E7a73cC0D41d762C7Db9cb3DB721396',
|
||||||
[ChainId.GÖRLI]: '0xb31b9A7b331eA8993bdfC67c650eDbfc9256eC62',
|
[ChainId.GÖRLI]: '0x5BbFe6FF864718cD1cE0F126be99e96239E3caDD',
|
||||||
[ChainId.KOVAN]: '',
|
[ChainId.KOVAN]: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TICK_LENS_ADDRESSES: { [chainId in ChainId]: string } = {
|
export const TICK_LENS_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||||
[ChainId.MAINNET]: '',
|
[ChainId.MAINNET]: '',
|
||||||
[ChainId.ROPSTEN]: '0x8E984b597F19E8D0FDd0b5bAfDb1d0ae4386455f',
|
[ChainId.ROPSTEN]: '0x1C8beBE5596b60A84e6d737229aDd502E14276Eb',
|
||||||
[ChainId.RINKEBY]: '0xB1c59e8Ae4B72f63a5a9CB9c25A9253096A4b126',
|
[ChainId.RINKEBY]: '0xd4013a706fa79487989b595Df35eF8AD1ffBb422',
|
||||||
[ChainId.GÖRLI]: '0x8E984b597F19E8D0FDd0b5bAfDb1d0ae4386455f',
|
[ChainId.GÖRLI]: '0x1C8beBE5596b60A84e6d737229aDd502E14276Eb',
|
||||||
[ChainId.KOVAN]: '',
|
[ChainId.KOVAN]: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: { [chainId in ChainId]: string } = {
|
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||||
[ChainId.MAINNET]: '',
|
[ChainId.MAINNET]: '',
|
||||||
[ChainId.ROPSTEN]: '0x29e4bF3bFD649b807B4C752c01023E535094F6Bc',
|
[ChainId.ROPSTEN]: '0x921647f0c094e2e59CDE6DEfafD77743012f52bd',
|
||||||
[ChainId.RINKEBY]: '0xee9e30637f84Bbf929042A9118c6E20023dab833',
|
[ChainId.RINKEBY]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65',
|
||||||
[ChainId.GÖRLI]: '0x29e4bF3bFD649b807B4C752c01023E535094F6Bc',
|
[ChainId.GÖRLI]: '0x921647f0c094e2e59CDE6DEfafD77743012f52bd',
|
||||||
[ChainId.KOVAN]: '',
|
[ChainId.KOVAN]: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NONFUNGIBLE_TOKEN_POSITION_DESCRIPTOR_ADDRESSES: { [chainId in ChainId]: string } = {
|
export const NONFUNGIBLE_TOKEN_POSITION_DESCRIPTOR_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||||
[ChainId.MAINNET]: '',
|
[ChainId.MAINNET]: '',
|
||||||
[ChainId.ROPSTEN]: '0xa0588c89Fe967e66533aB1A0504C30989f90156f',
|
[ChainId.ROPSTEN]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385',
|
||||||
[ChainId.RINKEBY]: '0x3431b9Ed12e3204bC6f7039e1c576417B70fdD67',
|
[ChainId.RINKEBY]: '0xAc03019C975F5e79215FeDAB4a1DC30Af3E478F2',
|
||||||
[ChainId.GÖRLI]: '0xa0588c89Fe967e66533aB1A0504C30989f90156f',
|
[ChainId.GÖRLI]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385',
|
||||||
[ChainId.KOVAN]: '',
|
[ChainId.KOVAN]: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SWAP_ROUTER_ADDRESSES: { [chainId in ChainId]: string } = {
|
export const SWAP_ROUTER_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||||
[ChainId.MAINNET]: '',
|
[ChainId.MAINNET]: '',
|
||||||
[ChainId.ROPSTEN]: '0x71bB3d0e63f2Fa2A5d04d54267211f4Caef7062e',
|
[ChainId.ROPSTEN]: '0xDD1B8aA26ac2330e39f8B291eA1E6a82A40E65C4',
|
||||||
[ChainId.RINKEBY]: '0xa0588c89Fe967e66533aB1A0504C30989f90156f',
|
[ChainId.RINKEBY]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385',
|
||||||
[ChainId.GÖRLI]: '0x71bB3d0e63f2Fa2A5d04d54267211f4Caef7062e',
|
[ChainId.GÖRLI]: '0xDD1B8aA26ac2330e39f8B291eA1E6a82A40E65C4',
|
||||||
[ChainId.KOVAN]: '',
|
[ChainId.KOVAN]: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const V2_MIGRATOR_ADDRESSES: { [chainId in ChainId]: string } = {
|
export const V2_MIGRATOR_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||||
[ChainId.MAINNET]: '',
|
[ChainId.MAINNET]: '',
|
||||||
[ChainId.ROPSTEN]: '',
|
[ChainId.ROPSTEN]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65',
|
||||||
[ChainId.RINKEBY]: '0xb31b9A7b331eA8993bdfC67c650eDbfc9256eC62',
|
[ChainId.RINKEBY]: '0x864e344eCd7f3a9A4368dEC11Be8104db5770364',
|
||||||
[ChainId.GÖRLI]: '0xee9e30637f84Bbf929042A9118c6E20023dab833',
|
[ChainId.GÖRLI]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65',
|
||||||
[ChainId.KOVAN]: '',
|
[ChainId.KOVAN]: '',
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import { ChainId, WETH9 } from '@uniswap/sdk-core'
|
|||||||
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
|
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
|
||||||
import { abi as V3FactoryABI } from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'
|
import { abi as V3FactoryABI } from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'
|
||||||
import { abi as V3PoolABI } from '@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json'
|
import { abi as V3PoolABI } from '@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json'
|
||||||
|
import { abi as V2MigratorABI } from '@uniswap/v3-periphery/artifacts/contracts/V3Migrator.sol/V3Migrator.json'
|
||||||
import { abi as TickLensABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/TickLens.sol/TickLens.json'
|
import { abi as TickLensABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/TickLens.sol/TickLens.json'
|
||||||
|
|
||||||
import ARGENT_WALLET_DETECTOR_ABI from 'abis/argent-wallet-detector.json'
|
import ARGENT_WALLET_DETECTOR_ABI from 'abis/argent-wallet-detector.json'
|
||||||
@ -29,10 +30,16 @@ import {
|
|||||||
} from 'constants/index'
|
} from 'constants/index'
|
||||||
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
|
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
|
||||||
import { V1_EXCHANGE_ABI, V1_FACTORY_ABI, V1_FACTORY_ADDRESSES } from 'constants/v1'
|
import { V1_EXCHANGE_ABI, V1_FACTORY_ABI, V1_FACTORY_ADDRESSES } from 'constants/v1'
|
||||||
import { FACTORY_ADDRESSES, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, TICK_LENS_ADDRESSES } from 'constants/v3'
|
import {
|
||||||
|
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
|
||||||
|
FACTORY_ADDRESSES,
|
||||||
|
TICK_LENS_ADDRESSES,
|
||||||
|
V2_MIGRATOR_ADDRESSES,
|
||||||
|
} from 'constants/v3'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { TickLens, UniswapV3Factory, UniswapV3Pool } from 'types/v3'
|
import { TickLens, UniswapV3Factory, UniswapV3Pool } from 'types/v3'
|
||||||
import { NonfungiblePositionManager } from 'types/v3/NonfungiblePositionManager'
|
import { NonfungiblePositionManager } from 'types/v3/NonfungiblePositionManager'
|
||||||
|
import { V3Migrator } from 'types/v3/V3Migrator'
|
||||||
import { getContract } from 'utils'
|
import { getContract } from 'utils'
|
||||||
import { useActiveWeb3React } from './index'
|
import { useActiveWeb3React } from './index'
|
||||||
|
|
||||||
@ -60,6 +67,11 @@ export function useV1MigratorContract(): Contract | null {
|
|||||||
return useContract(V1_MIGRATOR_ADDRESS, MIGRATOR_ABI, true)
|
return useContract(V1_MIGRATOR_ADDRESS, MIGRATOR_ABI, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useV2MigratorContract(): V3Migrator | null {
|
||||||
|
const { chainId } = useActiveWeb3React()
|
||||||
|
return useContract(chainId && V2_MIGRATOR_ADDRESSES[chainId], V2MigratorABI, true) as V3Migrator | null
|
||||||
|
}
|
||||||
|
|
||||||
export function useV1ExchangeContract(address?: string, withSignerIfPossible?: boolean): Contract | null {
|
export function useV1ExchangeContract(address?: string, withSignerIfPossible?: boolean): Contract | null {
|
||||||
return useContract(address, V1_EXCHANGE_ABI, withSignerIfPossible)
|
return useContract(address, V1_EXCHANGE_ABI, withSignerIfPossible)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { TransactionResponse } from '@ethersproject/providers'
|
import { TransactionResponse } from '@ethersproject/providers'
|
||||||
import { Currency, TokenAmount, Token, Percent, ETHER } from '@uniswap/sdk-core'
|
import { Currency, TokenAmount, Percent, ETHER } from '@uniswap/sdk-core'
|
||||||
import React, { useCallback, useContext, useState, useMemo } from 'react'
|
import React, { useCallback, useContext, useState } from 'react'
|
||||||
import { Link2, AlertTriangle } from 'react-feather'
|
import { Link2, AlertTriangle } from 'react-feather'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
|
import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
|
||||||
@ -47,6 +47,95 @@ import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
|||||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from 'constants/v3'
|
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from 'constants/v3'
|
||||||
import JSBI from 'jsbi'
|
import JSBI from 'jsbi'
|
||||||
|
|
||||||
|
export function FeeSelector({
|
||||||
|
disabled = false,
|
||||||
|
feeAmount,
|
||||||
|
handleFeePoolSelect,
|
||||||
|
}: {
|
||||||
|
disabled?: boolean
|
||||||
|
feeAmount?: FeeAmount
|
||||||
|
handleFeePoolSelect: (feeAmount: FeeAmount) => void
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AutoColumn gap="16px">
|
||||||
|
<DynamicSection gap="md" disabled={disabled}>
|
||||||
|
<TYPE.label>{t('selectPool')}</TYPE.label>
|
||||||
|
<RowBetween>
|
||||||
|
<ButtonRadioChecked
|
||||||
|
width="32%"
|
||||||
|
active={feeAmount === FeeAmount.LOW}
|
||||||
|
onClick={() => handleFeePoolSelect(FeeAmount.LOW)}
|
||||||
|
>
|
||||||
|
<AutoColumn gap="sm" justify="flex-start">
|
||||||
|
<TYPE.label>0.05% {t('fee')}</TYPE.label>
|
||||||
|
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
|
||||||
|
Optimized for stable assets.
|
||||||
|
</TYPE.main>
|
||||||
|
</AutoColumn>
|
||||||
|
</ButtonRadioChecked>
|
||||||
|
<ButtonRadioChecked
|
||||||
|
width="32%"
|
||||||
|
active={feeAmount === FeeAmount.MEDIUM}
|
||||||
|
onClick={() => handleFeePoolSelect(FeeAmount.MEDIUM)}
|
||||||
|
>
|
||||||
|
<AutoColumn gap="sm" justify="flex-start">
|
||||||
|
<TYPE.label>0.3% {t('fee')}</TYPE.label>
|
||||||
|
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
|
||||||
|
The classic Uniswap pool fee.
|
||||||
|
</TYPE.main>
|
||||||
|
</AutoColumn>
|
||||||
|
</ButtonRadioChecked>
|
||||||
|
<ButtonRadioChecked
|
||||||
|
width="32%"
|
||||||
|
active={feeAmount === FeeAmount.HIGH}
|
||||||
|
onClick={() => handleFeePoolSelect(FeeAmount.HIGH)}
|
||||||
|
>
|
||||||
|
<AutoColumn gap="sm" justify="flex-start">
|
||||||
|
<TYPE.label>1% {t('fee')}</TYPE.label>
|
||||||
|
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
|
||||||
|
Best for volatile assets.
|
||||||
|
</TYPE.main>
|
||||||
|
</AutoColumn>
|
||||||
|
</ButtonRadioChecked>
|
||||||
|
</RowBetween>
|
||||||
|
</DynamicSection>
|
||||||
|
</AutoColumn>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the order of displayed base currencies from left to right is always in sort order
|
||||||
|
// currencyA is treated as the preferred base currency
|
||||||
|
export function RateToggle({
|
||||||
|
currencyA,
|
||||||
|
currencyB,
|
||||||
|
handleRateToggle,
|
||||||
|
}: {
|
||||||
|
currencyA: Currency
|
||||||
|
currencyB: Currency
|
||||||
|
handleRateToggle: () => void
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { chainId } = useActiveWeb3React()
|
||||||
|
|
||||||
|
const tokenA = wrappedCurrency(currencyA, chainId)
|
||||||
|
const tokenB = wrappedCurrency(currencyB, chainId)
|
||||||
|
|
||||||
|
const isSorted = tokenA && tokenB && tokenA.sortsBefore(tokenB)
|
||||||
|
|
||||||
|
return tokenA && tokenB ? (
|
||||||
|
<ToggleWrapper width="fit-content">
|
||||||
|
<ToggleElement isActive={isSorted} fontSize="12px" onClick={handleRateToggle}>
|
||||||
|
{isSorted ? currencyA.symbol : currencyB.symbol} {t('rate')}
|
||||||
|
</ToggleElement>
|
||||||
|
<ToggleElement isActive={!isSorted} fontSize="12px" onClick={handleRateToggle}>
|
||||||
|
{isSorted ? currencyB.symbol : currencyA.symbol} {t('rate')}
|
||||||
|
</ToggleElement>
|
||||||
|
</ToggleWrapper>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
export default function AddLiquidity({
|
export default function AddLiquidity({
|
||||||
match: {
|
match: {
|
||||||
params: { currencyIdA, currencyIdB, feeAmount: feeAmountFromUrl },
|
params: { currencyIdA, currencyIdB, feeAmount: feeAmountFromUrl },
|
||||||
@ -285,19 +374,6 @@ export default function AddLiquidity({
|
|||||||
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
|
||||||
|
|
||||||
// used sort sorted toggle
|
|
||||||
const tokenA = wrappedCurrency(currencyA ?? undefined, chainId)
|
|
||||||
const tokenB = wrappedCurrency(currencyB ?? undefined, chainId)
|
|
||||||
const sortedTokens: Token[] | undefined = useMemo(
|
|
||||||
() =>
|
|
||||||
tokenA && tokenB && !tokenA.equals(tokenB)
|
|
||||||
? tokenA.sortsBefore(tokenB)
|
|
||||||
? [tokenA, tokenB]
|
|
||||||
: [tokenB, tokenA]
|
|
||||||
: undefined,
|
|
||||||
[tokenA, tokenB]
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleRateToggle = useCallback(() => {
|
const handleRateToggle = useCallback(() => {
|
||||||
if (currencyA && currencyB) {
|
if (currencyA && currencyB) {
|
||||||
const currencyIdA = currencyId(currencyA)
|
const currencyIdA = currencyId(currencyA)
|
||||||
@ -322,19 +398,6 @@ export default function AddLiquidity({
|
|||||||
onUpperRangeInput,
|
onUpperRangeInput,
|
||||||
])
|
])
|
||||||
|
|
||||||
const RateToggle = () => {
|
|
||||||
return sortedTokens && currencyB && currencyA ? (
|
|
||||||
<ToggleWrapper width="fit-content">
|
|
||||||
<ToggleElement isActive={tokenA === sortedTokens[0]} fontSize="12px" onClick={handleRateToggle}>
|
|
||||||
{tokenA === sortedTokens[0] ? currencyB.symbol : currencyA?.symbol} {t('rate')}
|
|
||||||
</ToggleElement>
|
|
||||||
<ToggleElement isActive={tokenB === sortedTokens[0]} fontSize="12px" onClick={handleRateToggle}>
|
|
||||||
{tokenB === sortedTokens[0] ? currencyB.symbol : currencyA?.symbol} {t('rate')}
|
|
||||||
</ToggleElement>
|
|
||||||
</ToggleWrapper>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollablePage>
|
<ScrollablePage>
|
||||||
<ScrollableContent>
|
<ScrollableContent>
|
||||||
@ -415,52 +478,11 @@ export default function AddLiquidity({
|
|||||||
</RowBetween>
|
</RowBetween>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
|
|
||||||
<AutoColumn gap="16px">
|
<FeeSelector
|
||||||
<DynamicSection gap="md" disabled={!currencyB || !currencyA}>
|
disabled={!currencyB || !currencyA}
|
||||||
<TYPE.label>{t('selectPool')}</TYPE.label>
|
feeAmount={feeAmount}
|
||||||
{/* <TYPE.main fontWeight={400} fontSize="14px">
|
handleFeePoolSelect={handleFeePoolSelect}
|
||||||
{t('poolType')}
|
/>
|
||||||
</TYPE.main> */}
|
|
||||||
<RowBetween>
|
|
||||||
<ButtonRadioChecked
|
|
||||||
width="32%"
|
|
||||||
active={feeAmount === FeeAmount.LOW}
|
|
||||||
onClick={() => handleFeePoolSelect(FeeAmount.LOW)}
|
|
||||||
>
|
|
||||||
<AutoColumn gap="sm" justify="flex-start">
|
|
||||||
<TYPE.label>0.05% {t('fee')}</TYPE.label>
|
|
||||||
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
|
|
||||||
Optimized for stable assets.
|
|
||||||
</TYPE.main>
|
|
||||||
</AutoColumn>
|
|
||||||
</ButtonRadioChecked>
|
|
||||||
<ButtonRadioChecked
|
|
||||||
width="32%"
|
|
||||||
active={feeAmount === FeeAmount.MEDIUM}
|
|
||||||
onClick={() => handleFeePoolSelect(FeeAmount.MEDIUM)}
|
|
||||||
>
|
|
||||||
<AutoColumn gap="sm" justify="flex-start">
|
|
||||||
<TYPE.label>0.3% {t('fee')}</TYPE.label>
|
|
||||||
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
|
|
||||||
The classic Uniswap pool fee.
|
|
||||||
</TYPE.main>
|
|
||||||
</AutoColumn>
|
|
||||||
</ButtonRadioChecked>
|
|
||||||
<ButtonRadioChecked
|
|
||||||
width="32%"
|
|
||||||
active={feeAmount === FeeAmount.HIGH}
|
|
||||||
onClick={() => handleFeePoolSelect(FeeAmount.HIGH)}
|
|
||||||
>
|
|
||||||
<AutoColumn gap="sm" justify="flex-start">
|
|
||||||
<TYPE.label>1% {t('fee')}</TYPE.label>
|
|
||||||
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
|
|
||||||
Best for volatile assets.
|
|
||||||
</TYPE.main>
|
|
||||||
</AutoColumn>
|
|
||||||
</ButtonRadioChecked>
|
|
||||||
</RowBetween>
|
|
||||||
</DynamicSection>
|
|
||||||
</AutoColumn>
|
|
||||||
|
|
||||||
{noLiquidity && (
|
{noLiquidity && (
|
||||||
<DynamicSection disabled={!currencyA || !currencyB}>
|
<DynamicSection disabled={!currencyA || !currencyB}>
|
||||||
@ -470,7 +492,9 @@ export default function AddLiquidity({
|
|||||||
</BlueCard>
|
</BlueCard>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.label>{t('selectStartingPrice')}</TYPE.label>
|
<TYPE.label>{t('selectStartingPrice')}</TYPE.label>
|
||||||
{tokenA && tokenB && <RateToggle />}
|
{currencyA && currencyB ? (
|
||||||
|
<RateToggle currencyA={currencyA} currencyB={currencyB} handleRateToggle={handleRateToggle} />
|
||||||
|
) : null}
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
{/* <TYPE.main fontWeight={400} fontSize="14px">
|
{/* <TYPE.main fontWeight={400} fontSize="14px">
|
||||||
{t('newPoolPrice')}
|
{t('newPoolPrice')}
|
||||||
@ -499,7 +523,9 @@ export default function AddLiquidity({
|
|||||||
<DynamicSection gap="md" disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}>
|
<DynamicSection gap="md" disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.label>{t('selectLiquidityRange')}</TYPE.label>
|
<TYPE.label>{t('selectLiquidityRange')}</TYPE.label>
|
||||||
{tokenA && tokenB && !noLiquidity && <RateToggle />}
|
{currencyA && currencyB && !noLiquidity && (
|
||||||
|
<RateToggle currencyA={currencyA} currencyB={currencyB} handleRateToggle={handleRateToggle} />
|
||||||
|
)}
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
{/* <TYPE.main fontWeight={400} fontSize="14px">
|
{/* <TYPE.main fontWeight={400} fontSize="14px">
|
||||||
{t('rangeWarning')}
|
{t('rangeWarning')}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useMemo } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
import { Currency, CurrencyAmount, Price, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Fraction, Price, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
|
||||||
import { JSBI } from '@uniswap/v2-sdk'
|
import { JSBI } from '@uniswap/v2-sdk'
|
||||||
import { Redirect, RouteComponentProps } from 'react-router'
|
import { Redirect, RouteComponentProps } from 'react-router'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
@ -11,7 +11,7 @@ import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
|
|||||||
import { useTotalSupply } from '../../data/TotalSupply'
|
import { useTotalSupply } from '../../data/TotalSupply'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { useToken } from '../../hooks/Tokens'
|
import { useToken } from '../../hooks/Tokens'
|
||||||
import { usePairContract } from '../../hooks/useContract'
|
import { usePairContract, useV2MigratorContract } from '../../hooks/useContract'
|
||||||
import { NEVER_RELOAD, useSingleCallResult } from '../../state/multicall/hooks'
|
import { NEVER_RELOAD, useSingleCallResult } from '../../state/multicall/hooks'
|
||||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||||
import { BackArrow, ExternalLink, TYPE } from '../../theme'
|
import { BackArrow, ExternalLink, TYPE } from '../../theme'
|
||||||
@ -19,14 +19,20 @@ import { getEtherscanLink, isAddress } from '../../utils'
|
|||||||
import { BodyWrapper } from '../AppBody'
|
import { BodyWrapper } from '../AppBody'
|
||||||
import { EmptyState } from '../MigrateV1/EmptyState'
|
import { EmptyState } from '../MigrateV1/EmptyState'
|
||||||
import { V2_MIGRATOR_ADDRESSES } from 'constants/v3'
|
import { V2_MIGRATOR_ADDRESSES } from 'constants/v3'
|
||||||
|
import { PoolState, usePool } from 'data/Pools'
|
||||||
|
import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk'
|
||||||
|
import { FeeSelector, RateToggle } from 'pages/AddLiquidity'
|
||||||
|
import { LightCard, PinkCard, YellowCard } from 'components/Card'
|
||||||
|
import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback'
|
||||||
|
import { Dots } from 'components/swap/styleds'
|
||||||
|
import { ButtonConfirmed } from 'components/Button'
|
||||||
|
import useTransactionDeadline from 'hooks/useTransactionDeadline'
|
||||||
|
import { useUserSlippageTolerance } from 'state/user/hooks'
|
||||||
|
import ReactGA from 'react-ga'
|
||||||
|
import { TransactionResponse } from '@ethersproject/providers'
|
||||||
|
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||||
|
|
||||||
// TODO the whole file
|
const ZERO = JSBI.BigInt(0)
|
||||||
|
|
||||||
// const WEI_DENOM = JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18))
|
|
||||||
// const ZERO = JSBI.BigInt(0)
|
|
||||||
// const ONE = JSBI.BigInt(1)
|
|
||||||
// const ZERO_FRACTION = new Fraction(ZERO, ONE)
|
|
||||||
// const ALLOWED_OUTPUT_MIN_PERCENT = new Percent(JSBI.BigInt(10000 - INITIAL_ALLOWED_SLIPPAGE), JSBI.BigInt(10000))
|
|
||||||
|
|
||||||
export function V2LiquidityInfo({
|
export function V2LiquidityInfo({
|
||||||
token,
|
token,
|
||||||
@ -94,7 +100,7 @@ function V2PairMigration({
|
|||||||
token0: Token
|
token0: Token
|
||||||
token1: Token
|
token1: Token
|
||||||
}) {
|
}) {
|
||||||
const { chainId } = useActiveWeb3React()
|
const { chainId, account } = useActiveWeb3React()
|
||||||
|
|
||||||
// this is just getLiquidityValue with the fee off, but for the passed pair
|
// this is just getLiquidityValue with the fee off, but for the passed pair
|
||||||
const token0Value = useMemo(
|
const token0Value = useMemo(
|
||||||
@ -106,90 +112,144 @@ function V2PairMigration({
|
|||||||
[token1, pairBalance, reserve1, totalSupply]
|
[token1, pairBalance, reserve1, totalSupply]
|
||||||
)
|
)
|
||||||
|
|
||||||
const v2SpotPrice = new Price(token0, token1, reserve0.raw, reserve1.raw)
|
// set up v3 pool
|
||||||
|
const [feeAmount, setFeeAmount] = useState(FeeAmount.MEDIUM)
|
||||||
|
const [poolState, pool] = usePool(token0, token1, feeAmount)
|
||||||
|
const noLiquidity = poolState === PoolState.NOT_EXISTS
|
||||||
|
|
||||||
console.log(token0Value, token1Value, v2SpotPrice)
|
// get spot prices + price difference
|
||||||
|
const v2SpotPrice = useMemo(() => new Price(token0, token1, reserve0.raw, reserve1.raw), [
|
||||||
|
token0,
|
||||||
|
token1,
|
||||||
|
reserve0,
|
||||||
|
reserve1,
|
||||||
|
])
|
||||||
|
const v3SpotPrice = poolState === PoolState.EXISTS ? pool?.token0Price : undefined
|
||||||
|
|
||||||
// const isFirstLiquidityProvider: boolean = false // check for v3 pair existence
|
let priceDifferenceFraction: Fraction | undefined =
|
||||||
|
v2SpotPrice && v3SpotPrice ? v3SpotPrice.divide(v2SpotPrice).subtract(1).multiply(100) : undefined
|
||||||
|
if (priceDifferenceFraction?.lessThan(ZERO)) {
|
||||||
|
priceDifferenceFraction = priceDifferenceFraction.multiply(-1)
|
||||||
|
}
|
||||||
|
|
||||||
// const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
|
const largePriceDifference = priceDifferenceFraction && !priceDifferenceFraction?.lessThan(JSBI.BigInt(4))
|
||||||
// const [pendingMigrationHash, setPendingMigrationHash] = useState<string | null>(null)
|
|
||||||
|
|
||||||
// const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
|
const [invertPrice, setInvertPrice] = useState(false)
|
||||||
|
|
||||||
// const ethWorth: CurrencyAmount = exchangeETHBalance
|
// TODO these obviously have to not be hardcoded eventually
|
||||||
// ? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
|
const lowerTick = -60000
|
||||||
// : CurrencyAmount.ether(ZERO)
|
const upperTick = 60000
|
||||||
|
const percentageToMigrate = 100
|
||||||
|
|
||||||
// const tokenWorth: TokenAmount = exchangeTokenBalance
|
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
|
||||||
// ? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
|
const [pendingMigrationHash, setPendingMigrationHash] = useState<string | null>(null)
|
||||||
// : new TokenAmount(token, ZERO)
|
|
||||||
|
|
||||||
// const [approval, approve] = useApproveCallback(liquidityTokenAmount, V1_MIGRATOR_ADDRESS)
|
// TODO add permit approval
|
||||||
|
const [approval, approve] = useApproveCallback(pairBalance, chainId ? V2_MIGRATOR_ADDRESSES[chainId] : undefined)
|
||||||
|
|
||||||
// const v1SpotPrice =
|
const addTransaction = useTransactionAdder()
|
||||||
// exchangeTokenBalance && exchangeETHBalance
|
const isMigrationPending = useIsTransactionPending(pendingMigrationHash ?? undefined)
|
||||||
// ? exchangeTokenBalance.divide(new Fraction(exchangeETHBalance.raw, WEI_DENOM))
|
|
||||||
// : null
|
|
||||||
|
|
||||||
// const priceDifferenceFraction: Fraction | undefined =
|
const deadline = useTransactionDeadline() // custom from users settings
|
||||||
// v1SpotPrice && v2SpotPrice ? v1SpotPrice.divide(v2SpotPrice).multiply('100').subtract('100') : undefined
|
const [allowedSlippage] = useUserSlippageTolerance() // custom from users
|
||||||
|
|
||||||
// const priceDifferenceAbs: Fraction | undefined = priceDifferenceFraction?.lessThan(ZERO)
|
const migrator = useV2MigratorContract()
|
||||||
// ? priceDifferenceFraction?.multiply('-1')
|
const migrate = useCallback(() => {
|
||||||
// : priceDifferenceFraction
|
if (!migrator || !account || !deadline) return
|
||||||
|
|
||||||
// const minAmountETH: JSBI | undefined =
|
// the v3 tick is either the tickCurrent, or the tick closest to the v2 spot price
|
||||||
// v2SpotPrice && tokenWorth
|
const tick = pool?.tickCurrent ?? priceToClosestTick(v2SpotPrice)
|
||||||
// ? tokenWorth.divide(v2SpotPrice).multiply(WEI_DENOM).multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
|
// the price is either the current v3 price, or the price at the tick
|
||||||
// : ethWorth?.numerator
|
const sqrtPrice = pool?.sqrtRatioX96 ?? TickMath.getSqrtRatioAtTick(tick)
|
||||||
|
|
||||||
// const minAmountToken: JSBI | undefined =
|
const data = []
|
||||||
// v2SpotPrice && ethWorth
|
|
||||||
// ? ethWorth
|
|
||||||
// .multiply(v2SpotPrice)
|
|
||||||
// .multiply(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(token.decimals)))
|
|
||||||
// .multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
|
|
||||||
// : tokenWorth?.numerator
|
|
||||||
|
|
||||||
// const addTransaction = useTransactionAdder()
|
// create/initialize pool if necessary
|
||||||
// const isMigrationPending = useIsTransactionPending(pendingMigrationHash ?? undefined)
|
if (noLiquidity) {
|
||||||
|
data.push(
|
||||||
|
migrator.interface.encodeFunctionData('createAndInitializePoolIfNecessary', [
|
||||||
|
token0.address,
|
||||||
|
token1.address,
|
||||||
|
feeAmount,
|
||||||
|
`0x${sqrtPrice.toString(16)}`,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// const migrator = useV1MigratorContract()
|
const position = Position.fromAmounts({
|
||||||
// const migrate = useCallback(() => {
|
pool: pool ?? new Pool(token0, token1, feeAmount, sqrtPrice, 0, tick, []),
|
||||||
// if (!minAmountToken || !minAmountETH || !migrator) return
|
tickLower: lowerTick,
|
||||||
|
tickUpper: upperTick,
|
||||||
|
amount0: token0Value.raw,
|
||||||
|
amount1: token1Value.raw,
|
||||||
|
})
|
||||||
|
|
||||||
// setConfirmingMigration(true)
|
// TODO could save gas by not doing this in multicall
|
||||||
// migrator
|
data.push(
|
||||||
// .migrate(
|
migrator.interface.encodeFunctionData('migrate', [
|
||||||
// token.address,
|
{
|
||||||
// minAmountToken.toString(),
|
pair: pairBalance.token.address,
|
||||||
// minAmountETH.toString(),
|
liquidityToMigrate: `0x${pairBalance.raw.toString(16)}`,
|
||||||
// account,
|
percentageToMigrate,
|
||||||
// Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
|
token0: token0.address,
|
||||||
// )
|
token1: token1.address,
|
||||||
// .then((response: TransactionResponse) => {
|
fee: feeAmount,
|
||||||
// ReactGA.event({
|
tickLower: lowerTick,
|
||||||
// category: 'Migrate',
|
tickUpper: upperTick,
|
||||||
// action: 'V1->V2',
|
amount0Min: `0x${JSBI.divide(
|
||||||
// label: token?.symbol,
|
JSBI.multiply(position.amount0.raw, JSBI.BigInt(allowedSlippage)),
|
||||||
// })
|
JSBI.BigInt(10000)
|
||||||
|
).toString(16)}`,
|
||||||
|
amount1Min: `0x${JSBI.divide(
|
||||||
|
JSBI.multiply(position.amount1.raw, JSBI.BigInt(allowedSlippage)),
|
||||||
|
JSBI.BigInt(10000)
|
||||||
|
).toString(16)}`,
|
||||||
|
recipient: account,
|
||||||
|
deadline,
|
||||||
|
refundAsETH: true, // TODO might want to change this?
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
// addTransaction(response, {
|
setConfirmingMigration(true)
|
||||||
// summary: `Migrate ${token.symbol} liquidity to V2`,
|
migrator
|
||||||
// })
|
.multicall(data)
|
||||||
// setPendingMigrationHash(response.hash)
|
.then((response: TransactionResponse) => {
|
||||||
// })
|
ReactGA.event({
|
||||||
// .catch(() => {
|
category: 'Migrate',
|
||||||
// setConfirmingMigration(false)
|
action: 'V2->V3',
|
||||||
// })
|
label: `${token0.symbol}/${token1.symbol}`,
|
||||||
// }, [minAmountToken, minAmountETH, migrator, token, account, addTransaction])
|
})
|
||||||
|
|
||||||
// const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
|
addTransaction(response, {
|
||||||
|
summary: `Migrate ${token0.symbol}/${token1.symbol} liquidity to V3`,
|
||||||
|
})
|
||||||
|
setPendingMigrationHash(response.hash)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setConfirmingMigration(false)
|
||||||
|
})
|
||||||
|
}, [
|
||||||
|
migrator,
|
||||||
|
noLiquidity,
|
||||||
|
token0,
|
||||||
|
token1,
|
||||||
|
feeAmount,
|
||||||
|
v2SpotPrice,
|
||||||
|
pairBalance,
|
||||||
|
token0Value,
|
||||||
|
token1Value,
|
||||||
|
percentageToMigrate,
|
||||||
|
lowerTick,
|
||||||
|
allowedSlippage,
|
||||||
|
pool,
|
||||||
|
upperTick,
|
||||||
|
account,
|
||||||
|
deadline,
|
||||||
|
addTransaction,
|
||||||
|
])
|
||||||
|
|
||||||
// const largePriceDifference = !!priceDifferenceAbs && !priceDifferenceAbs.lessThan(JSBI.BigInt(5))
|
const isSuccessfullyMigrated = !!pendingMigrationHash && JSBI.equal(pairBalance.raw, ZERO)
|
||||||
|
|
||||||
// const isSuccessfullyMigrated = !!pendingMigrationHash && noLiquidityTokens
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoColumn gap="20px">
|
<AutoColumn gap="20px">
|
||||||
@ -204,78 +264,76 @@ function V2PairMigration({
|
|||||||
.
|
.
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
|
|
||||||
{/* {!isFirstLiquidityProvider && largePriceDifference ? (
|
<FeeSelector feeAmount={feeAmount} handleFeePoolSelect={setFeeAmount} />
|
||||||
<YellowCard>
|
|
||||||
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
|
|
||||||
It{"'"}s best to deposit liquidity into Uniswap V2 at a price you believe is correct. If the V2 price seems
|
|
||||||
incorrect, you can either make a swap to move the price or wait for someone else to do so.
|
|
||||||
</TYPE.body>
|
|
||||||
<AutoColumn gap="8px">
|
|
||||||
<RowBetween>
|
|
||||||
<TYPE.body>V1 Price:</TYPE.body>
|
|
||||||
<TYPE.black>
|
|
||||||
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
|
|
||||||
</TYPE.black>
|
|
||||||
</RowBetween>
|
|
||||||
<RowBetween>
|
|
||||||
<div />
|
|
||||||
<TYPE.black>
|
|
||||||
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
|
|
||||||
</TYPE.black>
|
|
||||||
</RowBetween>
|
|
||||||
|
|
||||||
|
<div style={{ justifySelf: 'end' }}>
|
||||||
|
<RateToggle
|
||||||
|
currencyA={invertPrice ? token1 : token0}
|
||||||
|
currencyB={invertPrice ? token0 : token1}
|
||||||
|
handleRateToggle={() => setInvertPrice((invertPrice) => !invertPrice)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{noLiquidity && (
|
||||||
|
<PinkCard>
|
||||||
|
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
|
||||||
|
You are the first liquidity provider for this Uniswap V3 pool. Your liquidity will be migrated at the
|
||||||
|
current V2 price. Your transaction cost will include the gas to create the pool.
|
||||||
|
</TYPE.body>
|
||||||
|
|
||||||
|
<AutoColumn gap="8px">
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.body>V2 Price:</TYPE.body>
|
<TYPE.body>V2 Price:</TYPE.body>
|
||||||
<TYPE.black>
|
<TYPE.black>
|
||||||
{v2SpotPrice?.toSignificant(6)} {token.symbol}/ETH
|
{invertPrice
|
||||||
</TYPE.black>
|
? `${v2SpotPrice?.invert()?.toSignificant(6)} ${token0.symbol} / ${token1.symbol}`
|
||||||
</RowBetween>
|
: `${v2SpotPrice?.toSignificant(6)} ${token1.symbol} / ${token0.symbol}`}
|
||||||
<RowBetween>
|
|
||||||
<div />
|
|
||||||
<TYPE.black>
|
|
||||||
{v2SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
|
|
||||||
</TYPE.black>
|
|
||||||
</RowBetween>
|
|
||||||
|
|
||||||
<RowBetween>
|
|
||||||
<TYPE.body color="inherit">Price Difference:</TYPE.body>
|
|
||||||
<TYPE.black color="inherit">{priceDifferenceAbs?.toSignificant(4)}%</TYPE.black>
|
|
||||||
</RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
</YellowCard>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{isFirstLiquidityProvider && (
|
|
||||||
<PinkCard>
|
|
||||||
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
|
|
||||||
You are the first liquidity provider for this pair on Uniswap V2. Your liquidity will be migrated at the
|
|
||||||
current V1 price. Your transaction cost also includes the gas to create the pool.
|
|
||||||
</TYPE.body>
|
|
||||||
|
|
||||||
<AutoColumn gap="8px">
|
|
||||||
<RowBetween>
|
|
||||||
<TYPE.body>V1 Price:</TYPE.body>
|
|
||||||
<TYPE.black>
|
|
||||||
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
|
|
||||||
</TYPE.black>
|
|
||||||
</RowBetween>
|
|
||||||
<RowBetween>
|
|
||||||
<div />
|
|
||||||
<TYPE.black>
|
|
||||||
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
|
|
||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</PinkCard>
|
</PinkCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{largePriceDifference && (
|
||||||
|
<YellowCard>
|
||||||
|
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
|
||||||
|
You should only deposit liquidity into Uniswap V3 at a price you believe is correct. If the price seems
|
||||||
|
incorrect, you can either make a swap to move the price or wait for someone else to do so.
|
||||||
|
</TYPE.body>
|
||||||
|
<AutoColumn gap="8px">
|
||||||
|
<RowBetween>
|
||||||
|
<TYPE.body>V2 Price:</TYPE.body>
|
||||||
|
<TYPE.black>
|
||||||
|
{invertPrice
|
||||||
|
? `${v2SpotPrice?.invert()?.toSignificant(6)} ${token0.symbol} / ${token1.symbol}`
|
||||||
|
: `${v2SpotPrice?.toSignificant(6)} ${token1.symbol} / ${token0.symbol}`}
|
||||||
|
</TYPE.black>
|
||||||
|
</RowBetween>
|
||||||
|
|
||||||
|
<RowBetween>
|
||||||
|
<TYPE.body>V3 Price:</TYPE.body>
|
||||||
|
<TYPE.black>
|
||||||
|
{invertPrice
|
||||||
|
? `${v3SpotPrice?.invert()?.toSignificant(6)} ${token0.symbol} / ${token1.symbol}`
|
||||||
|
: `${v3SpotPrice?.toSignificant(6)} ${token1.symbol} / ${token0.symbol}`}
|
||||||
|
</TYPE.black>
|
||||||
|
</RowBetween>
|
||||||
|
|
||||||
|
<RowBetween>
|
||||||
|
<TYPE.body color="inherit">Price Difference:</TYPE.body>
|
||||||
|
<TYPE.black color="inherit">{priceDifferenceFraction?.toSignificant(4)}%</TYPE.black>
|
||||||
|
</RowBetween>
|
||||||
|
</AutoColumn>
|
||||||
|
</YellowCard>
|
||||||
|
)}
|
||||||
|
|
||||||
<LightCard>
|
<LightCard>
|
||||||
<V2LiquidityInfo
|
{/* <V2LiquidityInfo
|
||||||
token={token}
|
token={token}
|
||||||
liquidityTokenAmount={liquidityTokenAmount}
|
liquidityTokenAmount={liquidityTokenAmount}
|
||||||
tokenWorth={tokenWorth}
|
tokenWorth={tokenWorth}
|
||||||
ethWorth={ethWorth}
|
ethWorth={ethWorth}
|
||||||
/>
|
/> */}
|
||||||
|
|
||||||
<div style={{ display: 'flex', marginTop: '1rem' }}>
|
<div style={{ display: 'flex', marginTop: '1rem' }}>
|
||||||
<AutoColumn gap="12px" style={{ flex: '1', marginRight: 12 }}>
|
<AutoColumn gap="12px" style={{ flex: '1', marginRight: 12 }}>
|
||||||
@ -297,22 +355,25 @@ function V2PairMigration({
|
|||||||
<ButtonConfirmed
|
<ButtonConfirmed
|
||||||
confirmed={isSuccessfullyMigrated}
|
confirmed={isSuccessfullyMigrated}
|
||||||
disabled={
|
disabled={
|
||||||
isSuccessfullyMigrated ||
|
|
||||||
noLiquidityTokens ||
|
|
||||||
isMigrationPending ||
|
|
||||||
approval !== ApprovalState.APPROVED ||
|
approval !== ApprovalState.APPROVED ||
|
||||||
confirmingMigration
|
confirmingMigration ||
|
||||||
|
isMigrationPending ||
|
||||||
|
isSuccessfullyMigrated
|
||||||
}
|
}
|
||||||
onClick={migrate}
|
onClick={migrate}
|
||||||
>
|
>
|
||||||
{isSuccessfullyMigrated ? 'Success' : isMigrationPending ? <Dots>Migrating</Dots> : 'Migrate'}
|
{isSuccessfullyMigrated ? 'Success!' : isMigrationPending ? <Dots>Migrating</Dots> : 'Migrate'}
|
||||||
</ButtonConfirmed>
|
</ButtonConfirmed>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</div>
|
</div>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
<TYPE.darkGray style={{ textAlign: 'center' }}>
|
<TYPE.darkGray style={{ textAlign: 'center' }}>
|
||||||
{`Your Uniswap V1 ${token.symbol}/ETH liquidity will become Uniswap V2 ${token.symbol}/ETH liquidity.`}
|
{`Your Uniswap V2 ${invertPrice ? token0?.symbol : token1?.symbol} / ${
|
||||||
</TYPE.darkGray> */}
|
invertPrice ? token1?.symbol : token0?.symbol
|
||||||
|
} liquidity tokens will become a Uniswap V3 ${invertPrice ? token0?.symbol : token1?.symbol} / ${
|
||||||
|
invertPrice ? token1?.symbol : token0?.symbol
|
||||||
|
} NFT.`}
|
||||||
|
</TYPE.darkGray>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
12
yarn.lock
12
yarn.lock
@ -4134,7 +4134,7 @@
|
|||||||
tiny-invariant "^1.1.0"
|
tiny-invariant "^1.1.0"
|
||||||
tiny-warning "^1.0.3"
|
tiny-warning "^1.0.3"
|
||||||
|
|
||||||
"@uniswap/v3-core@1.0.0-rc.1", "@uniswap/v3-core@^1.0.0-rc.0":
|
"@uniswap/v3-core@1.0.0-rc.1", "@uniswap/v3-core@^1.0.0-rc.1":
|
||||||
version "1.0.0-rc.1"
|
version "1.0.0-rc.1"
|
||||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0-rc.1.tgz#f2bbc483451364a951fba06eb2d978c6e8bdd58f"
|
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0-rc.1.tgz#f2bbc483451364a951fba06eb2d978c6e8bdd58f"
|
||||||
integrity sha512-4ET2H0a8p7nVBGFWfio9SHc+RA6UIXEvlTRIJNsDwjQvfs8Jq9lfJ+eSOUTGmiB8Vp8V5dWarLDBU/rDE159pQ==
|
integrity sha512-4ET2H0a8p7nVBGFWfio9SHc+RA6UIXEvlTRIJNsDwjQvfs8Jq9lfJ+eSOUTGmiB8Vp8V5dWarLDBU/rDE159pQ==
|
||||||
@ -4149,6 +4149,16 @@
|
|||||||
"@uniswap/v2-core" "1.0.1"
|
"@uniswap/v2-core" "1.0.1"
|
||||||
"@uniswap/v3-core" "1.0.0-rc.1"
|
"@uniswap/v3-core" "1.0.0-rc.1"
|
||||||
|
|
||||||
|
"@uniswap/v3-periphery@^1.0.0-beta.19":
|
||||||
|
version "1.0.0-beta.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.0.0-beta.19.tgz#d9af90b12657049674cd2f26ae1c61b6cc393261"
|
||||||
|
integrity sha512-ZQX5KN/89OB7UjrmGOSB7QZIEbgW+R0uaVM5NdlK63Ji0rZjmddeoYS8oNk7i5BU3WR+xJY5DgfiDSmn1W6Sww==
|
||||||
|
dependencies:
|
||||||
|
"@openzeppelin/contracts" "3.4.1-solc-0.7-2"
|
||||||
|
"@uniswap/lib" "^4.0.1-alpha"
|
||||||
|
"@uniswap/v2-core" "1.0.1"
|
||||||
|
"@uniswap/v3-core" "1.0.0-rc.1"
|
||||||
|
|
||||||
"@uniswap/v3-sdk@^1.0.0-alpha.11":
|
"@uniswap/v3-sdk@^1.0.0-alpha.11":
|
||||||
version "1.0.0-alpha.11"
|
version "1.0.0-alpha.11"
|
||||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-1.0.0-alpha.11.tgz#184ed5ee8322b27f35aa830ad5e217b5dda6bd67"
|
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-1.0.0-alpha.11.tgz#184ed5ee8322b27f35aa830ad5e217b5dda6bd67"
|
||||||
|
Loading…
Reference in New Issue
Block a user