Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bc5d6504e | ||
|
|
7a0b85bf41 | ||
|
|
534afb3278 | ||
|
|
7d71af353e | ||
|
|
af6098bfe5 | ||
|
|
fce29bb36f | ||
|
|
4517af39ba | ||
|
|
b40163ce05 | ||
|
|
809902efec | ||
|
|
70be9894fa | ||
|
|
698ad5bac9 | ||
|
|
cd37b7533d | ||
|
|
c0cd6a1c8d | ||
|
|
f6245d1093 | ||
|
|
83c784f7c0 | ||
|
|
3d95b1a33b |
3
.env
3
.env
@@ -1,5 +1,4 @@
|
||||
REACT_APP_CHAIN_ID="1"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847"
|
||||
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
|
||||
REACT_APP_WALLETCONNECT_BRIDGE_URL="https://uniswap.bridge.walletconnect.org"
|
||||
# Because we use storybook which has its own babel-loader dependency @ 8.2.2, where react-scripts uses 8.1.0
|
||||
SKIP_PREFLIGHT_CHECK=true
|
||||
@@ -1,5 +1,4 @@
|
||||
REACT_APP_CHAIN_ID="1"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/099fc58e0de9451d80b18d7c74caa7c1"
|
||||
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
|
||||
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
|
||||
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
|
||||
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"
|
||||
|
||||
14
.github/workflows/release.yaml
vendored
14
.github/workflows/release.yaml
vendored
@@ -94,19 +94,13 @@ jobs:
|
||||
The latest release is always accessible via our alias to the Cloudflare IPFS gateway at [app.uniswap.org](https://app.uniswap.org).
|
||||
|
||||
You can also access the Uniswap Interface directly from an IPFS gateway.
|
||||
The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to store your settings.
|
||||
**Beware** that other sites you access via the _same_ IPFS gateway can read and modify your settings on the Uniswap interface without your permission.
|
||||
You can avoid this issue by using a subdomain IPFS gateway, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
|
||||
The preferred URLs below are safe to use to access this specific release.
|
||||
**BEWARE**: The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported.
|
||||
**You should always use an IPFS gateway that enforces origin separation**, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
|
||||
Your Uniswap settings are never remembered across different URLs.
|
||||
|
||||
Preferred URLs:
|
||||
IPFS gateways:
|
||||
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/
|
||||
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.cf-ipfs.com/
|
||||
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/)
|
||||
|
||||
Other IPFS gateways:
|
||||
- https://cloudflare-ipfs.com/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
- https://ipfs.infura.io/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
- https://ipfs.io/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
|
||||
${{ needs.bump_version.outputs.changelog }}
|
||||
|
||||
15
README.md
15
README.md
@@ -27,7 +27,7 @@ or visit [app.uniswap.org](https://app.uniswap.org).
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
yarn
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Run
|
||||
@@ -36,19 +36,6 @@ yarn
|
||||
yarn start
|
||||
```
|
||||
|
||||
### Configuring the environment (optional)
|
||||
|
||||
To have the interface default to a different network when a wallet is not connected:
|
||||
|
||||
1. Make a copy of `.env` named `.env.local`
|
||||
2. Change `REACT_APP_NETWORK_ID` to `"{YOUR_NETWORK_ID}"`
|
||||
3. Change `REACT_APP_NETWORK_URL` to e.g. `"https://{YOUR_NETWORK_ID}.infura.io/v3/{YOUR_INFURA_KEY}"`
|
||||
|
||||
Note that the interface only works on testnets where both
|
||||
[Uniswap V2](https://uniswap.org/docs/v2/smart-contracts/factory/) and
|
||||
[multicall](https://github.com/makerdao/multicall) are deployed.
|
||||
The interface will not work on other networks.
|
||||
|
||||
## Contributions
|
||||
|
||||
**Please open all pull requests against the `main` branch.**
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
"@uniswap/v2-sdk": "^3.0.0-alpha.0",
|
||||
"@uniswap/v3-core": "1.0.0",
|
||||
"@uniswap/v3-periphery": "1.0.0",
|
||||
"@uniswap/v3-sdk": "^3.0.0-alpha.1",
|
||||
"@uniswap/v3-sdk": "^3.0.0-alpha.4",
|
||||
"@web3-react/core": "^6.0.9",
|
||||
"@web3-react/fortmatic-connector": "^6.0.9",
|
||||
"@web3-react/injected-connector": "^6.0.7",
|
||||
"@web3-react/portis-connector": "^6.0.9",
|
||||
"@web3-react/walletconnect-connector": "^6.1.1",
|
||||
"@web3-react/walletlink-connector": "^6.0.9",
|
||||
"@web3-react/walletconnect-connector": "^6.2.0",
|
||||
"@web3-react/walletlink-connector": "^6.2.0",
|
||||
"ajv": "^6.12.3",
|
||||
"cids": "^1.0.0",
|
||||
"copy-to-clipboard": "^3.2.0",
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
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'
|
||||
import React, { useContext, useMemo } from 'react'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { TYPE } from '../../theme'
|
||||
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
|
||||
import { computeRealizedLPFeeAmount } from '../../utils/prices'
|
||||
import { computeRealizedLPFeePercent } from '../../utils/prices'
|
||||
import { AutoColumn } from '../Column'
|
||||
import { RowBetween, RowFixed } from '../Row'
|
||||
import FormattedPriceImpact from './FormattedPriceImpact'
|
||||
@@ -19,7 +18,14 @@ export interface AdvancedSwapDetailsProps {
|
||||
export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDetailsProps) {
|
||||
const theme = useContext(ThemeContext)
|
||||
|
||||
const realizedLPFee = computeRealizedLPFeeAmount(trade)
|
||||
const { realizedLPFee, priceImpact } = useMemo(() => {
|
||||
if (!trade) return { realizedLPFee: undefined, priceImpact: undefined }
|
||||
|
||||
const realizedLpFeePercent = computeRealizedLPFeePercent(trade)
|
||||
const realizedLPFee = trade.inputAmount.multiply(realizedLpFeePercent)
|
||||
const priceImpact = trade.priceImpact.subtract(realizedLpFeePercent)
|
||||
return { priceImpact, realizedLPFee }
|
||||
}, [trade])
|
||||
|
||||
return !trade ? null : (
|
||||
<AutoColumn gap="8px">
|
||||
@@ -30,7 +36,7 @@ export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDeta
|
||||
</TYPE.black>
|
||||
</RowFixed>
|
||||
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
|
||||
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${trade.inputAmount.currency.symbol}` : '-'}
|
||||
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${realizedLPFee.currency.symbol}` : '-'}
|
||||
</TYPE.black>
|
||||
</RowBetween>
|
||||
|
||||
@@ -48,11 +54,24 @@ export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDeta
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
|
||||
Execution price vs. spot price
|
||||
Price Impact
|
||||
</TYPE.black>
|
||||
</RowFixed>
|
||||
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
|
||||
<FormattedPriceImpact priceImpact={computePriceImpactWithMaximumSlippage(trade, allowedSlippage)} />
|
||||
<FormattedPriceImpact priceImpact={priceImpact} />
|
||||
</TYPE.black>
|
||||
</RowBetween>
|
||||
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
|
||||
{trade.tradeType === TradeType.EXACT_INPUT ? 'Minimum received' : 'Maximum sent'}
|
||||
</TYPE.black>
|
||||
</RowFixed>
|
||||
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
|
||||
{trade.tradeType === TradeType.EXACT_INPUT
|
||||
? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}`
|
||||
: `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`}
|
||||
</TYPE.black>
|
||||
</RowBetween>
|
||||
|
||||
|
||||
@@ -90,9 +90,9 @@ export default function ConfirmSwapModal({
|
||||
}, [onConfirm, showAcceptChanges, swapErrorMessage, trade])
|
||||
|
||||
// text to show while loading
|
||||
const pendingText = `Swapping ${trade?.maximumAmountIn(allowedSlippage)?.toSignificant(6)} ${
|
||||
const pendingText = `Swapping ${trade?.inputAmount?.toSignificant(6)} ${
|
||||
trade?.inputAmount?.currency?.symbol
|
||||
} for ${trade?.minimumAmountOut(allowedSlippage)?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
|
||||
} for ${trade?.outputAmount?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
|
||||
|
||||
const confirmationContent = useCallback(
|
||||
() =>
|
||||
|
||||
@@ -31,12 +31,10 @@ export const ArrowWrapper = styled.div`
|
||||
margin-top: -18px;
|
||||
margin-bottom: -18px;
|
||||
left: calc(50% - 16px);
|
||||
/* transform: rotate(90deg); */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.bg1};
|
||||
/* border: 4px solid ${({ theme }) => theme.bg0}; */
|
||||
z-index: 2;
|
||||
`
|
||||
|
||||
@@ -53,15 +51,12 @@ export default function SwapModalHeader({
|
||||
showAcceptChanges: boolean
|
||||
onAcceptChanges: () => void
|
||||
}) {
|
||||
const maximumAmountIn = trade.maximumAmountIn(allowedSlippage)
|
||||
const minimumAmountOut = trade.minimumAmountOut(allowedSlippage)
|
||||
|
||||
const theme = useContext(ThemeContext)
|
||||
|
||||
const [showInverted, setShowInverted] = useState<boolean>(false)
|
||||
|
||||
const fiatValueInput = useUSDCValue(maximumAmountIn)
|
||||
const fiatValueOutput = useUSDCValue(minimumAmountOut)
|
||||
const fiatValueInput = useUSDCValue(trade.inputAmount)
|
||||
const fiatValueOutput = useUSDCValue(trade.outputAmount)
|
||||
|
||||
return (
|
||||
<AutoColumn gap={'4px'} style={{ marginTop: '1rem' }}>
|
||||
@@ -86,7 +81,7 @@ export default function SwapModalHeader({
|
||||
fontWeight={500}
|
||||
color={showAcceptChanges && trade.tradeType === TradeType.EXACT_OUTPUT ? theme.primary1 : ''}
|
||||
>
|
||||
{maximumAmountIn.toSignificant(6)}
|
||||
{trade.inputAmount.toSignificant(6)}
|
||||
</TruncatedText>
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
@@ -117,7 +112,7 @@ export default function SwapModalHeader({
|
||||
</RowFixed>
|
||||
<RowFixed gap={'0px'}>
|
||||
<TruncatedText fontSize={24} fontWeight={500}>
|
||||
{minimumAmountOut.toSignificant(6)}
|
||||
{trade.outputAmount.toSignificant(6)}
|
||||
</TruncatedText>
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
@@ -127,11 +122,7 @@ export default function SwapModalHeader({
|
||||
<TYPE.body color={theme.text2} fontWeight={500} fontSize={14}>
|
||||
{'Price:'}
|
||||
</TYPE.body>
|
||||
<TradePrice
|
||||
price={trade.worstExecutionPrice(allowedSlippage)}
|
||||
showInverted={showInverted}
|
||||
setShowInverted={setShowInverted}
|
||||
/>
|
||||
<TradePrice price={trade.executionPrice} showInverted={showInverted} setShowInverted={setShowInverted} />
|
||||
</RowBetween>
|
||||
|
||||
<LightCard style={{ padding: '.75rem', marginTop: '0.5rem' }}>
|
||||
@@ -155,12 +146,12 @@ export default function SwapModalHeader({
|
||||
</SwapShowAcceptChanges>
|
||||
) : null}
|
||||
|
||||
{/* <AutoColumn justify="flex-start" gap="sm" style={{ padding: '.75rem 1rem' }}>
|
||||
<AutoColumn justify="flex-start" gap="sm" style={{ padding: '.75rem 1rem' }}>
|
||||
{trade.tradeType === TradeType.EXACT_INPUT ? (
|
||||
<TYPE.italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
|
||||
{`Output is estimated. You will receive at least `}
|
||||
<b>
|
||||
{minimumAmountOut.toSignificant(6)} {trade.outputAmount.currency.symbol}
|
||||
{trade.minimumAmountOut(allowedSlippage).toSignificant(6)} {trade.outputAmount.currency.symbol}
|
||||
</b>
|
||||
{' or the transaction will revert.'}
|
||||
</TYPE.italic>
|
||||
@@ -168,12 +159,12 @@ export default function SwapModalHeader({
|
||||
<TYPE.italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
|
||||
{`Input is estimated. You will sell at most `}
|
||||
<b>
|
||||
{maximumAmountIn.toSignificant(6)} {trade.inputAmount.currency.symbol}
|
||||
{trade.maximumAmountIn(allowedSlippage).toSignificant(6)} {trade.inputAmount.currency.symbol}
|
||||
</b>
|
||||
{' or the transaction will revert.'}
|
||||
</TYPE.italic>
|
||||
)}
|
||||
</AutoColumn> */}
|
||||
</AutoColumn>
|
||||
{recipient !== null ? (
|
||||
<AutoColumn justify="flex-start" gap="sm" style={{ padding: '12px 0 0 0px' }}>
|
||||
<TYPE.main>
|
||||
|
||||
@@ -1,40 +1,53 @@
|
||||
import { Web3Provider } from '@ethersproject/providers'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { InjectedConnector } from '@web3-react/injected-connector'
|
||||
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
|
||||
import { WalletLinkConnector } from '@web3-react/walletlink-connector'
|
||||
import { PortisConnector } from '@web3-react/portis-connector'
|
||||
import getLibrary from '../utils/getLibrary'
|
||||
|
||||
import { FortmaticConnector } from './Fortmatic'
|
||||
import { NetworkConnector } from './NetworkConnector'
|
||||
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
|
||||
|
||||
const NETWORK_URL = process.env.REACT_APP_NETWORK_URL
|
||||
const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
|
||||
const FORMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY
|
||||
const PORTIS_ID = process.env.REACT_APP_PORTIS_ID
|
||||
const WALLETCONNECT_BRIDGE_URL = process.env.REACT_APP_WALLETCONNECT_BRIDGE_URL
|
||||
|
||||
export const NETWORK_CHAIN_ID: number = parseInt(process.env.REACT_APP_CHAIN_ID ?? '1')
|
||||
|
||||
if (typeof NETWORK_URL === 'undefined') {
|
||||
throw new Error(`REACT_APP_NETWORK_URL must be a defined environment variable`)
|
||||
if (typeof INFURA_KEY === 'undefined') {
|
||||
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
|
||||
}
|
||||
|
||||
const NETWORK_URLS: {
|
||||
[chainId in ChainId]: string
|
||||
} = {
|
||||
[ChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.RINKEBY]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.ROPSTEN]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.GÖRLI]: `https://goerli.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.KOVAN]: `https://kovan.infura.io/v3/${INFURA_KEY}`,
|
||||
}
|
||||
|
||||
const SUPPORTED_CHAIN_IDS = [ChainId.MAINNET, ChainId.RINKEBY, ChainId.ROPSTEN, ChainId.KOVAN, ChainId.GÖRLI]
|
||||
|
||||
export const network = new NetworkConnector({
|
||||
urls: { [NETWORK_CHAIN_ID]: NETWORK_URL },
|
||||
urls: NETWORK_URLS,
|
||||
defaultChainId: ChainId.MAINNET,
|
||||
})
|
||||
|
||||
let networkLibrary: Web3Provider | undefined
|
||||
export function getNetworkLibrary(): Web3Provider {
|
||||
return (networkLibrary = networkLibrary ?? new Web3Provider(network.provider as any))
|
||||
return (networkLibrary = networkLibrary ?? getLibrary(network.provider))
|
||||
}
|
||||
|
||||
export const injected = new InjectedConnector({
|
||||
supportedChainIds: [1, 3, 4, 5, 42],
|
||||
supportedChainIds: SUPPORTED_CHAIN_IDS,
|
||||
})
|
||||
|
||||
// mainnet only
|
||||
export const walletconnect = new WalletConnectConnector({
|
||||
rpc: { 1: NETWORK_URL },
|
||||
supportedChainIds: SUPPORTED_CHAIN_IDS,
|
||||
infuraId: INFURA_KEY, // obviously a hack
|
||||
bridge: WALLETCONNECT_BRIDGE_URL,
|
||||
qrcode: true,
|
||||
pollingInterval: 15000,
|
||||
@@ -54,7 +67,7 @@ export const portis = new PortisConnector({
|
||||
|
||||
// mainnet only
|
||||
export const walletlink = new WalletLinkConnector({
|
||||
url: NETWORK_URL,
|
||||
url: NETWORK_URLS[ChainId.MAINNET],
|
||||
appName: 'Uniswap',
|
||||
appLogoUrl: UNISWAP_LOGO_URL,
|
||||
})
|
||||
|
||||
22
src/hooks/useApeModeQueryParamReader.ts
Normal file
22
src/hooks/useApeModeQueryParamReader.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { AppDispatch } from 'state'
|
||||
import { updateUserExpertMode } from '../state/user/actions'
|
||||
import useParsedQueryString from './useParsedQueryString'
|
||||
|
||||
export default function ApeModeQueryParamReader(): null {
|
||||
useApeModeQueryParamReader()
|
||||
return null
|
||||
}
|
||||
|
||||
function useApeModeQueryParamReader() {
|
||||
const dispatch = useDispatch<AppDispatch>()
|
||||
const { ape } = useParsedQueryString()
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof ape !== 'string') return
|
||||
if (ape === '' || ape.toLowerCase() === 'true') {
|
||||
dispatch(updateUserExpertMode({ userExpertMode: true }))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { ChainId } from '@uniswap/sdk-core'
|
||||
import { TokenList } from '@uniswap/token-lists'
|
||||
import { useCallback } from 'react'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { getNetworkLibrary, NETWORK_CHAIN_ID } from '../connectors'
|
||||
import { getNetworkLibrary } from '../connectors'
|
||||
import { AppDispatch } from '../state'
|
||||
import { fetchTokenList } from '../state/lists/actions'
|
||||
import getTokenList from '../utils/getTokenList'
|
||||
@@ -15,13 +15,12 @@ export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean
|
||||
const dispatch = useDispatch<AppDispatch>()
|
||||
|
||||
const ensResolver = useCallback(
|
||||
(ensName: string) => {
|
||||
async (ensName: string) => {
|
||||
if (!library || chainId !== ChainId.MAINNET) {
|
||||
if (NETWORK_CHAIN_ID === ChainId.MAINNET) {
|
||||
const networkLibrary = getNetworkLibrary()
|
||||
if (networkLibrary) {
|
||||
return resolveENSContentHash(ensName, networkLibrary)
|
||||
}
|
||||
const networkLibrary = getNetworkLibrary()
|
||||
const network = await networkLibrary.getNetwork()
|
||||
if (networkLibrary && network.chainId === ChainId.MAINNET) {
|
||||
return resolveENSContentHash(ensName, networkLibrary)
|
||||
}
|
||||
throw new Error('Could not construct mainnet ENS resolver')
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ export function swapErrorToUserReadableMessage(error: any): string {
|
||||
let reason: string | undefined
|
||||
while (Boolean(error)) {
|
||||
reason = error.reason ?? error.message ?? reason
|
||||
error = error.error ?? error.data.originalError
|
||||
error = error.error ?? error.data?.originalError
|
||||
}
|
||||
|
||||
if (reason?.indexOf('execution reverted: ') === 0) reason = reason.substr('execution reverted: '.length)
|
||||
@@ -153,16 +153,20 @@ export function swapErrorToUserReadableMessage(error: any): string {
|
||||
case 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT':
|
||||
case 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT':
|
||||
return 'This transaction will not succeed either due to price movement or fee on transfer. Try increasing your slippage tolerance.'
|
||||
case 'TransferHelper: TRANSFER_FROM_FAILED':
|
||||
return 'The input token cannot be transferred. There may be an issue with the input token.'
|
||||
case 'UniswapV2: TRANSFER_FAILED':
|
||||
return 'The token could not be transferred. There may be an issue with the token.'
|
||||
return 'The output token cannot be transferred. There may be an issue with the output token.'
|
||||
case 'UniswapV2: K':
|
||||
return 'The Uniswap invariant x*y=k was not satisfied by the swap. This usually means one of the tokens you are swapping incorporates custom behavior on transfer.'
|
||||
case 'Too little received':
|
||||
case 'Too much requested':
|
||||
case 'STF':
|
||||
return 'This transaction will not succeed due to price movement. Try increasing your slippage tolerance.'
|
||||
return 'This transaction will not succeed due to price movement. Try increasing your slippage tolerance. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.'
|
||||
case 'TF':
|
||||
return 'The output token cannot be transferred. There may be an issue with the output token. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.'
|
||||
default:
|
||||
return 'Unknown error. Please join the Discord to get help.'
|
||||
return `Unknown error${reason ? `: "${reason}"` : ''}. Please join the Discord to get help.`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,8 +275,8 @@ export function useSwapCallback(
|
||||
.then((response) => {
|
||||
const inputSymbol = trade.inputAmount.currency.symbol
|
||||
const outputSymbol = trade.outputAmount.currency.symbol
|
||||
const inputAmount = trade.maximumAmountIn(allowedSlippage).toSignificant(4)
|
||||
const outputAmount = trade.minimumAmountOut(allowedSlippage).toSignificant(4)
|
||||
const inputAmount = trade.inputAmount.toSignificant(4)
|
||||
const outputAmount = trade.outputAmount.toSignificant(4)
|
||||
|
||||
const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}`
|
||||
const withRecipient =
|
||||
@@ -302,13 +306,11 @@ export function useSwapCallback(
|
||||
// otherwise, the error was unexpected and we need to convey that
|
||||
console.error(`Swap failed`, error, address, calldata, value)
|
||||
|
||||
throw new Error(
|
||||
`Swap failed: ${'reason' in error ? swapErrorToUserReadableMessage(error) : error.message}`
|
||||
)
|
||||
throw new Error(`Swap failed: ${swapErrorToUserReadableMessage(error)}`)
|
||||
}
|
||||
})
|
||||
},
|
||||
error: null,
|
||||
}
|
||||
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, allowedSlippage, addTransaction])
|
||||
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction])
|
||||
}
|
||||
|
||||
@@ -56,7 +56,9 @@ export default function useUSDCPrice(currency?: Currency): Price<Currency, Token
|
||||
|
||||
const ethPairETHAmount = ethPair?.reserveOf(weth)
|
||||
const ethPairETHUSDCValue: JSBI =
|
||||
ethPairETHAmount && usdcEthPair ? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).quotient : JSBI.BigInt(0)
|
||||
ethPairETHAmount?.greaterThan(0) && usdcEthPair?.reserveOf(weth)?.greaterThan(0)
|
||||
? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).quotient
|
||||
: JSBI.BigInt(0)
|
||||
|
||||
// all other tokens
|
||||
// first try the usdc pair
|
||||
@@ -81,6 +83,10 @@ export function useUSDCValue(currencyAmount: CurrencyAmount<Currency> | undefine
|
||||
|
||||
return useMemo(() => {
|
||||
if (!price || !currencyAmount) return null
|
||||
return price.quote(currencyAmount)
|
||||
try {
|
||||
return price.quote(currencyAmount)
|
||||
} catch (error) {
|
||||
return null
|
||||
}
|
||||
}, [currencyAmount, price])
|
||||
}
|
||||
|
||||
@@ -3,16 +3,18 @@ import { useEffect, useState } from 'react'
|
||||
import { useV3NFTPositionManagerContract } from './useContract'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Pool } from '@uniswap/v3-sdk'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Token, currencyEquals, ETHER, Ether } from '@uniswap/sdk-core'
|
||||
import { useBlockNumber } from 'state/application/hooks'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
|
||||
const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)
|
||||
|
||||
// compute current + counterfactual fees for a v3 position
|
||||
export function useV3PositionFees(
|
||||
pool?: Pool,
|
||||
tokenId?: BigNumber
|
||||
): [CurrencyAmount<Token>, CurrencyAmount<Token>] | [undefined, undefined] {
|
||||
tokenId?: BigNumber,
|
||||
asWETH = false
|
||||
): [CurrencyAmount<Token | Ether>, CurrencyAmount<Token | Ether>] | [undefined, undefined] {
|
||||
const positionManager = useV3NFTPositionManagerContract(false)
|
||||
const owner = useSingleCallResult(tokenId ? positionManager : null, 'ownerOf', [tokenId]).result?.[0]
|
||||
|
||||
@@ -43,8 +45,12 @@ export function useV3PositionFees(
|
||||
|
||||
if (pool && amounts) {
|
||||
return [
|
||||
CurrencyAmount.fromRawAmount(pool.token0, amounts[0].toString()),
|
||||
CurrencyAmount.fromRawAmount(pool.token1, amounts[1].toString()),
|
||||
!asWETH && currencyEquals(unwrappedToken(pool.token0), ETHER)
|
||||
? CurrencyAmount.ether(amounts[0].toString())
|
||||
: CurrencyAmount.fromRawAmount(pool.token0, amounts[0].toString()),
|
||||
!asWETH && currencyEquals(unwrappedToken(pool.token1), ETHER)
|
||||
? CurrencyAmount.ether(amounts[1].toString())
|
||||
: CurrencyAmount.fromRawAmount(pool.token1, amounts[1].toString()),
|
||||
]
|
||||
} else {
|
||||
return [undefined, undefined]
|
||||
|
||||
@@ -29,6 +29,7 @@ import { RedirectDuplicateTokenIdsV2 } from './AddLiquidityV2/redirects'
|
||||
import { PositionPage } from './Pool/PositionPage'
|
||||
import AddLiquidity from './AddLiquidity'
|
||||
import { ThemedBackground } from '../theme'
|
||||
import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader'
|
||||
|
||||
const AppWrapper = styled.div`
|
||||
display: flex;
|
||||
@@ -76,6 +77,7 @@ export default function App() {
|
||||
<Suspense fallback={null}>
|
||||
<Route component={GoogleAnalyticsReporter} />
|
||||
<Route component={DarkModeQueryParamReader} />
|
||||
<Route component={ApeModeQueryParamReader} />
|
||||
<AppWrapper>
|
||||
<HeaderWrapper>
|
||||
<Header />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { SyntheticEvent, useCallback, useMemo, useRef, useState } from 'react'
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
||||
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { Link, RouteComponentProps } from 'react-router-dom'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import { unwrappedToken, wrappedCurrencyAmount } from 'utils/wrappedCurrency'
|
||||
import { usePositionTokenURI } from '../../hooks/usePositionTokenURI'
|
||||
import { LoadingRows } from './styleds'
|
||||
import styled from 'styled-components/macro'
|
||||
@@ -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 { Token, WETH9, Currency, CurrencyAmount, Percent, Fraction, Price, currencyEquals } from '@uniswap/sdk-core'
|
||||
import { Token, Currency, CurrencyAmount, Percent, Fraction, Price, Ether } from '@uniswap/sdk-core'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
@@ -38,6 +38,7 @@ import { useSingleCallResult } from 'state/multicall/hooks'
|
||||
import RangeBadge from '../../components/Badge/RangeBadge'
|
||||
import useUSDCPrice from 'hooks/useUSDCPrice'
|
||||
import Loader from 'components/Loader'
|
||||
import Toggle from 'components/Toggle'
|
||||
|
||||
const PageWrapper = styled.div`
|
||||
min-width: 800px;
|
||||
@@ -200,20 +201,11 @@ function getRatio(
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// snapshots a src img into a canvas
|
||||
function getSnapshot(src: HTMLImageElement, canvas: HTMLCanvasElement, targetHeight: number) {
|
||||
const context = canvas.getContext('2d')
|
||||
|
||||
if (context) {
|
||||
let { width, height } = src
|
||||
|
||||
// src may be hidden and not have the target dimensions
|
||||
@@ -231,15 +223,39 @@ function NFT({ image, height: targetHeight }: { image: string; height: number })
|
||||
context.clearRect(0, 0, width, height)
|
||||
context.drawImage(src, 0, 0, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
const onLoad = (e: SyntheticEvent<HTMLImageElement>) => {
|
||||
getSnapshot(e.target as HTMLImageElement)
|
||||
}
|
||||
function NFT({ image, height: targetHeight }: { image: string; height: number }) {
|
||||
const [animate, setAnimate] = useState(false)
|
||||
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||
const imageRef = useRef<HTMLImageElement>(null)
|
||||
|
||||
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
|
||||
onMouseEnter={() => {
|
||||
setAnimate(true)
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
// snapshot the current frame so the transition to the canvas is smooth
|
||||
if (imageRef.current && canvasRef.current) {
|
||||
getSnapshot(imageRef.current, canvasRef.current, targetHeight)
|
||||
}
|
||||
setAnimate(false)
|
||||
}}
|
||||
>
|
||||
<NFTCanvas ref={canvasRef} />
|
||||
<NFTImage
|
||||
ref={imageRef}
|
||||
src={image}
|
||||
hidden={!animate}
|
||||
onLoad={() => {
|
||||
// snapshot for the canvas
|
||||
if (imageRef.current && canvasRef.current) {
|
||||
getSnapshot(imageRef.current, canvasRef.current, targetHeight)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</NFTGrid>
|
||||
)
|
||||
}
|
||||
@@ -269,8 +285,11 @@ export function PositionPage({
|
||||
const currency0 = token0 ? unwrappedToken(token0) : undefined
|
||||
const currency1 = token1 ? unwrappedToken(token1) : undefined
|
||||
|
||||
// flag for receiving WETH
|
||||
const [receiveWETH, setReceiveWETH] = useState(false)
|
||||
|
||||
// construct Position from details returned
|
||||
const [poolState, pool] = usePool(currency0 ?? undefined, currency1 ?? undefined, feeAmount)
|
||||
const [poolState, pool] = usePool(token0 ?? undefined, token1 ?? undefined, feeAmount)
|
||||
const position = useMemo(() => {
|
||||
if (pool && liquidity && typeof tickLower === 'number' && typeof tickUpper === 'number') {
|
||||
return new Position({ pool, liquidity: liquidity.toString(), tickLower, tickUpper })
|
||||
@@ -304,7 +323,7 @@ export function PositionPage({
|
||||
}, [inverted, pool, priceLower, priceUpper])
|
||||
|
||||
// fees
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails?.tokenId)
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails?.tokenId, receiveWETH)
|
||||
|
||||
const [collecting, setCollecting] = useState<boolean>(false)
|
||||
const [collectMigrationHash, setCollectMigrationHash] = useState<string | null>(null)
|
||||
@@ -320,12 +339,8 @@ export function PositionPage({
|
||||
|
||||
const { calldata, value } = NonfungiblePositionManager.collectCallParameters({
|
||||
tokenId: tokenId.toString(),
|
||||
expectedCurrencyOwed0: currencyEquals(feeValue0.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue0.quotient)
|
||||
: feeValue0,
|
||||
expectedCurrencyOwed1: currencyEquals(feeValue1.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue1.quotient)
|
||||
: feeValue1,
|
||||
expectedCurrencyOwed0: feeValue0,
|
||||
expectedCurrencyOwed1: feeValue1,
|
||||
recipient: account,
|
||||
})
|
||||
|
||||
@@ -371,15 +386,23 @@ export function PositionPage({
|
||||
const owner = useSingleCallResult(!!tokenId ? positionManager : null, 'ownerOf', [tokenId]).result?.[0]
|
||||
const ownsNFT = owner === account || positionDetails?.operator === account
|
||||
|
||||
// usdc prices always in terms of tokens
|
||||
const price0 = useUSDCPrice(token0 ?? undefined)
|
||||
const price1 = useUSDCPrice(token1 ?? undefined)
|
||||
|
||||
const fiatValueOfFees: CurrencyAmount<Token> | null = useMemo(() => {
|
||||
const fiatValueOfFees: CurrencyAmount<Token | Ether> | null = useMemo(() => {
|
||||
if (!price0 || !price1 || !feeValue0 || !feeValue1) return null
|
||||
const amount0 = price0.quote(feeValue0)
|
||||
const amount1 = price1.quote(feeValue1)
|
||||
|
||||
// we wrap because it doesn't matter, the quote returns a USDC amount
|
||||
const feeValue0Wrapped = wrappedCurrencyAmount(feeValue0, chainId)
|
||||
const feeValue1Wrapped = wrappedCurrencyAmount(feeValue1, chainId)
|
||||
|
||||
if (!feeValue0Wrapped || !feeValue1Wrapped) return null
|
||||
|
||||
const amount0 = price0.quote(feeValue0Wrapped)
|
||||
const amount1 = price1.quote(feeValue1Wrapped)
|
||||
return amount0.add(amount1)
|
||||
}, [price0, price1, feeValue0, feeValue1])
|
||||
}, [price0, price1, feeValue0, feeValue1, chainId])
|
||||
|
||||
const fiatValueOfLiquidity: CurrencyAmount<Token> | null = useMemo(() => {
|
||||
if (!price0 || !price1 || !position) return null
|
||||
@@ -388,6 +411,9 @@ export function PositionPage({
|
||||
return amount0.add(amount1)
|
||||
}, [price0, price1, position])
|
||||
|
||||
const feeValueUpper = inverted ? feeValue0 : feeValue1
|
||||
const feeValueLower = inverted ? feeValue1 : feeValue0
|
||||
|
||||
function modalHeader() {
|
||||
return (
|
||||
<AutoColumn gap={'md'} style={{ marginTop: '20px' }}>
|
||||
@@ -395,33 +421,17 @@ export function PositionPage({
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currencyQuote} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>
|
||||
{inverted
|
||||
? feeValue0
|
||||
? formatTokenAmount(feeValue0, 4)
|
||||
: '-'
|
||||
: feeValue1
|
||||
? formatTokenAmount(feeValue1, 4)
|
||||
: '-'}
|
||||
</TYPE.main>
|
||||
<CurrencyLogo currency={feeValueUpper?.currency} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{feeValueUpper ? formatTokenAmount(feeValueUpper, 4) : '-'}</TYPE.main>
|
||||
</RowFixed>
|
||||
<TYPE.main>{currencyQuote?.symbol}</TYPE.main>
|
||||
<TYPE.main>{feeValueUpper?.currency?.symbol}</TYPE.main>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currencyBase} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>
|
||||
{inverted
|
||||
? feeValue0
|
||||
? formatTokenAmount(feeValue1, 4)
|
||||
: '-'
|
||||
: feeValue1
|
||||
? formatTokenAmount(feeValue0, 4)
|
||||
: '-'}
|
||||
</TYPE.main>
|
||||
<CurrencyLogo currency={feeValueLower?.currency} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{feeValueLower ? formatTokenAmount(feeValueLower, 4) : '-'}</TYPE.main>
|
||||
</RowFixed>
|
||||
<TYPE.main>{currencyBase?.symbol}</TYPE.main>
|
||||
<TYPE.main>{feeValueLower?.currency?.symbol}</TYPE.main>
|
||||
</RowBetween>
|
||||
</AutoColumn>
|
||||
</LightCard>
|
||||
@@ -640,40 +650,44 @@ export function PositionPage({
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currencyQuote} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{currencyQuote?.symbol}</TYPE.main>
|
||||
<CurrencyLogo
|
||||
currency={feeValueUpper?.currency}
|
||||
size={'20px'}
|
||||
style={{ marginRight: '0.5rem' }}
|
||||
/>
|
||||
<TYPE.main>{feeValueUpper?.currency?.symbol}</TYPE.main>
|
||||
</RowFixed>
|
||||
<RowFixed>
|
||||
<TYPE.main>
|
||||
{inverted
|
||||
? feeValue0
|
||||
? formatTokenAmount(feeValue0, 4)
|
||||
: '-'
|
||||
: feeValue1
|
||||
? formatTokenAmount(feeValue1, 4)
|
||||
: '-'}
|
||||
</TYPE.main>
|
||||
<TYPE.main>{feeValueUpper ? formatTokenAmount(feeValueUpper, 4) : '-'}</TYPE.main>
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currencyBase} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{currencyBase?.symbol}</TYPE.main>
|
||||
<CurrencyLogo
|
||||
currency={feeValueLower?.currency}
|
||||
size={'20px'}
|
||||
style={{ marginRight: '0.5rem' }}
|
||||
/>
|
||||
<TYPE.main>{feeValueLower?.currency?.symbol}</TYPE.main>
|
||||
</RowFixed>
|
||||
<RowFixed>
|
||||
<TYPE.main>
|
||||
{inverted
|
||||
? feeValue0
|
||||
? formatTokenAmount(feeValue1, 4)
|
||||
: '-'
|
||||
: feeValue1
|
||||
? formatTokenAmount(feeValue0, 4)
|
||||
: '-'}
|
||||
</TYPE.main>
|
||||
<TYPE.main>{feeValueLower ? formatTokenAmount(feeValueLower, 4) : '-'}</TYPE.main>
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
</AutoColumn>
|
||||
</LightCard>
|
||||
{ownsNFT && (feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0)) && !collectMigrationHash ? (
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<TYPE.main>Collect as WETH</TYPE.main>
|
||||
<Toggle
|
||||
id="receive-as-weth"
|
||||
isActive={receiveWETH}
|
||||
toggle={() => setReceiveWETH((receiveWETH) => !receiveWETH)}
|
||||
/>
|
||||
</RowBetween>
|
||||
</AutoColumn>
|
||||
) : null}
|
||||
</AutoColumn>
|
||||
</DarkCard>
|
||||
</AutoColumn>
|
||||
|
||||
@@ -21,12 +21,10 @@ import ReactGA from 'react-ga'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from 'state/transactions/hooks'
|
||||
import { WETH9, CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import { TYPE } from 'theme'
|
||||
import { Wrapper, SmallMaxButton, ResponsiveHeaderText } from './styled'
|
||||
import Loader from 'components/Loader'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import { Break } from 'components/earn/styled'
|
||||
import { NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
||||
@@ -34,6 +32,7 @@ import { calculateGasMargin } from 'utils'
|
||||
import useTheme from 'hooks/useTheme'
|
||||
import { AddRemoveTabs } from 'components/NavigationTabs'
|
||||
import RangeBadge from 'components/Badge/RangeBadge'
|
||||
import Toggle from 'components/Toggle'
|
||||
|
||||
export const UINT128MAX = BigNumber.from(2).pow(128).sub(1)
|
||||
|
||||
@@ -65,11 +64,8 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
const theme = useTheme()
|
||||
const { account, chainId, library } = useActiveWeb3React()
|
||||
|
||||
// currencies from position
|
||||
const token0 = useToken(position?.token0)
|
||||
const token1 = useToken(position?.token1)
|
||||
const currency0 = token0 ? unwrappedToken(token0) : undefined
|
||||
const currency1 = token1 ? unwrappedToken(token1) : undefined
|
||||
// flag for receiving WETH
|
||||
const [receiveWETH, setReceiveWETH] = useState(false)
|
||||
|
||||
// burn state
|
||||
const { percent } = useBurnV3State()
|
||||
@@ -82,7 +78,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
feeValue1,
|
||||
outOfRange,
|
||||
error,
|
||||
} = useDerivedV3BurnInfo(position)
|
||||
} = useDerivedV3BurnInfo(position, receiveWETH)
|
||||
const { onPercentSelect } = useBurnV3ActionHandlers()
|
||||
|
||||
const removed = position?.liquidity?.eq(0)
|
||||
@@ -122,12 +118,8 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
slippageTolerance: allowedSlippage,
|
||||
deadline: deadline.toString(),
|
||||
collectOptions: {
|
||||
expectedCurrencyOwed0: currencyEquals(liquidityValue0.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue0.quotient)
|
||||
: feeValue0,
|
||||
expectedCurrencyOwed1: currencyEquals(liquidityValue1.currency, WETH9[chainId])
|
||||
? CurrencyAmount.ether(feeValue1.quotient)
|
||||
: feeValue1,
|
||||
expectedCurrencyOwed0: feeValue0,
|
||||
expectedCurrencyOwed1: feeValue1,
|
||||
recipient: account,
|
||||
},
|
||||
})
|
||||
@@ -195,32 +187,32 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
}, [onPercentSelectForSlider, txnHash])
|
||||
|
||||
const pendingText = `Removing ${liquidityValue0?.toSignificant(6)} ${
|
||||
currency0?.symbol
|
||||
} and ${liquidityValue1?.toSignificant(6)} ${currency1?.symbol}`
|
||||
liquidityValue0?.currency?.symbol
|
||||
} and ${liquidityValue1?.toSignificant(6)} ${liquidityValue1?.currency?.symbol}`
|
||||
|
||||
function modalHeader() {
|
||||
return (
|
||||
<AutoColumn gap={'sm'} style={{ padding: '16px' }}>
|
||||
<RowBetween align="flex-end">
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
{currency0?.symbol}:
|
||||
Pooled {liquidityValue0?.currency?.symbol}:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{liquidityValue0 && <FormattedCurrencyAmount currencyAmount={liquidityValue0} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={liquidityValue0?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
<RowBetween align="flex-end">
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
{currency1?.symbol}:
|
||||
Pooled {liquidityValue1?.currency?.symbol}:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{liquidityValue1 && <FormattedCurrencyAmount currencyAmount={liquidityValue1} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={liquidityValue1?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
{feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) ? (
|
||||
@@ -230,24 +222,24 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
</TYPE.italic>
|
||||
<RowBetween>
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
{currency0?.symbol} from fees:
|
||||
{feeValue0?.currency?.symbol} Fees Earned:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{feeValue0 && <FormattedCurrencyAmount currencyAmount={feeValue0} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={feeValue0?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
{currency1?.symbol} from fees:
|
||||
{feeValue1?.currency?.symbol} Fees Earned:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{feeValue1 && <FormattedCurrencyAmount currencyAmount={feeValue1} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={feeValue1?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
</>
|
||||
@@ -287,8 +279,16 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
<AutoColumn gap="lg">
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<DoubleCurrencyLogo currency0={currency1} currency1={currency0} size={20} margin={true} />
|
||||
<TYPE.label ml="10px" fontSize="20px">{`${currency0?.symbol}/${currency1?.symbol}`}</TYPE.label>
|
||||
<DoubleCurrencyLogo
|
||||
currency0={feeValue0?.currency}
|
||||
currency1={feeValue1?.currency}
|
||||
size={20}
|
||||
margin={true}
|
||||
/>
|
||||
<TYPE.label
|
||||
ml="10px"
|
||||
fontSize="20px"
|
||||
>{`${feeValue0?.currency?.symbol}/${feeValue1?.currency?.symbol}`}</TYPE.label>
|
||||
</RowFixed>
|
||||
<RangeBadge removed={removed} inRange={!outOfRange} />
|
||||
</RowBetween>
|
||||
@@ -319,24 +319,24 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
Pooled {currency0?.symbol}:
|
||||
Pooled {liquidityValue0?.currency?.symbol}:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{liquidityValue0 && <FormattedCurrencyAmount currencyAmount={liquidityValue0} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={liquidityValue0?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
Pooled {currency1?.symbol}:
|
||||
Pooled {liquidityValue1?.currency?.symbol}:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{liquidityValue1 && <FormattedCurrencyAmount currencyAmount={liquidityValue1} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={liquidityValue1?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
{feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) ? (
|
||||
@@ -344,30 +344,40 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
<Break />
|
||||
<RowBetween>
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
{currency0?.symbol} Fees Earned:
|
||||
{feeValue0?.currency?.symbol} Fees Earned:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{feeValue0 && <FormattedCurrencyAmount currencyAmount={feeValue0} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={feeValue0?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<Text fontSize={16} fontWeight={500}>
|
||||
{currency1?.symbol} Fees Earned:
|
||||
{feeValue1?.currency?.symbol} Fees Earned:
|
||||
</Text>
|
||||
<RowFixed>
|
||||
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
|
||||
{feeValue1 && <FormattedCurrencyAmount currencyAmount={feeValue1} />}
|
||||
</Text>
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
|
||||
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={feeValue1?.currency} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
</>
|
||||
) : null}
|
||||
</AutoColumn>
|
||||
</LightCard>
|
||||
|
||||
<RowBetween>
|
||||
<TYPE.main>Collect as WETH</TYPE.main>
|
||||
<Toggle
|
||||
id="receive-as-weth"
|
||||
isActive={receiveWETH}
|
||||
toggle={() => setReceiveWETH((receiveWETH) => !receiveWETH)}
|
||||
/>
|
||||
</RowBetween>
|
||||
|
||||
<div style={{ display: 'flex' }}>
|
||||
<AutoColumn gap="12px" style={{ flex: '1' }}>
|
||||
<ButtonConfirmed
|
||||
|
||||
@@ -49,7 +49,6 @@ import {
|
||||
import { useExpertModeManager, useUserSingleHopOnly } from '../../state/user/hooks'
|
||||
import { HideSmall, LinkStyledButton, TYPE } from '../../theme'
|
||||
import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact'
|
||||
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
|
||||
import { getTradeVersion } from '../../utils/getTradeVersion'
|
||||
import { isTradeBetter } from '../../utils/isTradeBetter'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
@@ -132,10 +131,10 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
[Field.OUTPUT]: parsedAmount,
|
||||
}
|
||||
: {
|
||||
[Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.maximumAmountIn(allowedSlippage),
|
||||
[Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.minimumAmountOut(allowedSlippage),
|
||||
[Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.inputAmount,
|
||||
[Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.outputAmount,
|
||||
},
|
||||
[allowedSlippage, independentField, parsedAmount, showWrap, trade]
|
||||
[independentField, parsedAmount, showWrap, trade]
|
||||
)
|
||||
|
||||
const fiatValueInput = useUSDCValue(parsedAmounts[Field.INPUT])
|
||||
@@ -292,7 +291,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
|
||||
// warnings on the greater of fiat value price impact and execution price impact
|
||||
const priceImpactSeverity = useMemo(() => {
|
||||
const executionPriceImpact = trade ? computePriceImpactWithMaximumSlippage(trade, allowedSlippage) : undefined
|
||||
const executionPriceImpact = trade?.priceImpact
|
||||
return warningSeverity(
|
||||
executionPriceImpact && priceImpact
|
||||
? executionPriceImpact.greaterThan(priceImpact)
|
||||
@@ -300,7 +299,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
: priceImpact
|
||||
: executionPriceImpact ?? priceImpact
|
||||
)
|
||||
}, [allowedSlippage, priceImpact, trade])
|
||||
}, [priceImpact, trade])
|
||||
|
||||
// show approve flow when: no error on inputs, not approved or pending, or approved in current session
|
||||
// never show if price impact is above threshold in non expert mode
|
||||
@@ -475,7 +474,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
{trade ? (
|
||||
<RowFixed>
|
||||
<TradePrice
|
||||
price={trade.worstExecutionPrice(allowedSlippage)}
|
||||
price={trade.executionPrice}
|
||||
showInverted={showInverted}
|
||||
setShowInverted={setShowInverted}
|
||||
/>
|
||||
@@ -526,12 +525,12 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
approvalState === ApprovalState.APPROVED || signatureState === UseERC20PermitState.SIGNED
|
||||
}
|
||||
>
|
||||
<AutoRow justify="space-between">
|
||||
<AutoRow justify="space-between" style={{ flexWrap: 'nowrap' }}>
|
||||
<span style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<CurrencyLogo
|
||||
currency={currencies[Field.INPUT]}
|
||||
size={'20px'}
|
||||
style={{ marginRight: '8px' }}
|
||||
style={{ marginRight: '8px', flexShrink: 0 }}
|
||||
/>
|
||||
{/* we need to shorten this string on mobile */}
|
||||
{approvalState === ApprovalState.APPROVED || signatureState === UseERC20PermitState.SIGNED
|
||||
@@ -551,7 +550,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
'. You only have to do this once per token.'
|
||||
}
|
||||
>
|
||||
<HelpCircle size="20" color={'white'} />
|
||||
<HelpCircle size="20" color={'white'} style={{ marginLeft: '8px' }} />
|
||||
</MouseoverTooltip>
|
||||
)}
|
||||
</AutoRow>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Token, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { Token, CurrencyAmount, Percent, Ether, currencyEquals, ETHER } from '@uniswap/sdk-core'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import { usePool } from 'hooks/usePools'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
@@ -10,20 +10,22 @@ import { PositionDetails } from 'types/position'
|
||||
|
||||
import { AppDispatch, AppState } from '../../index'
|
||||
import { selectPercent } from './actions'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
|
||||
export function useBurnV3State(): AppState['burnV3'] {
|
||||
return useSelector<AppState, AppState['burnV3']>((state) => state.burnV3)
|
||||
}
|
||||
|
||||
export function useDerivedV3BurnInfo(
|
||||
position?: PositionDetails
|
||||
position?: PositionDetails,
|
||||
asWETH = false
|
||||
): {
|
||||
position?: Position
|
||||
liquidityPercentage?: Percent
|
||||
liquidityValue0?: CurrencyAmount<Token>
|
||||
liquidityValue1?: CurrencyAmount<Token>
|
||||
feeValue0?: CurrencyAmount<Token>
|
||||
feeValue1?: CurrencyAmount<Token>
|
||||
liquidityValue0?: CurrencyAmount<Token | Ether>
|
||||
liquidityValue1?: CurrencyAmount<Token | Ether>
|
||||
feeValue0?: CurrencyAmount<Token | Ether>
|
||||
feeValue1?: CurrencyAmount<Token | Ether>
|
||||
outOfRange: boolean
|
||||
error?: string
|
||||
} {
|
||||
@@ -50,20 +52,27 @@ export function useDerivedV3BurnInfo(
|
||||
|
||||
const liquidityPercentage = new Percent(percent, 100)
|
||||
|
||||
const liquidityValue0 =
|
||||
positionSDK &&
|
||||
CurrencyAmount.fromRawAmount(
|
||||
positionSDK.amount0.currency,
|
||||
liquidityPercentage.multiply(positionSDK.amount0.quotient).quotient
|
||||
)
|
||||
const liquidityValue1 =
|
||||
positionSDK &&
|
||||
CurrencyAmount.fromRawAmount(
|
||||
positionSDK.amount1.currency,
|
||||
liquidityPercentage.multiply(positionSDK.amount1.quotient).quotient
|
||||
)
|
||||
const discountedAmount0 = positionSDK
|
||||
? liquidityPercentage.multiply(positionSDK.amount0.quotient).quotient
|
||||
: undefined
|
||||
const discountedAmount1 = positionSDK
|
||||
? liquidityPercentage.multiply(positionSDK.amount1.quotient).quotient
|
||||
: undefined
|
||||
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, position?.tokenId)
|
||||
const liquidityValue0 =
|
||||
token0 && discountedAmount0
|
||||
? currencyEquals(unwrappedToken(token0), ETHER) && !asWETH
|
||||
? CurrencyAmount.ether(discountedAmount0)
|
||||
: CurrencyAmount.fromRawAmount(token0, discountedAmount0)
|
||||
: undefined
|
||||
const liquidityValue1 =
|
||||
token1 && discountedAmount1
|
||||
? currencyEquals(unwrappedToken(token1), ETHER) && !asWETH
|
||||
? CurrencyAmount.ether(discountedAmount1)
|
||||
: CurrencyAmount.fromRawAmount(token1, discountedAmount1)
|
||||
: undefined
|
||||
|
||||
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, position?.tokenId, asWETH)
|
||||
|
||||
const outOfRange =
|
||||
pool && position ? pool.tickCurrent < position.tickLower || pool.tickCurrent > position.tickUpper : false
|
||||
|
||||
@@ -28,7 +28,7 @@ const store = configureStore({
|
||||
multicall,
|
||||
lists,
|
||||
},
|
||||
middleware: [...getDefaultMiddleware({ thunk: false }), save({ states: PERSISTED_KEYS })],
|
||||
middleware: [...getDefaultMiddleware({ thunk: false }), save({ states: PERSISTED_KEYS, debounce: 1000 })],
|
||||
preloadedState: load({ states: PERSISTED_KEYS }),
|
||||
})
|
||||
|
||||
|
||||
@@ -164,8 +164,8 @@ export default function Updater(): null {
|
||||
cancellations: chunkedCalls.map((chunk, index) => {
|
||||
const { cancel, promise } = retry(() => fetchChunk(multicall2Contract, chunk, latestBlockNumber), {
|
||||
n: Infinity,
|
||||
minWait: 2500,
|
||||
maxWait: 3500,
|
||||
minWait: 1000,
|
||||
maxWait: 2500,
|
||||
})
|
||||
promise
|
||||
.then(({ results: returnData, blockNumber: fetchBlockNumber }) => {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
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'
|
||||
|
||||
export function computePriceImpactWithMaximumSlippage(
|
||||
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>,
|
||||
allowedSlippage: Percent
|
||||
): Percent {
|
||||
return computePriceImpact(
|
||||
trade.route.midPrice,
|
||||
trade.maximumAmountIn(allowedSlippage),
|
||||
trade.minimumAmountOut(allowedSlippage)
|
||||
)
|
||||
}
|
||||
@@ -22,15 +22,15 @@ export function computeRealizedLPFeePercent(
|
||||
// for each hop in our trade, take away the x*y=k price impact from 0.3% fees
|
||||
// e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03))
|
||||
percent = ONE_HUNDRED_PERCENT.subtract(
|
||||
trade.route.pairs.reduce<Fraction>(
|
||||
(currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
|
||||
trade.route.pairs.reduce<Percent>(
|
||||
(currentFee: Percent): Percent => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
|
||||
ONE_HUNDRED_PERCENT
|
||||
)
|
||||
)
|
||||
} else {
|
||||
percent = ONE_HUNDRED_PERCENT.subtract(
|
||||
trade.route.pools.reduce<Fraction>(
|
||||
(currentFee: Fraction, pool): Fraction =>
|
||||
trade.route.pools.reduce<Percent>(
|
||||
(currentFee: Percent, pool): Percent =>
|
||||
currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(pool.fee, 1_000_000))),
|
||||
ONE_HUNDRED_PERCENT
|
||||
)
|
||||
@@ -44,14 +44,11 @@ export function computeRealizedLPFeePercent(
|
||||
export function computeRealizedLPFeeAmount(
|
||||
trade?: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | null
|
||||
): CurrencyAmount<Currency> | undefined {
|
||||
if (trade instanceof V2Trade || trade instanceof V3Trade) {
|
||||
if (trade) {
|
||||
const realizedLPFee = computeRealizedLPFeePercent(trade)
|
||||
|
||||
// the amount of the input that accrues to LPs
|
||||
return CurrencyAmount.fromRawAmount(
|
||||
trade.inputAmount.currency,
|
||||
trade.inputAmount.asFraction.multiply(realizedLPFee).quotient
|
||||
)
|
||||
return CurrencyAmount.fromRawAmount(trade.inputAmount.currency, trade.inputAmount.multiply(realizedLPFee).quotient)
|
||||
}
|
||||
|
||||
return undefined
|
||||
|
||||
72
yarn.lock
72
yarn.lock
@@ -2452,7 +2452,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b"
|
||||
integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==
|
||||
|
||||
"@metamask/safe-event-emitter@^2.0.0":
|
||||
"@metamask/safe-event-emitter@2.0.0", "@metamask/safe-event-emitter@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c"
|
||||
integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==
|
||||
@@ -4478,10 +4478,10 @@
|
||||
"@uniswap/v3-core" "1.0.0"
|
||||
base64-sol "1.0.1"
|
||||
|
||||
"@uniswap/v3-sdk@^3.0.0-alpha.1":
|
||||
version "3.0.0-alpha.1"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.0.0-alpha.1.tgz#33fcd4b1587d323c6afde3bb546ad0bb1c77e492"
|
||||
integrity sha512-3+rVWwGlryEX/Nu7qevBrScTjZ4791fSfmLDz+U5ofWQL/edhZkjgTY1I/fkndUSI8FKWRppRAdzqcnmbpqqlQ==
|
||||
"@uniswap/v3-sdk@^3.0.0-alpha.4":
|
||||
version "3.0.0-alpha.4"
|
||||
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.0.0-alpha.4.tgz#e8bf26291fd74e36a5a3d9b88f1809a7aceb7d3a"
|
||||
integrity sha512-BcEH8eHt+b6eaaiLDlzbFox2NquP1H7KgrgmNjAlU/et+vC4azdfNN6SsRlTFzhioPOwHlAKAAZJLq+yzboDOQ==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "^5.0.12"
|
||||
"@ethersproject/solidity" "^5.0.9"
|
||||
@@ -4582,7 +4582,7 @@
|
||||
js-sha3 "0.8.0"
|
||||
query-string "6.13.5"
|
||||
|
||||
"@walletconnect/web3-provider@^1.3.6":
|
||||
"@walletconnect/web3-provider@^1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@walletconnect/web3-provider/-/web3-provider-1.4.1.tgz#34f6319ab2473ab9ff0fcf1e8bc280c697fa01ff"
|
||||
integrity sha512-gUoBGM5hdtcXSoLXDTG1/WTamnUNpEWfaYMIVkfVnvVFd4whIjb0iOW5ywvDOf/49wq0C2+QThZL2Wc+r+jKLA==
|
||||
@@ -4646,24 +4646,24 @@
|
||||
resolved "https://registry.yarnpkg.com/@web3-react/types/-/types-6.0.7.tgz#34a6204224467eedc6123abaf55fbb6baeb2809f"
|
||||
integrity sha512-ofGmfDhxmNT1/P/MgVa8IKSkCStFiyvXe+U5tyZurKdrtTDFU+wJ/LxClPDtFerWpczNFPUSrKcuhfPX1sI6+A==
|
||||
|
||||
"@web3-react/walletconnect-connector@^6.1.1":
|
||||
version "6.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@web3-react/walletconnect-connector/-/walletconnect-connector-6.1.9.tgz#3459ccf2a2ac7ae8f155645d29a517712afeb731"
|
||||
integrity sha512-gPtcFFRAnRgqhmBjhH+dtuG3cx23X+JOX+mRO1D7dN+8yxLZhLhjOZlJFECH5hkC20KMM/sk+rq2yy6Vqp76PQ==
|
||||
"@web3-react/walletconnect-connector@^6.2.0":
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@web3-react/walletconnect-connector/-/walletconnect-connector-6.2.0.tgz#5451f332a25b94cf7e615a20cc7d22a27532629d"
|
||||
integrity sha512-F6xYwI3MKiSdKa0248y2wBW0kTDddc2/IGn4CjMSYe0DJFggtxFsAAGHQTRmvwDcLlgQwtemJJ0cTA82MOVfEg==
|
||||
dependencies:
|
||||
"@walletconnect/web3-provider" "^1.3.6"
|
||||
"@walletconnect/web3-provider" "^1.4.1"
|
||||
"@web3-react/abstract-connector" "^6.0.7"
|
||||
"@web3-react/types" "^6.0.7"
|
||||
tiny-invariant "^1.0.6"
|
||||
|
||||
"@web3-react/walletlink-connector@^6.0.9":
|
||||
version "6.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@web3-react/walletlink-connector/-/walletlink-connector-6.1.9.tgz#3b27b79057ea3865b447a2ecdd3807d094f34061"
|
||||
integrity sha512-0kgb28CsUp5k0MVdl3bk5FUSvgDl5psXyRLrXi2WFeHToOJTQnmMstVo9/1Mj36zaYHuSUcdcyLKnLGoabSivQ==
|
||||
"@web3-react/walletlink-connector@^6.2.0":
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@web3-react/walletlink-connector/-/walletlink-connector-6.2.0.tgz#7619bdca5a030b475b3a205f92f949d61e3b9b25"
|
||||
integrity sha512-Vz0QOLHQnZD/xDJfZ+TJ19NLYqy0Ii62RKwaF0xiKnAIcwjrq8MVEPtnY7kB9G1g8EoCD2ghqnWb4NyZTltQHw==
|
||||
dependencies:
|
||||
"@web3-react/abstract-connector" "^6.0.7"
|
||||
"@web3-react/types" "^6.0.7"
|
||||
walletlink "^2.0.2"
|
||||
walletlink "^2.1.0"
|
||||
|
||||
"@webassemblyjs/ast@1.9.0":
|
||||
version "1.9.0"
|
||||
@@ -9114,7 +9114,7 @@ etag@~1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
eth-block-tracker@^4.2.0, eth-block-tracker@^4.4.2:
|
||||
eth-block-tracker@4.4.3, eth-block-tracker@^4.2.0, eth-block-tracker@^4.4.2:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-4.4.3.tgz#766a0a0eb4a52c867a28328e9ae21353812cf626"
|
||||
integrity sha512-A8tG4Z4iNg4mw5tP1Vung9N9IjgMNqpiMoJ/FouSFwNCGHv2X0mmOYwtQOJzki6XN7r7Tyo01S29p7b224I4jw==
|
||||
@@ -9126,7 +9126,7 @@ eth-block-tracker@^4.2.0, eth-block-tracker@^4.4.2:
|
||||
pify "^3.0.0"
|
||||
safe-event-emitter "^1.0.1"
|
||||
|
||||
eth-json-rpc-filters@^4.0.2, eth-json-rpc-filters@^4.2.1:
|
||||
eth-json-rpc-filters@4.2.2, eth-json-rpc-filters@^4.0.2, eth-json-rpc-filters@^4.2.1:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.2.2.tgz#eb35e1dfe9357ace8a8908e7daee80b2cd60a10d"
|
||||
integrity sha512-DGtqpLU7bBg63wPMWg1sCpkKCf57dJ+hj/k3zF26anXMzkmtSBDExL8IhUu7LUd34f0Zsce3PYNO2vV2GaTzaw==
|
||||
@@ -9222,6 +9222,13 @@ eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2:
|
||||
json-rpc-random-id "^1.0.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
eth-rpc-errors@4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.2.tgz#11bc164e25237a679061ac05b7da7537b673d3b7"
|
||||
integrity sha512-n+Re6Gu8XGyfFy1it0AwbD1x0MUzspQs0D5UiPs1fFPCr6WAwZM+vbIhXheBFrpgosqN9bs5PqlB4Q61U/QytQ==
|
||||
dependencies:
|
||||
fast-safe-stringify "^2.0.6"
|
||||
|
||||
eth-rpc-errors@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz#d7b22653c70dbf9defd4ef490fd08fe70608ca10"
|
||||
@@ -12503,6 +12510,14 @@ json-parse-even-better-errors@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
json-rpc-engine@6.1.0, json-rpc-engine@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393"
|
||||
integrity sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==
|
||||
dependencies:
|
||||
"@metamask/safe-event-emitter" "^2.0.0"
|
||||
eth-rpc-errors "^4.0.2"
|
||||
|
||||
json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9"
|
||||
@@ -12523,14 +12538,6 @@ json-rpc-engine@^5.3.0:
|
||||
eth-rpc-errors "^3.0.0"
|
||||
safe-event-emitter "^1.0.1"
|
||||
|
||||
json-rpc-engine@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393"
|
||||
integrity sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==
|
||||
dependencies:
|
||||
"@metamask/safe-event-emitter" "^2.0.0"
|
||||
eth-rpc-errors "^4.0.2"
|
||||
|
||||
json-rpc-error@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02"
|
||||
@@ -19214,14 +19221,19 @@ walker@^1.0.7, walker@~1.0.5:
|
||||
dependencies:
|
||||
makeerror "1.0.x"
|
||||
|
||||
walletlink@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/walletlink/-/walletlink-2.0.3.tgz#8905deed6ba9a07d5dd49d709db359df571b0cc4"
|
||||
integrity sha512-fl8LmelFpgVITdGxGkoGhCn9coIcV/8ubg2kT96DaqGi2N4BNvUjlmgOsXMuHvVUMg4kGVZeq2XKaChXBC9ySA==
|
||||
walletlink@^2.1.0:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/walletlink/-/walletlink-2.1.3.tgz#dd7ae5c5464ab3608c0faa5435ba736b945abcd7"
|
||||
integrity sha512-W8qgXiJn5BoecV8gneo7hMCGue7H5UsXjLfhaph6Z6BT7cC4+3ItWWGY5PoSbXRtR7LGe3h0kPZqCggiPrSQzQ==
|
||||
dependencies:
|
||||
"@metamask/safe-event-emitter" "2.0.0"
|
||||
bind-decorator "^1.0.11"
|
||||
bn.js "^5.1.1"
|
||||
clsx "^1.1.0"
|
||||
eth-block-tracker "4.4.3"
|
||||
eth-json-rpc-filters "4.2.2"
|
||||
eth-rpc-errors "4.0.2"
|
||||
json-rpc-engine "6.1.0"
|
||||
preact "^10.5.9"
|
||||
rxjs "^6.6.3"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user