Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46911593e5 | ||
|
|
1ac36c7b6b | ||
|
|
8e055df447 | ||
|
|
02ecd727eb | ||
|
|
adc8429bdc | ||
|
|
458d34d96c | ||
|
|
6a4fa0c9bf | ||
|
|
7fc9a655fc | ||
|
|
8d3babd015 | ||
|
|
75ed4c5dae | ||
|
|
58dfadb13c | ||
|
|
3d5f5f783c | ||
|
|
ecb7132843 | ||
|
|
980eb8a518 | ||
|
|
a11e89c0e1 | ||
|
|
3efe5268ae | ||
|
|
3f43a8fbaf | ||
|
|
cccf149568 | ||
|
|
604ea49567 | ||
|
|
4c0c6dfde6 | ||
|
|
a160bb8f02 | ||
|
|
e86946b104 | ||
|
|
03108b981e | ||
|
|
ae27e245b4 | ||
|
|
897f354202 | ||
|
|
4745052f0e | ||
|
|
5bc5d6504e | ||
|
|
7a0b85bf41 | ||
|
|
534afb3278 | ||
|
|
7d71af353e | ||
|
|
af6098bfe5 | ||
|
|
fce29bb36f | ||
|
|
4517af39ba | ||
|
|
b40163ce05 | ||
|
|
809902efec | ||
|
|
70be9894fa | ||
|
|
698ad5bac9 | ||
|
|
cd37b7533d | ||
|
|
c0cd6a1c8d | ||
|
|
f6245d1093 | ||
|
|
83c784f7c0 |
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"
|
||||
|
||||
17
.github/workflows/check-pr-title.yaml
vendored
Normal file
17
.github/workflows/check-pr-title.yaml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: "Check PR Title"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
check-pr-title:
|
||||
name: Check PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v3.4.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
16
.github/workflows/release.yaml
vendored
16
.github/workflows/release.yaml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
- name: Bump version and push tag
|
||||
id: github_tag_action
|
||||
uses: mathieudutour/github-tag-action@v4.5
|
||||
uses: mathieudutour/github-tag-action@331898d5052eedac9b15fec867b5ba66ebf9b692
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release_branches: .*
|
||||
@@ -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 }}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createWeb3ReactRoot, Web3ReactProvider } from '@web3-react/core'
|
||||
import React from 'react'
|
||||
import { Provider as StoreProvider } from 'react-redux'
|
||||
import { ThemeProvider as SCThemeProvider } from 'styled-components'
|
||||
import { NetworkContextName } from '../src/constants'
|
||||
import { NetworkContextName } from '../src/constants/misc'
|
||||
import store from '../src/state'
|
||||
import { FixedGlobalStyle, theme, ThemedGlobalStyle } from '../src/theme'
|
||||
import getLibrary from '../src/utils/getLibrary'
|
||||
|
||||
30
README.md
30
README.md
@@ -27,7 +27,7 @@ or visit [app.uniswap.org](https://app.uniswap.org).
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
yarn
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Run
|
||||
@@ -36,26 +36,22 @@ 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.**
|
||||
CI checks will run against all PRs.
|
||||
|
||||
## Accessing Uniswap Interface V1
|
||||
## Accessing Uniswap V2
|
||||
|
||||
The Uniswap Interface supports swapping against, and migrating or removing liquidity from Uniswap V1. However,
|
||||
if you would like to use Uniswap V1, the Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways
|
||||
The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for
|
||||
Uniswap protocol V2.
|
||||
|
||||
- Swap on Uniswap V2: https://app.uniswap.org/#/swap?use=v2
|
||||
- View V2 liquidity: https://app.uniswap.org/#/pool/v2
|
||||
- Add V2 liquidity: https://app.uniswap.org/#/add/v2
|
||||
- Migrate V2 liquidity to V3: https://app.uniswap.org/#/migrate/v2
|
||||
|
||||
## Accessing Uniswap V1
|
||||
|
||||
The Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways
|
||||
linked from the [v1.0.0 release](https://github.com/Uniswap/uniswap-interface/releases/tag/v1.0.0).
|
||||
|
||||
13
package.json
13
package.json
@@ -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.6",
|
||||
"@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",
|
||||
@@ -116,10 +116,13 @@
|
||||
"workbox-routing": "^6.1.0",
|
||||
"workbox-strategies": "^6.1.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@walletconnect/web3-provider": "1.4.2-rc.2"
|
||||
},
|
||||
"scripts": {
|
||||
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
|
||||
"compile-external-abi-types": "npx typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
|
||||
"compile-v3-contract-types": "npx typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
|
||||
"compile-external-abi-types": "typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
|
||||
"compile-v3-contract-types": "typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
|
||||
"build": "yarn compile-contract-types && react-scripts build",
|
||||
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
|
||||
"postinstall": "yarn compile-contract-types",
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_factoryV1",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_router",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountTokenMin",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountETHMin",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "migrate",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"stateMutability": "payable",
|
||||
"type": "receive"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +0,0 @@
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
|
||||
|
||||
const STAKING_REWARDS_INTERFACE = new Interface(STAKING_REWARDS_ABI)
|
||||
|
||||
export { STAKING_REWARDS_INTERFACE }
|
||||
@@ -2,10 +2,10 @@ import React from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import { CheckCircle, Triangle } from 'react-feather'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ExternalLink } from '../../theme'
|
||||
import { useAllTransactions } from '../../state/transactions/hooks'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { RowFixed } from '../Row'
|
||||
import Loader from '../Loader'
|
||||
|
||||
@@ -49,7 +49,11 @@ export default function Transaction({ hash }: { hash: string }) {
|
||||
|
||||
return (
|
||||
<TransactionWrapper>
|
||||
<TransactionState href={getEtherscanLink(chainId, hash, 'transaction')} pending={pending} success={success}>
|
||||
<TransactionState
|
||||
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
|
||||
pending={pending}
|
||||
success={success}
|
||||
>
|
||||
<RowFixed>
|
||||
<TransactionStatusText>{summary ?? hash} ↗</TransactionStatusText>
|
||||
</RowFixed>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import React, { useCallback, useContext } from 'react'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import styled, { ThemeContext } from 'styled-components'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { SUPPORTED_WALLETS } from '../../constants/wallet'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { AppDispatch } from '../../state'
|
||||
import { clearAllTransactions } from '../../state/transactions/actions'
|
||||
import { shortenAddress } from '../../utils'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { AutoRow } from '../Row'
|
||||
import Copy from './Copy'
|
||||
import Transaction from './Transaction'
|
||||
|
||||
import { SUPPORTED_WALLETS } from '../../constants'
|
||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { injected, walletconnect, walletlink, fortmatic, portis } from '../../connectors'
|
||||
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
|
||||
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
|
||||
@@ -354,7 +354,7 @@ export default function AccountDetails({
|
||||
<AddressLink
|
||||
hasENS={!!ENSName}
|
||||
isENS={true}
|
||||
href={chainId && getEtherscanLink(chainId, ENSName, 'address')}
|
||||
href={chainId && getExplorerLink(chainId, ENSName, ExplorerDataType.ADDRESS)}
|
||||
>
|
||||
<LinkIcon size={16} />
|
||||
<span style={{ marginLeft: '4px' }}>View on Etherscan</span>
|
||||
@@ -376,7 +376,7 @@ export default function AccountDetails({
|
||||
<AddressLink
|
||||
hasENS={!!ENSName}
|
||||
isENS={false}
|
||||
href={getEtherscanLink(chainId, account, 'address')}
|
||||
href={getExplorerLink(chainId, account, ExplorerDataType.ADDRESS)}
|
||||
>
|
||||
<LinkIcon size={16} />
|
||||
<span style={{ marginLeft: '4px' }}>View on Etherscan</span>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useContext, useCallback } from 'react'
|
||||
import styled, { ThemeContext } from 'styled-components'
|
||||
import useENS from '../../hooks/useENS'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ExternalLink, TYPE } from '../../theme'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { AutoColumn } from '../Column'
|
||||
import { RowBetween } from '../Row'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
|
||||
const InputPanel = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
@@ -102,7 +102,10 @@ export default function AddressInputPanel({
|
||||
Recipient
|
||||
</TYPE.black>
|
||||
{address && chainId && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, name ?? address, 'address')} style={{ fontSize: '14px' }}>
|
||||
<ExternalLink
|
||||
href={getExplorerLink(chainId, name ?? address, ExplorerDataType.ADDRESS)}
|
||||
style={{ fontSize: '14px' }}
|
||||
>
|
||||
(View on Etherscan)
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import React, { ReactNode, useMemo } from 'react'
|
||||
import { BLOCKED_ADDRESSES } from '../../constants'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
|
||||
// SDN OFAC addresses
|
||||
const BLOCKED_ADDRESSES: string[] = [
|
||||
'0x7F367cC41522cE07553e823bf3be79A889DEbe1B',
|
||||
'0xd882cFc20F52f2599D84b8e8D58C7FB62cfE344b',
|
||||
'0x901bb9583b24D97e995513C6778dc6888AB6870e',
|
||||
'0xA7e5d5A720f06526557c513402f2e6B5fA20b008',
|
||||
'0x8576aCC5C05D6Ce88f4e49bf65BdF0C62F91353C',
|
||||
]
|
||||
|
||||
export default function Blocklist({ children }: { children: ReactNode }) {
|
||||
const { account } = useActiveWeb3React()
|
||||
|
||||
@@ -12,7 +12,7 @@ import { RowBetween, RowFixed } from '../Row'
|
||||
import { TYPE } from '../../theme'
|
||||
import { Input as NumericalInput } from '../NumericalInput'
|
||||
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useTheme from '../../hooks/useTheme'
|
||||
import { Lock } from 'react-feather'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Story } from '@storybook/react/types-6-0'
|
||||
import React from 'react'
|
||||
import { DAI, WBTC } from '../../constants'
|
||||
import { DAI, WBTC } from '../../constants/tokens'
|
||||
import Component, { DoubleCurrencyLogoProps } from './index'
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import styled, { keyframes } from 'styled-components'
|
||||
import { TYPE, ExternalLink } from '../../theme'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
|
||||
import { useBlockNumber } from '../../state/application/hooks'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { ExternalLink, TYPE } from '../../theme'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
|
||||
const StyledPolling = styled.div`
|
||||
position: fixed;
|
||||
@@ -91,7 +91,9 @@ export default function Polling() {
|
||||
)
|
||||
|
||||
return (
|
||||
<ExternalLink href={chainId && blockNumber ? getEtherscanLink(chainId, blockNumber.toString(), 'block') : ''}>
|
||||
<ExternalLink
|
||||
href={chainId && blockNumber ? getExplorerLink(chainId, blockNumber.toString(), ExplorerDataType.BLOCK) : ''}
|
||||
>
|
||||
<StyledPolling onMouseEnter={() => setIsHover(true)} onMouseLeave={() => setIsHover(false)}>
|
||||
<StyledPollingNumber breathe={isMounting} hovering={isHover}>
|
||||
{blockNumber}
|
||||
|
||||
@@ -3,9 +3,9 @@ import React, { useMemo } from 'react'
|
||||
import { X } from 'react-feather'
|
||||
import styled from 'styled-components/macro'
|
||||
import tokenLogo from '../../assets/images/token-logo.png'
|
||||
import { UNI } from '../../constants'
|
||||
import { UNI } from '../../constants/tokens'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useMerkleDistributorContract } from '../../hooks/useContract'
|
||||
import useCurrentBlockTimestamp from '../../hooks/useCurrentBlockTimestamp'
|
||||
import { useTotalUniEarned } from '../../state/stake/hooks'
|
||||
|
||||
@@ -11,7 +11,7 @@ import styled from 'styled-components/macro'
|
||||
import Logo from '../../assets/svg/logo.svg'
|
||||
import LogoDark from '../../assets/svg/logo_white.svg'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useDarkModeManager } from '../../state/user/hooks'
|
||||
import { useETHBalances } from '../../state/wallet/hooks'
|
||||
import { CardNoise } from '../earn/styled'
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react'
|
||||
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import Jazzicon from 'jazzicon'
|
||||
|
||||
const StyledIdenticonContainer = styled.div`
|
||||
|
||||
@@ -3,7 +3,7 @@ import { BookOpen, Code, Info, MessageCircle, PieChart } from 'react-feather'
|
||||
import { Link } from 'react-router-dom'
|
||||
import styled, { css } from 'styled-components'
|
||||
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
||||
import { ApplicationModal } from '../../state/application/actions'
|
||||
import { useModalOpen, useToggleModal } from '../../state/application/hooks'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useContext } from 'react'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
|
||||
import { AutoColumn, ColumnCenter } from '../Column'
|
||||
import styled, { ThemeContext } from 'styled-components'
|
||||
@@ -8,7 +9,6 @@ import { TYPE, CloseIcon, CustomLightSpinner } from '../../theme'
|
||||
import { ArrowUpCircle } from 'react-feather'
|
||||
|
||||
import Circle from '../../assets/images/blue-loader.svg'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { ExternalLink } from '../../theme/components'
|
||||
|
||||
const ConfirmOrLoadingWrapper = styled.div`
|
||||
@@ -62,7 +62,10 @@ export function SubmittedView({
|
||||
<AutoColumn gap="100px" justify={'center'}>
|
||||
{children}
|
||||
{chainId && hash && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ marginLeft: '4px' }}>
|
||||
<ExternalLink
|
||||
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
|
||||
style={{ marginLeft: '4px' }}
|
||||
>
|
||||
<TYPE.subHeader>View transaction on Etherscan</TYPE.subHeader>
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { X } from 'react-feather'
|
||||
import styled, { keyframes } from 'styled-components'
|
||||
import tokenLogo from '../../assets/images/token-logo.png'
|
||||
import { ButtonPrimary } from '../../components/Button'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ApplicationModal } from '../../state/application/actions'
|
||||
import {
|
||||
useModalOpen,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useContext } from 'react'
|
||||
import { AlertCircle, CheckCircle } from 'react-feather'
|
||||
import styled, { ThemeContext } from 'styled-components'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { TYPE } from '../../theme'
|
||||
import { ExternalLink } from '../../theme/components'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { AutoColumn } from '../Column'
|
||||
import { AutoRow } from '../Row'
|
||||
|
||||
@@ -33,7 +33,9 @@ export default function TransactionPopup({
|
||||
<AutoColumn gap="8px">
|
||||
<TYPE.body fontWeight={500}>{summary ?? 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}</TYPE.body>
|
||||
{chainId && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')}>View on Etherscan</ExternalLink>
|
||||
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
|
||||
View on Etherscan
|
||||
</ExternalLink>
|
||||
)}
|
||||
</AutoColumn>
|
||||
</RowNoFlex>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Text } from 'rebass'
|
||||
import styled from 'styled-components/macro'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { unwrappedToken } from '../../utils/wrappedCurrency'
|
||||
@@ -24,7 +24,7 @@ import CurrencyLogo from '../CurrencyLogo'
|
||||
import DoubleCurrencyLogo from '../DoubleLogo'
|
||||
import { RowBetween, RowFixed, AutoRow } from '../Row'
|
||||
import { Dots } from '../swap/styleds'
|
||||
import { BIG_INT_ZERO } from '../../constants'
|
||||
import { BIG_INT_ZERO } from '../../constants/misc'
|
||||
import { FixedHeightRow } from '.'
|
||||
|
||||
const StyledPositionCard = styled(LightCard)<{ bgColor: any }>`
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Text } from 'rebass'
|
||||
import styled from 'styled-components/macro'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { ExternalLink, TYPE } from '../../theme'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
@@ -26,7 +26,7 @@ import CurrencyLogo from '../CurrencyLogo'
|
||||
import DoubleCurrencyLogo from '../DoubleLogo'
|
||||
import { RowBetween, RowFixed, AutoRow } from '../Row'
|
||||
import { Dots } from '../swap/styleds'
|
||||
import { BIG_INT_ZERO } from '../../constants'
|
||||
import { BIG_INT_ZERO } from '../../constants/misc'
|
||||
|
||||
export const FixedHeightRow = styled(RowBetween)`
|
||||
height: 24px;
|
||||
|
||||
@@ -12,10 +12,10 @@ import { WETH9, Price, Token, Percent } from '@uniswap/sdk-core'
|
||||
import { formatPrice } from 'utils/formatTokenAmount'
|
||||
import Loader from 'components/Loader'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import { DAI, USDC, USDT, WBTC } from '../../constants'
|
||||
import RangeBadge from 'components/Badge/RangeBadge'
|
||||
import { RowFixed } from 'components/Row'
|
||||
import HoverInlineText from 'components/HoverInlineText'
|
||||
import { DAI, USDC, USDT, WBTC } from '../../constants/tokens'
|
||||
|
||||
const Row = styled(Link)`
|
||||
align-items: center;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
import { Currency, Price, Token } from '@uniswap/sdk-core'
|
||||
import StepCounter from 'components/InputStepCounter/InputStepCounter'
|
||||
import { RowBetween } from 'components/Row'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
|
||||
// currencyA is the base token
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { ToggleElement, ToggleWrapper } from 'components/Toggle/MultiToggle'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
|
||||
// the order of displayed base currencies from left to right is always in sort order
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Text } from 'rebass'
|
||||
import { ChainId, Currency, currencyEquals, Token, ETHER } from '@uniswap/sdk-core'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { SUGGESTED_BASES } from '../../constants'
|
||||
import { SUGGESTED_BASES } from '../../constants/routing'
|
||||
import { AutoColumn } from '../Column'
|
||||
import QuestionHelper from '../QuestionHelper'
|
||||
import { AutoRow } from '../Row'
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 're
|
||||
import { FixedSizeList } from 'react-window'
|
||||
import { Text } from 'rebass'
|
||||
import styled from 'styled-components/macro'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCombinedActiveList } from '../../state/lists/hooks'
|
||||
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
|
||||
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
||||
|
||||
@@ -4,7 +4,7 @@ import ReactGA from 'react-ga'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FixedSizeList } from 'react-window'
|
||||
import { Text } from 'rebass'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useAllTokens, useToken, useIsUserAddedToken, useSearchInactiveTokenLists } from '../../hooks/Tokens'
|
||||
import { CloseIcon, TYPE, ButtonText, IconWrapper } from '../../theme'
|
||||
import { isAddress } from '../../utils'
|
||||
|
||||
@@ -13,10 +13,10 @@ import useTheme from 'hooks/useTheme'
|
||||
import { ButtonPrimary } from 'components/Button'
|
||||
import { SectionBreak } from 'components/swap/styleds'
|
||||
import { useAddUserToken } from 'state/user/hooks'
|
||||
import { getEtherscanLink } from 'utils'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { ExternalLink } from '../../theme/components'
|
||||
import ListLogo from 'components/ListLogo'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { PaddedColumn } from './styleds'
|
||||
|
||||
const Wrapper = styled.div`
|
||||
@@ -93,7 +93,7 @@ export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySel
|
||||
</TYPE.darkGray>
|
||||
</AutoColumn>
|
||||
{chainId && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
|
||||
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
|
||||
<AddressText fontSize={12}>{token.address}</AddressText>
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useRef, RefObject, useCallback, useState, useMemo } from 'react'
|
||||
import Column from 'components/Column'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { PaddedColumn, Separator, SearchInput } from './styleds'
|
||||
import Row, { RowBetween, RowFixed } from 'components/Row'
|
||||
import { TYPE, ExternalLinkIcon, TrashIcon, ButtonText, ExternalLink } from 'theme'
|
||||
@@ -8,8 +9,8 @@ import styled from 'styled-components/macro'
|
||||
import { useUserAddedTokens, useRemoveUserAddedToken } from 'state/user/hooks'
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
import { getEtherscanLink, isAddress } from 'utils'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { isAddress } from 'utils'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import Card from 'components/Card'
|
||||
import ImportRow from './ImportRow'
|
||||
import useTheme from '../../hooks/useTheme'
|
||||
@@ -20,7 +21,7 @@ const Wrapper = styled.div`
|
||||
width: 100%;
|
||||
height: calc(100% - 60px);
|
||||
position: relative;
|
||||
padding-bottom: 60px;
|
||||
padding-bottom: 80px;
|
||||
`
|
||||
|
||||
const Footer = styled.div`
|
||||
@@ -78,7 +79,7 @@ export default function ManageTokens({
|
||||
<RowBetween key={token.address} width="100%">
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={token} size={'20px'} />
|
||||
<ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
|
||||
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
|
||||
<TYPE.main ml={'10px'} fontWeight={600}>
|
||||
{token.symbol}
|
||||
</TYPE.main>
|
||||
@@ -86,7 +87,7 @@ export default function ManageTokens({
|
||||
</RowFixed>
|
||||
<RowFixed>
|
||||
<TrashIcon onClick={() => removeToken(chainId, token.address)} />
|
||||
<ExternalLinkIcon href={getEtherscanLink(chainId, token.address, 'address')} />
|
||||
<ExternalLinkIcon href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)} />
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
))
|
||||
@@ -95,7 +96,7 @@ export default function ManageTokens({
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Column style={{ width: '100%', flex: '1 1' }}>
|
||||
<Column style={{ width: '100%', height: '100%', flex: '1 1' }}>
|
||||
<PaddedColumn gap="14px">
|
||||
<Row>
|
||||
<SearchInput
|
||||
@@ -121,7 +122,7 @@ export default function ManageTokens({
|
||||
)}
|
||||
</PaddedColumn>
|
||||
<Separator />
|
||||
<PaddedColumn gap="lg">
|
||||
<PaddedColumn gap="lg" style={{ overflow: 'auto', marginBottom: '10px' }}>
|
||||
<RowBetween>
|
||||
<TYPE.main fontWeight={600}>
|
||||
{userAddedTokens?.length} Custom {userAddedTokens.length === 1 ? 'Token' : 'Tokens'}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import React, { useContext } from 'react'
|
||||
import styled, { ThemeContext } from 'styled-components'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
import Modal from '../Modal'
|
||||
import { ExternalLink } from '../../theme'
|
||||
import { Text } from 'rebass'
|
||||
@@ -11,8 +12,7 @@ import { ButtonPrimary, ButtonLight } from '../Button'
|
||||
import { AutoColumn, ColumnCenter } from '../Column'
|
||||
import Circle from '../../assets/images/blue-loader.svg'
|
||||
import MetaMaskLogo from '../../assets/images/metamask.png'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import useAddTokenToMetamask from 'hooks/useAddTokenToMetamask'
|
||||
|
||||
const Wrapper = styled.div`
|
||||
@@ -113,7 +113,7 @@ export function TransactionSubmittedContent({
|
||||
Transaction Submitted
|
||||
</Text>
|
||||
{chainId && hash && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')}>
|
||||
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
|
||||
<Text fontWeight={500} fontSize={14} color={theme.primary1}>
|
||||
View on Etherscan
|
||||
</Text>
|
||||
@@ -184,7 +184,12 @@ export function TransactionErrorContent({ message, onDismiss }: { message: strin
|
||||
</RowBetween>
|
||||
<AutoColumn style={{ marginTop: 20, padding: '2rem 0' }} gap="24px" justify="center">
|
||||
<AlertTriangle color={theme.red1} style={{ strokeWidth: 1.5 }} size={64} />
|
||||
<Text fontWeight={500} fontSize={16} color={theme.red1} style={{ textAlign: 'center', width: '85%' }}>
|
||||
<Text
|
||||
fontWeight={500}
|
||||
fontSize={16}
|
||||
color={theme.red1}
|
||||
style={{ textAlign: 'center', width: '85%', wordBreak: 'break-word' }}
|
||||
>
|
||||
{message}
|
||||
</Text>
|
||||
</AutoColumn>
|
||||
|
||||
@@ -6,7 +6,7 @@ import QuestionHelper from '../QuestionHelper'
|
||||
import { TYPE } from '../../theme'
|
||||
import { AutoColumn } from '../Column'
|
||||
import { RowBetween, RowFixed } from '../Row'
|
||||
import { DEFAULT_DEADLINE_FROM_NOW } from 'constants/index'
|
||||
import { DEFAULT_DEADLINE_FROM_NOW } from 'constants/misc'
|
||||
import { darken } from 'polished'
|
||||
import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks'
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { AbstractConnector } from '@web3-react/abstract-connector'
|
||||
import React from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import { SUPPORTED_WALLETS } from '../../constants/wallet'
|
||||
import Option from './Option'
|
||||
import { SUPPORTED_WALLETS } from '../../constants'
|
||||
import { injected } from '../../connectors'
|
||||
import { darken } from 'polished'
|
||||
import Loader from '../Loader'
|
||||
|
||||
@@ -10,7 +10,7 @@ import MetamaskIcon from '../../assets/images/metamask.png'
|
||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||
import { fortmatic, injected, portis } from '../../connectors'
|
||||
import { OVERLAY_READY } from '../../connectors/Fortmatic'
|
||||
import { SUPPORTED_WALLETS } from '../../constants'
|
||||
import { SUPPORTED_WALLETS } from '../../constants/wallet'
|
||||
import usePrevious from '../../hooks/usePrevious'
|
||||
import { ApplicationModal } from '../../state/application/actions'
|
||||
import { useModalOpen, useWalletModalToggle } from '../../state/application/hooks'
|
||||
|
||||
@@ -4,8 +4,8 @@ import styled from 'styled-components/macro'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { network } from '../../connectors'
|
||||
import { useEagerConnect, useInactiveListener } from '../../hooks'
|
||||
import { NetworkContextName } from '../../constants'
|
||||
import { useEagerConnect, useInactiveListener } from '../../hooks/web3'
|
||||
import { NetworkContextName } from '../../constants/misc'
|
||||
import Loader from '../Loader'
|
||||
|
||||
const MessageWrapper = styled.div`
|
||||
|
||||
@@ -10,7 +10,7 @@ import FortmaticIcon from '../../assets/images/fortmaticIcon.png'
|
||||
import PortisIcon from '../../assets/images/portisIcon.png'
|
||||
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
|
||||
import { fortmatic, injected, portis, walletconnect, walletlink } from '../../connectors'
|
||||
import { NetworkContextName } from '../../constants'
|
||||
import { NetworkContextName } from '../../constants/misc'
|
||||
import useENSName from '../../hooks/useENSName'
|
||||
import { useHasSocks } from '../../hooks/useSocksBalance'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import Modal from '../Modal'
|
||||
import { AutoColumn, ColumnCenter } from '../Column'
|
||||
import styled from 'styled-components/macro'
|
||||
@@ -12,13 +13,13 @@ import Circle from '../../assets/images/blue-loader.svg'
|
||||
import { Text } from 'rebass'
|
||||
import AddressInputPanel from '../AddressInputPanel'
|
||||
import useENS from '../../hooks/useENS'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
import Confetti from '../Confetti'
|
||||
import { CardNoise, CardBGImage, CardBGImageSmaller } from '../earn/styled'
|
||||
import { useIsTransactionPending } from '../../state/transactions/hooks'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { getEtherscanLink, shortenAddress } from '../../utils'
|
||||
import { shortenAddress } from '../../utils'
|
||||
|
||||
const ContentWrapper = styled(AutoColumn)`
|
||||
width: 100%;
|
||||
@@ -181,7 +182,7 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
|
||||
<TYPE.subHeader color="black">Confirm this transaction in your wallet</TYPE.subHeader>
|
||||
)}
|
||||
{attempting && hash && !claimConfirmed && chainId && hash && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ zIndex: 99 }}>
|
||||
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)} style={{ zIndex: 99 }}>
|
||||
View transaction on Etherscan
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -6,13 +6,13 @@ import { Text } from 'rebass'
|
||||
import styled from 'styled-components/macro'
|
||||
import Circle from '../../assets/images/blue-loader.svg'
|
||||
import tokenLogo from '../../assets/images/token-logo.png'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ApplicationModal } from '../../state/application/actions'
|
||||
import { useModalOpen, useToggleSelfClaimModal } from '../../state/application/hooks'
|
||||
import { useClaimCallback, useUserClaimData, useUserUnclaimedAmount } from '../../state/claim/hooks'
|
||||
import { useUserHasSubmittedClaim } from '../../state/transactions/hooks'
|
||||
import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE, UniTokenAnimated } from '../../theme'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { ButtonPrimary } from '../Button'
|
||||
import { AutoColumn, ColumnCenter } from '../Column'
|
||||
import Confetti from '../Confetti'
|
||||
@@ -196,7 +196,10 @@ export default function ClaimModal() {
|
||||
<TYPE.subHeader color="black">Confirm this transaction in your wallet</TYPE.subHeader>
|
||||
)}
|
||||
{attempting && claimSubmitted && !claimConfirmed && chainId && claimTxn?.hash && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, claimTxn?.hash, 'transaction')} style={{ zIndex: 99 }}>
|
||||
<ExternalLink
|
||||
href={getExplorerLink(chainId, claimTxn?.hash, ExplorerDataType.TRANSACTION)}
|
||||
style={{ zIndex: 99 }}
|
||||
>
|
||||
View transaction on Etherscan
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useStakingContract } from '../../hooks/useContract'
|
||||
import { SubmittedView, LoadingView } from '../ModalViews'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
|
||||
const ContentWrapper = styled(AutoColumn)`
|
||||
width: 100%;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { unwrappedToken } from '../../utils/wrappedCurrency'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
import { useV2Pair } from '../../hooks/useV2Pairs'
|
||||
import useUSDCPrice from '../../hooks/useUSDCPrice'
|
||||
import { BIG_INT_SECONDS_IN_WEEK } from '../../constants'
|
||||
import { BIG_INT_SECONDS_IN_WEEK } from '../../constants/misc'
|
||||
|
||||
const StatContainer = styled.div`
|
||||
display: flex;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import { V2_ROUTER_ADDRESS } from '../../constants'
|
||||
import { V2_ROUTER_ADDRESS } from '../../constants/addresses'
|
||||
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import Modal from '../Modal'
|
||||
@@ -12,7 +12,7 @@ import ProgressCircles from '../ProgressSteps'
|
||||
import CurrencyInputPanel from '../CurrencyInputPanel'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { usePairContract, useStakingContract } from '../../hooks/useContract'
|
||||
import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallback'
|
||||
@@ -83,7 +83,10 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
||||
|
||||
// approval data for stake
|
||||
const deadline = useTransactionDeadline()
|
||||
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(parsedAmountWrapped, V2_ROUTER_ADDRESS)
|
||||
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(
|
||||
parsedAmountWrapped,
|
||||
chainId && V2_ROUTER_ADDRESS[chainId]
|
||||
)
|
||||
const [approval, approveCallback] = useApproveCallback(parsedAmount, stakingInfo.stakingRewardAddress)
|
||||
|
||||
const stakingContract = useStakingContract(stakingInfo.stakingRewardAddress)
|
||||
|
||||
@@ -11,7 +11,7 @@ import { SubmittedView, LoadingView } from '../ModalViews'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import FormattedCurrencyAmount from '../FormattedCurrencyAmount'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
|
||||
const ContentWrapper = styled(AutoColumn)`
|
||||
width: 100%;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -7,11 +7,11 @@ import Card, { OutlineCard } from 'components/Card'
|
||||
import { RowBetween, AutoRow } from 'components/Row'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { getEtherscanLink } from 'utils'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { Currency, Token } from '@uniswap/sdk-core'
|
||||
import { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
import { useUnsupportedTokens } from '../../hooks/Tokens'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
|
||||
const DetailsFooter = styled.div<{ show: boolean }>`
|
||||
padding-top: calc(16px + 2rem);
|
||||
@@ -78,7 +78,7 @@ export default function UnsupportedCurrencyFooter({
|
||||
<TYPE.body fontWeight={500}>{token.symbol}</TYPE.body>
|
||||
</AutoRow>
|
||||
{chainId && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
|
||||
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
|
||||
<AddressText>{token.address}</AddressText>
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '../../constants'
|
||||
import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '../../constants/misc'
|
||||
|
||||
/**
|
||||
* Given the price impact, get user confirmation.
|
||||
|
||||
@@ -171,7 +171,7 @@ export function SwapCallbackError({ error }: { error: string }) {
|
||||
<SwapCallbackErrorInnerAlertTriangle>
|
||||
<AlertTriangle size={24} />
|
||||
</SwapCallbackErrorInnerAlertTriangle>
|
||||
<p>{error}</p>
|
||||
<p style={{ wordBreak: 'break-word' }}>{error}</p>
|
||||
</SwapCallbackErrorInner>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react'
|
||||
import { UNI } from '../../constants/tokens'
|
||||
|
||||
import Modal from '../Modal'
|
||||
import { AutoColumn } from '../Column'
|
||||
@@ -7,13 +8,12 @@ import { RowBetween } from '../Row'
|
||||
import { TYPE } from '../../theme'
|
||||
import { X } from 'react-feather'
|
||||
import { ButtonPrimary } from '../Button'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import AddressInputPanel from '../AddressInputPanel'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
import useENS from '../../hooks/useENS'
|
||||
import { useDelegateCallback } from '../../state/governance/hooks'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { UNI } from '../../constants'
|
||||
import { LoadingView, SubmittedView } from '../ModalViews'
|
||||
import { formatTokenAmount } from 'utils/formatTokenAmount'
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useContext } from 'react'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
|
||||
import Modal from '../Modal'
|
||||
import { AutoColumn, ColumnCenter } from '../Column'
|
||||
@@ -10,7 +11,6 @@ import { X, ArrowUpCircle } from 'react-feather'
|
||||
import { ButtonPrimary } from '../Button'
|
||||
import Circle from '../../assets/images/blue-loader.svg'
|
||||
import { useVoteCallback, useUserVotes } from '../../state/governance/hooks'
|
||||
import { getEtherscanLink } from '../../utils'
|
||||
import { ExternalLink } from '../../theme/components'
|
||||
import { formatTokenAmount } from 'utils/formatTokenAmount'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
@@ -133,7 +133,10 @@ export default function VoteModal({ isOpen, onDismiss, proposalId, support }: Vo
|
||||
<TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
|
||||
</AutoColumn>
|
||||
{chainId && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ marginLeft: '4px' }}>
|
||||
<ExternalLink
|
||||
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
|
||||
style={{ marginLeft: '4px' }}
|
||||
>
|
||||
<TYPE.subHeader>View transaction on Etherscan</TYPE.subHeader>
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -1,40 +1,53 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { Web3Provider } from '@ethersproject/providers'
|
||||
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,
|
||||
})
|
||||
|
||||
32
src/constants/addresses.ts
Normal file
32
src/constants/addresses.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { FACTORY_ADDRESS as V3_FACTORY_ADDRESS } from '@uniswap/v3-sdk'
|
||||
import { constructSameAddressMap } from '../utils/constructSameAddressMap'
|
||||
|
||||
export const UNI_ADDRESS = constructSameAddressMap('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984')
|
||||
export const MULTICALL2_ADDRESSES = constructSameAddressMap('0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696')
|
||||
export const V2_ROUTER_ADDRESS = constructSameAddressMap('0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D')
|
||||
export const GOVERNANCE_ADDRESS = constructSameAddressMap('0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F')
|
||||
export const TIMELOCK_ADDRESS = constructSameAddressMap('0x1a9C8182C09F50C8318d769245beA52c32BE35BC')
|
||||
export const MERKLE_DISTRIBUTOR_ADDRESS: { [chainId in ChainId]?: string } = {
|
||||
[ChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e',
|
||||
}
|
||||
export const ARGENT_WALLET_DETECTOR_ADDRESS: { [chainId in ChainId]?: string } = {
|
||||
[ChainId.MAINNET]: '0xeca4B0bDBf7c55E9b7925919d03CbF8Dc82537E8',
|
||||
}
|
||||
export const V3_CORE_FACTORY_ADDRESSES = constructSameAddressMap(V3_FACTORY_ADDRESS)
|
||||
export const QUOTER_ADDRESSES = constructSameAddressMap('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')
|
||||
export const TICK_LENS_ADDRESSES = constructSameAddressMap('0xbfd8137f7d1516D3ea5cA83523914859ec47F573')
|
||||
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = constructSameAddressMap(
|
||||
'0xC36442b4a4522E871399CD717aBDD847Ab11FE88'
|
||||
)
|
||||
export const ENS_REGISTRAR_ADDRESSES = {
|
||||
[ChainId.MAINNET]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
[ChainId.GÖRLI]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
[ChainId.RINKEBY]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
[ChainId.ROPSTEN]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
}
|
||||
export const SOCKS_CONTROLLER_ADDRESSES = {
|
||||
[ChainId.MAINNET]: '0x65770b5283117639760beA3F867b69b3697a91dd',
|
||||
}
|
||||
export const SWAP_ROUTER_ADDRESSES = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564')
|
||||
export const V3_MIGRATOR_ADDRESSES = constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34')
|
||||
37
src/constants/governance.ts
Normal file
37
src/constants/governance.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { GOVERNANCE_ADDRESS, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses'
|
||||
|
||||
export const COMMON_CONTRACT_NAMES: { [chainId in ChainId]?: { [address: string]: string } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
[UNI_ADDRESS[ChainId.MAINNET]]: 'UNI',
|
||||
[GOVERNANCE_ADDRESS[ChainId.MAINNET]]: 'Governance',
|
||||
[TIMELOCK_ADDRESS[ChainId.MAINNET]]: 'Timelock',
|
||||
},
|
||||
[ChainId.RINKEBY]: {
|
||||
[UNI_ADDRESS[ChainId.RINKEBY]]: 'Rinkeby UNI',
|
||||
[GOVERNANCE_ADDRESS[ChainId.RINKEBY]]: 'Rinkeby Governance',
|
||||
[TIMELOCK_ADDRESS[ChainId.RINKEBY]]: 'Rinkeby Timelock',
|
||||
},
|
||||
[ChainId.ROPSTEN]: {
|
||||
[UNI_ADDRESS[ChainId.ROPSTEN]]: 'Ropsten UNI',
|
||||
[GOVERNANCE_ADDRESS[ChainId.ROPSTEN]]: 'Ropsten Governance',
|
||||
[TIMELOCK_ADDRESS[ChainId.ROPSTEN]]: 'Ropsten Timelock',
|
||||
},
|
||||
[ChainId.KOVAN]: {
|
||||
[UNI_ADDRESS[ChainId.KOVAN]]: 'Kovan UNI',
|
||||
[GOVERNANCE_ADDRESS[ChainId.KOVAN]]: 'Kovan Governance',
|
||||
[TIMELOCK_ADDRESS[ChainId.KOVAN]]: 'Kovan Timelock',
|
||||
},
|
||||
[ChainId.GÖRLI]: {
|
||||
[UNI_ADDRESS[ChainId.GÖRLI]]: 'Goerli UNI',
|
||||
[GOVERNANCE_ADDRESS[ChainId.GÖRLI]]: 'Goerli Governance',
|
||||
[TIMELOCK_ADDRESS[ChainId.GÖRLI]]: 'Goerli Timelock',
|
||||
},
|
||||
}
|
||||
|
||||
export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13
|
||||
|
||||
// Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time
|
||||
export const AVERAGE_BLOCK_TIME_IN_SECS: { [chainId in ChainId]?: number } = {
|
||||
[ChainId.MAINNET]: DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS,
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
import { ChainId, Percent, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import { AbstractConnector } from '@web3-react/abstract-connector'
|
||||
import JSBI from 'jsbi'
|
||||
import { fortmatic, injected, portis, walletconnect, walletlink } from '../connectors'
|
||||
|
||||
import INJECTED_ICON_URL from '../assets/images/arrow-right.svg'
|
||||
import METAMASK_ICON_URL from '../assets/images/metamask.png'
|
||||
import WALLETCONNECT_ICON_URL from '../assets/images/walletConnectIcon.svg'
|
||||
import COINBASE_ICON_URL from '../assets/images/coinbaseWalletIcon.svg'
|
||||
import FORTMATIC_ICON_URL from '../assets/images/fortmaticIcon.png'
|
||||
import PORTIS_ICON_URL from '../assets/images/portisIcon.png'
|
||||
|
||||
export const MULTICALL2_ADDRESSES: { [chainId in ChainId]: string } = {
|
||||
[ChainId.MAINNET]: '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696',
|
||||
[ChainId.ROPSTEN]: '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696',
|
||||
[ChainId.KOVAN]: '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696',
|
||||
[ChainId.RINKEBY]: '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696',
|
||||
[ChainId.GÖRLI]: '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696',
|
||||
}
|
||||
|
||||
export const V2_ROUTER_ADDRESS = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'
|
||||
|
||||
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
|
||||
export { PRELOADED_PROPOSALS } from './proposals'
|
||||
|
||||
// a list of tokens by chain
|
||||
type ChainTokenList = {
|
||||
readonly [chainId in ChainId]: Token[]
|
||||
}
|
||||
|
||||
export const AMPL = new Token(ChainId.MAINNET, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
||||
export const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
||||
export const USDC = new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C')
|
||||
export const USDT = new Token(ChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD')
|
||||
export const WBTC = new Token(ChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC')
|
||||
export const FEI = new Token(ChainId.MAINNET, '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', 18, 'FEI', 'Fei USD')
|
||||
export const TRIBE = new Token(ChainId.MAINNET, '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', 18, 'TRIBE', 'Tribe')
|
||||
export const FRAX = new Token(ChainId.MAINNET, '0x853d955aCEf822Db058eb8505911ED77F175b99e', 18, 'FRAX', 'Frax')
|
||||
export const FXS = new Token(ChainId.MAINNET, '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', 18, 'FXS', 'Frax Share')
|
||||
export const renBTC = new Token(ChainId.MAINNET, '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', 8, 'renBTC', 'renBTC')
|
||||
export const UMA = new Token(
|
||||
ChainId.MAINNET,
|
||||
'0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828',
|
||||
18,
|
||||
'UMA',
|
||||
'UMA Voting Token v1'
|
||||
)
|
||||
|
||||
// Mirror Protocol compat.
|
||||
export const UST = new Token(ChainId.MAINNET, '0xa47c8bf37f92abed4a126bda807a7b7498661acd', 18, 'UST', 'Wrapped UST')
|
||||
export const MIR = new Token(ChainId.MAINNET, '0x09a3ecafa817268f77be1283176b946c4ff2e608', 18, 'MIR', 'Wrapped MIR')
|
||||
// List of all mirror's assets addresses.
|
||||
// Last pulled from : https://whitelist.mirror.finance/eth/tokenlists.json
|
||||
// TODO: Generate this programaticaly ?
|
||||
const mAssetsAdditionalBases: { [tokenAddress: string]: Token[] } = {
|
||||
[UST.address]: [MIR],
|
||||
[MIR.address]: [UST],
|
||||
'0xd36932143F6eBDEDD872D5Fb0651f4B72Fd15a84': [MIR, UST], // mAAPL
|
||||
'0x59A921Db27Dd6d4d974745B7FfC5c33932653442': [MIR, UST], // mGOOGL
|
||||
'0x21cA39943E91d704678F5D00b6616650F066fD63': [MIR, UST], // mTSLA
|
||||
'0xC8d674114bac90148d11D3C1d33C61835a0F9DCD': [MIR, UST], // mNFLX
|
||||
'0x13B02c8dE71680e71F0820c996E4bE43c2F57d15': [MIR, UST], // mQQQ
|
||||
'0xEdb0414627E6f1e3F082DE65cD4F9C693D78CCA9': [MIR, UST], // mTWTR
|
||||
'0x41BbEDd7286dAab5910a1f15d12CBda839852BD7': [MIR, UST], // mMSFT
|
||||
'0x0cae9e4d663793c2a2A0b211c1Cf4bBca2B9cAa7': [MIR, UST], // mAMZN
|
||||
'0x56aA298a19C93c6801FDde870fA63EF75Cc0aF72': [MIR, UST], // mBABA
|
||||
'0x1d350417d9787E000cc1b95d70E9536DcD91F373': [MIR, UST], // mIAU
|
||||
'0x9d1555d8cB3C846Bb4f7D5B1B1080872c3166676': [MIR, UST], // mSLV
|
||||
'0x31c63146a635EB7465e5853020b39713AC356991': [MIR, UST], // mUSO
|
||||
'0xf72FCd9DCF0190923Fadd44811E240Ef4533fc86': [MIR, UST], // mVIXY
|
||||
}
|
||||
|
||||
// Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time
|
||||
export const AVERAGE_BLOCK_TIME_IN_SECS = 13
|
||||
export const PROPOSAL_LENGTH_IN_BLOCKS = 40_320
|
||||
export const PROPOSAL_LENGTH_IN_SECS = AVERAGE_BLOCK_TIME_IN_SECS * PROPOSAL_LENGTH_IN_BLOCKS
|
||||
|
||||
export const GOVERNANCE_ADDRESS = '0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F'
|
||||
|
||||
export const TIMELOCK_ADDRESS = '0x1a9C8182C09F50C8318d769245beA52c32BE35BC'
|
||||
|
||||
const UNI_ADDRESS = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984'
|
||||
export const UNI: { [chainId in ChainId]: Token } = {
|
||||
[ChainId.MAINNET]: new Token(ChainId.MAINNET, UNI_ADDRESS, 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.RINKEBY]: new Token(ChainId.RINKEBY, UNI_ADDRESS, 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.ROPSTEN]: new Token(ChainId.ROPSTEN, UNI_ADDRESS, 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.GÖRLI]: new Token(ChainId.GÖRLI, UNI_ADDRESS, 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.KOVAN]: new Token(ChainId.KOVAN, UNI_ADDRESS, 18, 'UNI', 'Uniswap'),
|
||||
}
|
||||
|
||||
export const COMMON_CONTRACT_NAMES: { [address: string]: string } = {
|
||||
[UNI_ADDRESS]: 'UNI',
|
||||
[GOVERNANCE_ADDRESS]: 'Governance',
|
||||
[TIMELOCK_ADDRESS]: 'Timelock',
|
||||
}
|
||||
|
||||
export const MERKLE_DISTRIBUTOR_ADDRESS: { [chainId in ChainId]?: string } = {
|
||||
[ChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e',
|
||||
}
|
||||
|
||||
const WETH_ONLY: ChainTokenList = {
|
||||
[ChainId.MAINNET]: [WETH9[ChainId.MAINNET]],
|
||||
[ChainId.ROPSTEN]: [WETH9[ChainId.ROPSTEN]],
|
||||
[ChainId.RINKEBY]: [WETH9[ChainId.RINKEBY]],
|
||||
[ChainId.GÖRLI]: [WETH9[ChainId.GÖRLI]],
|
||||
[ChainId.KOVAN]: [WETH9[ChainId.KOVAN]],
|
||||
}
|
||||
|
||||
// used to construct intermediary pairs for trading
|
||||
export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
|
||||
...WETH_ONLY,
|
||||
[ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
|
||||
export const ADDITIONAL_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: Token[] } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
...mAssetsAdditionalBases,
|
||||
'0xA948E86885e12Fb09AfEF8C52142EBDbDf73cD18': [UNI[ChainId.MAINNET]],
|
||||
'0x561a4717537ff4AF5c687328c0f7E90a319705C0': [UNI[ChainId.MAINNET]],
|
||||
'0xa6e3454fec677772dd771788a079355e43910638': [UMA],
|
||||
[FEI.address]: [TRIBE],
|
||||
[TRIBE.address]: [FEI],
|
||||
[FRAX.address]: [FXS],
|
||||
[FXS.address]: [FRAX],
|
||||
[WBTC.address]: [renBTC],
|
||||
[renBTC.address]: [WBTC],
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Some tokens can only be swapped via certain pairs, so we override the list of bases that are considered for these
|
||||
* tokens.
|
||||
*/
|
||||
export const CUSTOM_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: Token[] } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
[AMPL.address]: [DAI, WETH9[ChainId.MAINNET]],
|
||||
},
|
||||
}
|
||||
|
||||
// used for display in the default list when adding liquidity
|
||||
export const SUGGESTED_BASES: Partial<ChainTokenList> = {
|
||||
[ChainId.MAINNET]: [DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
|
||||
// used to construct the list of all pairs we consider by default in the frontend
|
||||
export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
|
||||
...WETH_ONLY,
|
||||
[ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
|
||||
export const PINNED_PAIRS: { readonly [chainId in ChainId]?: [Token, Token][] } = {
|
||||
[ChainId.MAINNET]: [
|
||||
[
|
||||
new Token(ChainId.MAINNET, '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', 8, 'cDAI', 'Compound Dai'),
|
||||
new Token(ChainId.MAINNET, '0x39AA39c021dfbaE8faC545936693aC917d5E7563', 8, 'cUSDC', 'Compound USD Coin'),
|
||||
],
|
||||
[USDC, USDT],
|
||||
[DAI, USDT],
|
||||
],
|
||||
}
|
||||
|
||||
export interface WalletInfo {
|
||||
connector?: AbstractConnector
|
||||
name: string
|
||||
iconURL: string
|
||||
description: string
|
||||
href: string | null
|
||||
color: string
|
||||
primary?: true
|
||||
mobile?: true
|
||||
mobileOnly?: true
|
||||
}
|
||||
|
||||
export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
|
||||
INJECTED: {
|
||||
connector: injected,
|
||||
name: 'Injected',
|
||||
iconURL: INJECTED_ICON_URL,
|
||||
description: 'Injected web3 provider.',
|
||||
href: null,
|
||||
color: '#010101',
|
||||
primary: true,
|
||||
},
|
||||
METAMASK: {
|
||||
connector: injected,
|
||||
name: 'MetaMask',
|
||||
iconURL: METAMASK_ICON_URL,
|
||||
description: 'Easy-to-use browser extension.',
|
||||
href: null,
|
||||
color: '#E8831D',
|
||||
},
|
||||
WALLET_CONNECT: {
|
||||
connector: walletconnect,
|
||||
name: 'WalletConnect',
|
||||
iconURL: WALLETCONNECT_ICON_URL,
|
||||
description: 'Connect to Trust Wallet, Rainbow Wallet and more...',
|
||||
href: null,
|
||||
color: '#4196FC',
|
||||
mobile: true,
|
||||
},
|
||||
WALLET_LINK: {
|
||||
connector: walletlink,
|
||||
name: 'Coinbase Wallet',
|
||||
iconURL: COINBASE_ICON_URL,
|
||||
description: 'Use Coinbase Wallet app on mobile device',
|
||||
href: null,
|
||||
color: '#315CF5',
|
||||
},
|
||||
COINBASE_LINK: {
|
||||
name: 'Open in Coinbase Wallet',
|
||||
iconURL: COINBASE_ICON_URL,
|
||||
description: 'Open in Coinbase Wallet app.',
|
||||
href: 'https://go.cb-w.com/mtUDhEZPy1',
|
||||
color: '#315CF5',
|
||||
mobile: true,
|
||||
mobileOnly: true,
|
||||
},
|
||||
FORTMATIC: {
|
||||
connector: fortmatic,
|
||||
name: 'Fortmatic',
|
||||
iconURL: FORTMATIC_ICON_URL,
|
||||
description: 'Login using Fortmatic hosted wallet',
|
||||
href: null,
|
||||
color: '#6748FF',
|
||||
mobile: true,
|
||||
},
|
||||
Portis: {
|
||||
connector: portis,
|
||||
name: 'Portis',
|
||||
iconURL: PORTIS_ICON_URL,
|
||||
description: 'Login using Portis hosted wallet',
|
||||
href: null,
|
||||
color: '#4A6C9B',
|
||||
mobile: true,
|
||||
},
|
||||
}
|
||||
|
||||
export const NetworkContextName = 'NETWORK'
|
||||
|
||||
// 30 minutes, denominated in seconds
|
||||
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 30
|
||||
|
||||
// used for rewards deadlines
|
||||
export const BIG_INT_SECONDS_IN_WEEK = JSBI.BigInt(60 * 60 * 24 * 7)
|
||||
|
||||
export const BIG_INT_ZERO = JSBI.BigInt(0)
|
||||
|
||||
// one basis JSBI.BigInt
|
||||
export const ONE_BIPS = new Percent(JSBI.BigInt(1), JSBI.BigInt(10))
|
||||
export const BIPS_BASE = JSBI.BigInt(10000)
|
||||
// used for warning states
|
||||
export const ALLOWED_PRICE_IMPACT_LOW: Percent = new Percent(JSBI.BigInt(100), BIPS_BASE) // 1%
|
||||
export const ALLOWED_PRICE_IMPACT_MEDIUM: Percent = new Percent(JSBI.BigInt(300), BIPS_BASE) // 3%
|
||||
export const ALLOWED_PRICE_IMPACT_HIGH: Percent = new Percent(JSBI.BigInt(500), BIPS_BASE) // 5%
|
||||
// if the price slippage exceeds this number, force the user to type 'confirm' to execute
|
||||
export const PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN: Percent = new Percent(JSBI.BigInt(1000), BIPS_BASE) // 10%
|
||||
// for non expert mode disable swaps above this
|
||||
export const BLOCKED_PRICE_IMPACT_NON_EXPERT: Percent = new Percent(JSBI.BigInt(1500), BIPS_BASE) // 15%
|
||||
|
||||
// used to ensure the user doesn't send so much ETH so they end up with <.01
|
||||
export const MIN_ETH: JSBI = JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(16)) // .01 ETH
|
||||
export const BETTER_TRADE_LESS_HOPS_THRESHOLD = new Percent(JSBI.BigInt(50), JSBI.BigInt(10000))
|
||||
|
||||
export const ZERO_PERCENT = new Percent('0')
|
||||
export const ONE_HUNDRED_PERCENT = new Percent('1')
|
||||
|
||||
// SDN OFAC addresses
|
||||
export const BLOCKED_ADDRESSES: string[] = [
|
||||
'0x7F367cC41522cE07553e823bf3be79A889DEbe1B',
|
||||
'0xd882cFc20F52f2599D84b8e8D58C7FB62cfE344b',
|
||||
'0x901bb9583b24D97e995513C6778dc6888AB6870e',
|
||||
'0xA7e5d5A720f06526557c513402f2e6B5fA20b008',
|
||||
'0x8576aCC5C05D6Ce88f4e49bf65BdF0C62F91353C',
|
||||
]
|
||||
|
||||
export const ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS = '0xeca4B0bDBf7c55E9b7925919d03CbF8Dc82537E8'
|
||||
|
||||
export const V1_MIGRATOR_ADDRESS = '0x16D4F26C15f3658ec65B1126ff27DD3dF2a2996b'
|
||||
33
src/constants/misc.ts
Normal file
33
src/constants/misc.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
|
||||
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
|
||||
export const NetworkContextName = 'NETWORK'
|
||||
|
||||
// 30 minutes, denominated in seconds
|
||||
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 30
|
||||
|
||||
// used for rewards deadlines
|
||||
export const BIG_INT_SECONDS_IN_WEEK = JSBI.BigInt(60 * 60 * 24 * 7)
|
||||
|
||||
export const BIG_INT_ZERO = JSBI.BigInt(0)
|
||||
|
||||
// one basis JSBI.BigInt
|
||||
export const ONE_BIPS = new Percent(JSBI.BigInt(1), JSBI.BigInt(10000))
|
||||
export const BIPS_BASE = JSBI.BigInt(10000)
|
||||
// used for warning states
|
||||
export const ALLOWED_PRICE_IMPACT_LOW: Percent = new Percent(JSBI.BigInt(100), BIPS_BASE) // 1%
|
||||
export const ALLOWED_PRICE_IMPACT_MEDIUM: Percent = new Percent(JSBI.BigInt(300), BIPS_BASE) // 3%
|
||||
export const ALLOWED_PRICE_IMPACT_HIGH: Percent = new Percent(JSBI.BigInt(500), BIPS_BASE) // 5%
|
||||
// if the price slippage exceeds this number, force the user to type 'confirm' to execute
|
||||
export const PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN: Percent = new Percent(JSBI.BigInt(1000), BIPS_BASE) // 10%
|
||||
// for non expert mode disable swaps above this
|
||||
export const BLOCKED_PRICE_IMPACT_NON_EXPERT: Percent = new Percent(JSBI.BigInt(1500), BIPS_BASE) // 15%
|
||||
|
||||
// used to ensure the user doesn't send so much ETH so they end up with <.01
|
||||
export const MIN_ETH: JSBI = JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(16)) // .01 ETH
|
||||
export const BETTER_TRADE_LESS_HOPS_THRESHOLD = new Percent(JSBI.BigInt(50), JSBI.BigInt(10000))
|
||||
|
||||
export const ZERO_PERCENT = new Percent('0')
|
||||
export const ONE_HUNDRED_PERCENT = new Percent('1')
|
||||
@@ -1,4 +1,6 @@
|
||||
import { UNISWAP_GRANTS } from './uniswap_grants'
|
||||
import { UNISWAP_GRANTS_PROPOSAL_DESCRIPTION } from './uniswap_grants_proposal_description'
|
||||
|
||||
// Proposals are 0-indexed
|
||||
export const PRELOADED_PROPOSALS = new Map([[2, UNISWAP_GRANTS]])
|
||||
export const PROPOSAL_DESCRIPTION_TEXT: { [proposalId: number]: string } = {
|
||||
[2]: UNISWAP_GRANTS_PROPOSAL_DESCRIPTION,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const UNISWAP_GRANTS = `# Uniswap Grants Program v0.1
|
||||
export const UNISWAP_GRANTS_PROPOSAL_DESCRIPTION = `# Uniswap Grants Program v0.1
|
||||
|
||||
*co-authored with [Ken Ng](https://twitter.com/nkennethk?lang=en)*
|
||||
|
||||
81
src/constants/routing.ts
Normal file
81
src/constants/routing.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
// a list of tokens by chain
|
||||
import { ChainId, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import { AMPL, DAI, FEI, FRAX, FXS, MIR, renBTC, TRIBE, UMA, UNI, USDC, USDT, UST, WBTC } from './tokens'
|
||||
|
||||
type ChainTokenList = {
|
||||
readonly [chainId in ChainId]: Token[]
|
||||
}
|
||||
// List of all mirror's assets addresses.
|
||||
// Last pulled from : https://whitelist.mirror.finance/eth/tokenlists.json
|
||||
// TODO: Generate this programmatically ?
|
||||
const mAssetsAdditionalBases: { [tokenAddress: string]: Token[] } = {
|
||||
[UST.address]: [MIR],
|
||||
[MIR.address]: [UST],
|
||||
'0xd36932143F6eBDEDD872D5Fb0651f4B72Fd15a84': [MIR, UST], // mAAPL
|
||||
'0x59A921Db27Dd6d4d974745B7FfC5c33932653442': [MIR, UST], // mGOOGL
|
||||
'0x21cA39943E91d704678F5D00b6616650F066fD63': [MIR, UST], // mTSLA
|
||||
'0xC8d674114bac90148d11D3C1d33C61835a0F9DCD': [MIR, UST], // mNFLX
|
||||
'0x13B02c8dE71680e71F0820c996E4bE43c2F57d15': [MIR, UST], // mQQQ
|
||||
'0xEdb0414627E6f1e3F082DE65cD4F9C693D78CCA9': [MIR, UST], // mTWTR
|
||||
'0x41BbEDd7286dAab5910a1f15d12CBda839852BD7': [MIR, UST], // mMSFT
|
||||
'0x0cae9e4d663793c2a2A0b211c1Cf4bBca2B9cAa7': [MIR, UST], // mAMZN
|
||||
'0x56aA298a19C93c6801FDde870fA63EF75Cc0aF72': [MIR, UST], // mBABA
|
||||
'0x1d350417d9787E000cc1b95d70E9536DcD91F373': [MIR, UST], // mIAU
|
||||
'0x9d1555d8cB3C846Bb4f7D5B1B1080872c3166676': [MIR, UST], // mSLV
|
||||
'0x31c63146a635EB7465e5853020b39713AC356991': [MIR, UST], // mUSO
|
||||
'0xf72FCd9DCF0190923Fadd44811E240Ef4533fc86': [MIR, UST], // mVIXY
|
||||
}
|
||||
const WETH_ONLY: ChainTokenList = {
|
||||
[ChainId.MAINNET]: [WETH9[ChainId.MAINNET]],
|
||||
[ChainId.ROPSTEN]: [WETH9[ChainId.ROPSTEN]],
|
||||
[ChainId.RINKEBY]: [WETH9[ChainId.RINKEBY]],
|
||||
[ChainId.GÖRLI]: [WETH9[ChainId.GÖRLI]],
|
||||
[ChainId.KOVAN]: [WETH9[ChainId.KOVAN]],
|
||||
}
|
||||
// used to construct intermediary pairs for trading
|
||||
export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
|
||||
...WETH_ONLY,
|
||||
[ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
export const ADDITIONAL_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: Token[] } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
...mAssetsAdditionalBases,
|
||||
'0xA948E86885e12Fb09AfEF8C52142EBDbDf73cD18': [UNI[ChainId.MAINNET]],
|
||||
'0x561a4717537ff4AF5c687328c0f7E90a319705C0': [UNI[ChainId.MAINNET]],
|
||||
'0xa6e3454fec677772dd771788a079355e43910638': [UMA],
|
||||
[FEI.address]: [TRIBE],
|
||||
[TRIBE.address]: [FEI],
|
||||
[FRAX.address]: [FXS],
|
||||
[FXS.address]: [FRAX],
|
||||
[WBTC.address]: [renBTC],
|
||||
[renBTC.address]: [WBTC],
|
||||
},
|
||||
}
|
||||
/**
|
||||
* Some tokens can only be swapped via certain pairs, so we override the list of bases that are considered for these
|
||||
* tokens.
|
||||
*/
|
||||
export const CUSTOM_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: Token[] } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
[AMPL.address]: [DAI, WETH9[ChainId.MAINNET]],
|
||||
},
|
||||
}
|
||||
// used for display in the default list when adding liquidity
|
||||
export const SUGGESTED_BASES: Partial<ChainTokenList> = {
|
||||
[ChainId.MAINNET]: [DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
// used to construct the list of all pairs we consider by default in the frontend
|
||||
export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
|
||||
...WETH_ONLY,
|
||||
[ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
export const PINNED_PAIRS: { readonly [chainId in ChainId]?: [Token, Token][] } = {
|
||||
[ChainId.MAINNET]: [
|
||||
[
|
||||
new Token(ChainId.MAINNET, '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', 8, 'cDAI', 'Compound Dai'),
|
||||
new Token(ChainId.MAINNET, '0x39AA39c021dfbaE8faC545936693aC917d5E7563', 8, 'cUSDC', 'Compound USD Coin'),
|
||||
],
|
||||
[USDC, USDT],
|
||||
[DAI, USDT],
|
||||
],
|
||||
}
|
||||
30
src/constants/tokens.ts
Normal file
30
src/constants/tokens.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ChainId, Token } from '@uniswap/sdk-core'
|
||||
import { UNI_ADDRESS } from './addresses'
|
||||
|
||||
export const AMPL = new Token(ChainId.MAINNET, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
||||
export const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
||||
export const USDC = new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C')
|
||||
export const USDT = new Token(ChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD')
|
||||
export const WBTC = new Token(ChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC')
|
||||
export const FEI = new Token(ChainId.MAINNET, '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', 18, 'FEI', 'Fei USD')
|
||||
export const TRIBE = new Token(ChainId.MAINNET, '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', 18, 'TRIBE', 'Tribe')
|
||||
export const FRAX = new Token(ChainId.MAINNET, '0x853d955aCEf822Db058eb8505911ED77F175b99e', 18, 'FRAX', 'Frax')
|
||||
export const FXS = new Token(ChainId.MAINNET, '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', 18, 'FXS', 'Frax Share')
|
||||
export const renBTC = new Token(ChainId.MAINNET, '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', 8, 'renBTC', 'renBTC')
|
||||
export const UMA = new Token(
|
||||
ChainId.MAINNET,
|
||||
'0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828',
|
||||
18,
|
||||
'UMA',
|
||||
'UMA Voting Token v1'
|
||||
)
|
||||
// Mirror Protocol compat.
|
||||
export const UST = new Token(ChainId.MAINNET, '0xa47c8bf37f92abed4a126bda807a7b7498661acd', 18, 'UST', 'Wrapped UST')
|
||||
export const MIR = new Token(ChainId.MAINNET, '0x09a3ecafa817268f77be1283176b946c4ff2e608', 18, 'MIR', 'Wrapped MIR')
|
||||
export const UNI: { [chainId in ChainId]: Token } = {
|
||||
[ChainId.MAINNET]: new Token(ChainId.MAINNET, UNI_ADDRESS[ChainId.MAINNET], 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.RINKEBY]: new Token(ChainId.RINKEBY, UNI_ADDRESS[ChainId.RINKEBY], 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.ROPSTEN]: new Token(ChainId.ROPSTEN, UNI_ADDRESS[ChainId.ROPSTEN], 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.GÖRLI]: new Token(ChainId.GÖRLI, UNI_ADDRESS[ChainId.GÖRLI], 18, 'UNI', 'Uniswap'),
|
||||
[ChainId.KOVAN]: new Token(ChainId.KOVAN, UNI_ADDRESS[ChainId.KOVAN], 18, 'UNI', 'Uniswap'),
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { FACTORY_ADDRESS } from '@uniswap/v3-sdk'
|
||||
|
||||
function constructSameAddressMap(address: string): { [chainId in ChainId]: string } {
|
||||
return {
|
||||
[ChainId.MAINNET]: address,
|
||||
[ChainId.ROPSTEN]: address,
|
||||
[ChainId.KOVAN]: address,
|
||||
[ChainId.RINKEBY]: address,
|
||||
[ChainId.GÖRLI]: address,
|
||||
}
|
||||
}
|
||||
|
||||
export const V3_CORE_FACTORY_ADDRESSES = constructSameAddressMap(FACTORY_ADDRESS)
|
||||
|
||||
export const QUOTER_ADDRESSES = constructSameAddressMap('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')
|
||||
|
||||
export const TICK_LENS_ADDRESSES = constructSameAddressMap('0xbfd8137f7d1516D3ea5cA83523914859ec47F573')
|
||||
|
||||
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = constructSameAddressMap(
|
||||
'0xC36442b4a4522E871399CD717aBDD847Ab11FE88'
|
||||
)
|
||||
|
||||
export const SWAP_ROUTER_ADDRESSES = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564')
|
||||
|
||||
export const V3_MIGRATOR_ADDRESSES = constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34')
|
||||
84
src/constants/wallet.ts
Normal file
84
src/constants/wallet.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { AbstractConnector } from '@web3-react/abstract-connector'
|
||||
import INJECTED_ICON_URL from '../assets/images/arrow-right.svg'
|
||||
import COINBASE_ICON_URL from '../assets/images/coinbaseWalletIcon.svg'
|
||||
import FORTMATIC_ICON_URL from '../assets/images/fortmaticIcon.png'
|
||||
import METAMASK_ICON_URL from '../assets/images/metamask.png'
|
||||
import PORTIS_ICON_URL from '../assets/images/portisIcon.png'
|
||||
import WALLETCONNECT_ICON_URL from '../assets/images/walletConnectIcon.svg'
|
||||
import { fortmatic, injected, portis, walletconnect, walletlink } from '../connectors'
|
||||
|
||||
export interface WalletInfo {
|
||||
connector?: AbstractConnector
|
||||
name: string
|
||||
iconURL: string
|
||||
description: string
|
||||
href: string | null
|
||||
color: string
|
||||
primary?: true
|
||||
mobile?: true
|
||||
mobileOnly?: true
|
||||
}
|
||||
|
||||
export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
|
||||
INJECTED: {
|
||||
connector: injected,
|
||||
name: 'Injected',
|
||||
iconURL: INJECTED_ICON_URL,
|
||||
description: 'Injected web3 provider.',
|
||||
href: null,
|
||||
color: '#010101',
|
||||
primary: true,
|
||||
},
|
||||
METAMASK: {
|
||||
connector: injected,
|
||||
name: 'MetaMask',
|
||||
iconURL: METAMASK_ICON_URL,
|
||||
description: 'Easy-to-use browser extension.',
|
||||
href: null,
|
||||
color: '#E8831D',
|
||||
},
|
||||
WALLET_CONNECT: {
|
||||
connector: walletconnect,
|
||||
name: 'WalletConnect',
|
||||
iconURL: WALLETCONNECT_ICON_URL,
|
||||
description: 'Connect to Trust Wallet, Rainbow Wallet and more...',
|
||||
href: null,
|
||||
color: '#4196FC',
|
||||
mobile: true,
|
||||
},
|
||||
WALLET_LINK: {
|
||||
connector: walletlink,
|
||||
name: 'Coinbase Wallet',
|
||||
iconURL: COINBASE_ICON_URL,
|
||||
description: 'Use Coinbase Wallet app on mobile device',
|
||||
href: null,
|
||||
color: '#315CF5',
|
||||
},
|
||||
COINBASE_LINK: {
|
||||
name: 'Open in Coinbase Wallet',
|
||||
iconURL: COINBASE_ICON_URL,
|
||||
description: 'Open in Coinbase Wallet app.',
|
||||
href: 'https://go.cb-w.com/mtUDhEZPy1',
|
||||
color: '#315CF5',
|
||||
mobile: true,
|
||||
mobileOnly: true,
|
||||
},
|
||||
FORTMATIC: {
|
||||
connector: fortmatic,
|
||||
name: 'Fortmatic',
|
||||
iconURL: FORTMATIC_ICON_URL,
|
||||
description: 'Login using Fortmatic hosted wallet',
|
||||
href: null,
|
||||
color: '#6748FF',
|
||||
mobile: true,
|
||||
},
|
||||
Portis: {
|
||||
connector: portis,
|
||||
name: 'Portis',
|
||||
iconURL: PORTIS_ICON_URL,
|
||||
description: 'Login using Portis hosted wallet',
|
||||
href: null,
|
||||
color: '#4A6C9B',
|
||||
mobile: true,
|
||||
},
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { useUserAddedTokens } from '../state/user/hooks'
|
||||
import { isAddress } from '../utils'
|
||||
import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks'
|
||||
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useBytes32TokenContract, useTokenContract } from './useContract'
|
||||
|
||||
// reduce token map into standard address <-> Token mapping, optionally include user added tokens
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getTokenLogoURL } from './../components/CurrencyLogo/index'
|
||||
import { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
import { Currency, Token } from '@uniswap/sdk-core'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
|
||||
export default function useAddTokenToMetamask(
|
||||
currencyToAdd: Currency | undefined
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Currency, Token } from '@uniswap/sdk-core'
|
||||
import flatMap from 'lodash.flatmap'
|
||||
import { useMemo } from 'react'
|
||||
import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants'
|
||||
import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants/routing'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
|
||||
export function useAllCurrencyCombinations(currencyA?: Currency, currencyB?: Currency): [Token, Token][] {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Pool, Route } from '@uniswap/v3-sdk'
|
||||
import { useMemo } from 'react'
|
||||
import { useUserSingleHopOnly } from '../state/user/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useV3SwapPools } from './useV3SwapPools'
|
||||
|
||||
function computeAllRoutes(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import { FeeAmount, TICK_SPACINGS } from '@uniswap/v3-sdk'
|
||||
import { nearestUsableTick, TickMath } from '@uniswap/v3-sdk/dist/'
|
||||
import { ZERO_ADDRESS } from '../constants'
|
||||
import { ZERO_ADDRESS } from '../constants/misc'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Result, useSingleCallResult, useSingleContractMultipleData } from 'state/multicall/hooks'
|
||||
import { useTickLens, useV3Factory } from './useContract'
|
||||
|
||||
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 }))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -4,12 +4,11 @@ import { CurrencyAmount, ChainId, Percent, Currency, TradeType } from '@uniswap/
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { V2_ROUTER_ADDRESS } from '../constants'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/v3'
|
||||
import { SWAP_ROUTER_ADDRESSES, V2_ROUTER_ADDRESS } from '../constants/addresses'
|
||||
import { useTransactionAdder, useHasPendingApproval } from '../state/transactions/hooks'
|
||||
import { calculateGasMargin } from '../utils'
|
||||
import { calculateGasMargin } from '../utils/calculateGasMargin'
|
||||
import { useTokenContract } from './useContract'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useTokenAllowance } from './useTokenAllowance'
|
||||
|
||||
export enum ApprovalState {
|
||||
@@ -104,13 +103,19 @@ export function useApproveCallbackFromTrade(
|
||||
allowedSlippage: Percent
|
||||
) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
|
||||
const v3SwapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
|
||||
const amountToApprove = useMemo(
|
||||
() => (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
|
||||
[trade, allowedSlippage]
|
||||
)
|
||||
return useApproveCallback(
|
||||
amountToApprove,
|
||||
trade instanceof V2Trade ? V2_ROUTER_ADDRESS : trade instanceof V3Trade ? swapRouterAddress : undefined
|
||||
chainId
|
||||
? trade instanceof V2Trade
|
||||
? V2_ROUTER_ADDRESS[chainId]
|
||||
: trade instanceof V3Trade
|
||||
? v3SwapRouterAddress
|
||||
: undefined
|
||||
: undefined
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import ENS_PUBLIC_RESOLVER_ABI from 'abis/ens-public-resolver.json'
|
||||
import ENS_ABI from 'abis/ens-registrar.json'
|
||||
import ERC20_ABI from 'abis/erc20.json'
|
||||
import ERC20_BYTES32_ABI from 'abis/erc20_bytes32.json'
|
||||
import MIGRATOR_ABI from 'abis/migrator.json'
|
||||
import MULTICALL_ABI from 'abis/multicall2.json'
|
||||
import { Unisocks } from 'abis/types/Unisocks'
|
||||
import UNISOCKS_ABI from 'abis/unisocks.json'
|
||||
@@ -25,91 +24,75 @@ import WETH_ABI from 'abis/weth.json'
|
||||
import EIP_2612 from 'abis/eip_2612.json'
|
||||
|
||||
import {
|
||||
ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS,
|
||||
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
|
||||
QUOTER_ADDRESSES,
|
||||
TICK_LENS_ADDRESSES,
|
||||
V3_CORE_FACTORY_ADDRESSES,
|
||||
V3_MIGRATOR_ADDRESSES,
|
||||
ARGENT_WALLET_DETECTOR_ADDRESS,
|
||||
GOVERNANCE_ADDRESS,
|
||||
MERKLE_DISTRIBUTOR_ADDRESS,
|
||||
V1_MIGRATOR_ADDRESS,
|
||||
UNI,
|
||||
MULTICALL2_ADDRESSES,
|
||||
V2_ROUTER_ADDRESS,
|
||||
} from 'constants/index'
|
||||
ENS_REGISTRAR_ADDRESSES,
|
||||
SOCKS_CONTROLLER_ADDRESSES,
|
||||
} from 'constants/addresses'
|
||||
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
|
||||
import {
|
||||
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
|
||||
V3_CORE_FACTORY_ADDRESSES,
|
||||
TICK_LENS_ADDRESSES,
|
||||
V3_MIGRATOR_ADDRESSES,
|
||||
QUOTER_ADDRESSES,
|
||||
} from 'constants/v3'
|
||||
import { useMemo } from 'react'
|
||||
import { Quoter, TickLens, UniswapV3Factory, UniswapV3Pool } from 'types/v3'
|
||||
import { NonfungiblePositionManager } from 'types/v3/NonfungiblePositionManager'
|
||||
import { V3Migrator } from 'types/v3/V3Migrator'
|
||||
import { getContract } from 'utils'
|
||||
import { Multicall2 } from '../abis/types'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { ArgentWalletDetector, EnsPublicResolver, EnsRegistrar, Erc20, Multicall2, Weth } from '../abis/types'
|
||||
import { UNI } from '../constants/tokens'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
|
||||
// returns null on errors
|
||||
export function useContract(address: string | undefined, ABI: any, withSignerIfPossible = true): Contract | null {
|
||||
const { library, account } = useActiveWeb3React()
|
||||
export function useContract<T extends Contract = Contract>(
|
||||
addressOrAddressMap: string | { [chainId in ChainId]?: string } | undefined,
|
||||
ABI: any,
|
||||
withSignerIfPossible = true
|
||||
): T | null {
|
||||
const { library, account, chainId } = useActiveWeb3React()
|
||||
|
||||
return useMemo(() => {
|
||||
if (!address || !ABI || !library) return null
|
||||
if (!addressOrAddressMap || !ABI || !library || !chainId) return null
|
||||
let address: string | undefined
|
||||
if (typeof addressOrAddressMap === 'string') address = addressOrAddressMap
|
||||
else address = addressOrAddressMap[chainId]
|
||||
if (!address) return null
|
||||
try {
|
||||
return getContract(address, ABI, library, withSignerIfPossible && account ? account : undefined)
|
||||
} catch (error) {
|
||||
console.error('Failed to get contract', error)
|
||||
return null
|
||||
}
|
||||
}, [address, ABI, library, withSignerIfPossible, account])
|
||||
}, [addressOrAddressMap, ABI, library, chainId, withSignerIfPossible, account]) as T
|
||||
}
|
||||
|
||||
export function useV1MigratorContract(): Contract | null {
|
||||
return useContract(V1_MIGRATOR_ADDRESS, MIGRATOR_ABI, true)
|
||||
export function useV2MigratorContract() {
|
||||
return useContract<V3Migrator>(V3_MIGRATOR_ADDRESSES, V2MigratorABI, true)
|
||||
}
|
||||
|
||||
export function useV2MigratorContract(): V3Migrator | null {
|
||||
export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean) {
|
||||
return useContract<Erc20>(tokenAddress, ERC20_ABI, withSignerIfPossible)
|
||||
}
|
||||
|
||||
export function useWETHContract(withSignerIfPossible?: boolean) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(chainId && V3_MIGRATOR_ADDRESSES[chainId], V2MigratorABI, true) as V3Migrator | null
|
||||
return useContract<Weth>(chainId ? WETH9[chainId]?.address : undefined, WETH_ABI, withSignerIfPossible)
|
||||
}
|
||||
|
||||
export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null {
|
||||
return useContract(tokenAddress, ERC20_ABI, withSignerIfPossible)
|
||||
export function useArgentWalletDetectorContract() {
|
||||
return useContract<ArgentWalletDetector>(ARGENT_WALLET_DETECTOR_ADDRESS, ARGENT_WALLET_DETECTOR_ABI, false)
|
||||
}
|
||||
|
||||
export function useWETHContract(withSignerIfPossible?: boolean): Contract | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const address = chainId && chainId in WETH9 ? WETH9[chainId].address : undefined
|
||||
return useContract(address, WETH_ABI, withSignerIfPossible)
|
||||
export function useENSRegistrarContract(withSignerIfPossible?: boolean) {
|
||||
return useContract<EnsRegistrar>(ENS_REGISTRAR_ADDRESSES, ENS_ABI, withSignerIfPossible)
|
||||
}
|
||||
|
||||
export function useArgentWalletDetectorContract(): Contract | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(
|
||||
chainId === ChainId.MAINNET ? ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS : undefined,
|
||||
ARGENT_WALLET_DETECTOR_ABI,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
export function useENSRegistrarContract(withSignerIfPossible?: boolean): Contract | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
let address: string | undefined
|
||||
if (chainId) {
|
||||
switch (chainId) {
|
||||
case ChainId.MAINNET:
|
||||
case ChainId.GÖRLI:
|
||||
case ChainId.ROPSTEN:
|
||||
case ChainId.RINKEBY:
|
||||
address = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'
|
||||
break
|
||||
}
|
||||
}
|
||||
return useContract(address, ENS_ABI, withSignerIfPossible)
|
||||
}
|
||||
|
||||
export function useENSResolverContract(address: string | undefined, withSignerIfPossible?: boolean): Contract | null {
|
||||
return useContract(address, ENS_PUBLIC_RESOLVER_ABI, withSignerIfPossible)
|
||||
export function useENSResolverContract(address: string | undefined, withSignerIfPossible?: boolean) {
|
||||
return useContract<EnsPublicResolver>(address, ENS_PUBLIC_RESOLVER_ABI, withSignerIfPossible)
|
||||
}
|
||||
|
||||
export function useBytes32TokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null {
|
||||
@@ -128,61 +111,51 @@ export function useV2RouterContract(): Contract | null {
|
||||
return useContract(V2_ROUTER_ADDRESS, IUniswapV2Router02ABI, true)
|
||||
}
|
||||
|
||||
export function useMulticall2Contract(): Multicall2 | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(chainId && MULTICALL2_ADDRESSES[chainId], MULTICALL_ABI, false) as Multicall2
|
||||
export function useMulticall2Contract() {
|
||||
return useContract<Multicall2>(MULTICALL2_ADDRESSES, MULTICALL_ABI, false) as Multicall2
|
||||
}
|
||||
|
||||
export function useMerkleDistributorContract(): Contract | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(chainId ? MERKLE_DISTRIBUTOR_ADDRESS[chainId] : undefined, MERKLE_DISTRIBUTOR_ABI, true)
|
||||
export function useMerkleDistributorContract() {
|
||||
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
|
||||
}
|
||||
|
||||
export function useGovernanceContract(): Contract | null {
|
||||
export function useGovernanceContract() {
|
||||
return useContract(GOVERNANCE_ADDRESS, GOVERNANCE_ABI, true)
|
||||
}
|
||||
|
||||
export function useUniContract(): Contract | null {
|
||||
export function useUniContract() {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(chainId ? UNI[chainId].address : undefined, UNI_ABI, true)
|
||||
return useContract(chainId ? UNI[chainId]?.address : undefined, UNI_ABI, true)
|
||||
}
|
||||
|
||||
export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean): Contract | null {
|
||||
export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
|
||||
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
|
||||
}
|
||||
|
||||
export function useSocksController(): Unisocks | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(
|
||||
chainId === ChainId.MAINNET ? '0x65770b5283117639760beA3F867b69b3697a91dd' : undefined,
|
||||
UNISOCKS_ABI,
|
||||
false
|
||||
) as Unisocks | null
|
||||
return useContract<Unisocks>(SOCKS_CONTROLLER_ADDRESSES, UNISOCKS_ABI, false)
|
||||
}
|
||||
|
||||
export function useV3NFTPositionManagerContract(withSignerIfPossible?: boolean): NonfungiblePositionManager | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const address = chainId ? NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId] : undefined
|
||||
return useContract(address, NFTPositionManagerABI, withSignerIfPossible) as NonfungiblePositionManager | null
|
||||
return useContract<NonfungiblePositionManager>(
|
||||
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
|
||||
NFTPositionManagerABI,
|
||||
withSignerIfPossible
|
||||
)
|
||||
}
|
||||
|
||||
export function useV3Factory(): UniswapV3Factory | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const address = chainId ? V3_CORE_FACTORY_ADDRESSES[chainId] : undefined
|
||||
return useContract(address, V3FactoryABI) as UniswapV3Factory | null
|
||||
export function useV3Factory() {
|
||||
return useContract<UniswapV3Factory>(V3_CORE_FACTORY_ADDRESSES, V3FactoryABI) as UniswapV3Factory | null
|
||||
}
|
||||
|
||||
export function useV3Pool(address: string | undefined): UniswapV3Pool | null {
|
||||
return useContract(address, V3PoolABI) as UniswapV3Pool | null
|
||||
export function useV3Pool(address: string | undefined) {
|
||||
return useContract<UniswapV3Pool>(address, V3PoolABI)
|
||||
}
|
||||
|
||||
export function useV3Quoter(): Quoter | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
return useContract(chainId ? QUOTER_ADDRESSES[chainId] : undefined, QuoterABI) as Quoter | null
|
||||
export function useV3Quoter() {
|
||||
return useContract<Quoter>(QUOTER_ADDRESSES, QuoterABI)
|
||||
}
|
||||
|
||||
export function useTickLens(): TickLens | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const address = chainId ? TICK_LENS_ADDRESSES[chainId] : undefined
|
||||
return useContract(address, TickLensABI) as TickLens | null
|
||||
return useContract<TickLens>(TICK_LENS_ADDRESSES, TickLensABI)
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { splitSignature } from 'ethers/lib/utils'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { UNI, USDC, DAI } from '../constants'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/v3'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/addresses'
|
||||
import { DAI, UNI, USDC } from '../constants/tokens'
|
||||
import { useSingleCallResult } from '../state/multicall/hooks'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useEIP2612Contract } from './useContract'
|
||||
import useIsArgentWallet from './useIsArgentWallet'
|
||||
import useTransactionDeadline from './useTransactionDeadline'
|
||||
|
||||
@@ -3,25 +3,24 @@ 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'
|
||||
import resolveENSContentHash from '../utils/resolveENSContentHash'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
|
||||
export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean) => Promise<TokenList> {
|
||||
const { chainId, library } = useActiveWeb3React()
|
||||
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')
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useArgentWalletDetectorContract } from './useContract'
|
||||
|
||||
export default function useIsArgentWallet(): boolean {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { computePoolAddress } from '@uniswap/v3-sdk'
|
||||
import { V3_CORE_FACTORY_ADDRESSES } from '../constants/addresses'
|
||||
import { IUniswapV3PoolStateInterface } from '../types/v3/IUniswapV3PoolState'
|
||||
import { Token, Currency } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useMultipleContractSingleData } from '../state/multicall/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { Pool, FeeAmount } from '@uniswap/v3-sdk'
|
||||
import { V3_CORE_FACTORY_ADDRESSES } from 'constants/v3'
|
||||
import { abi as IUniswapV3PoolStateABI } from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import JSBI from 'jsbi'
|
||||
import { useMemo } from 'react'
|
||||
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useSocksController } from './useContract'
|
||||
|
||||
export default function useSocksBalance(): JSBI | undefined {
|
||||
|
||||
@@ -3,12 +3,13 @@ import { Router, Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { ChainId, Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/v3'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/addresses'
|
||||
import { calculateGasMargin } from '../utils/calculateGasMargin'
|
||||
import { getTradeVersion } from '../utils/getTradeVersion'
|
||||
import { useTransactionAdder } from '../state/transactions/hooks'
|
||||
import { calculateGasMargin, isAddress, shortenAddress } from '../utils'
|
||||
import { isAddress, shortenAddress } from '../utils'
|
||||
import isZero from '../utils/isZero'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useV2RouterContract } from './useContract'
|
||||
import { SignatureData } from './useERC20Permit'
|
||||
import useTransactionDeadline from './useTransactionDeadline'
|
||||
@@ -153,16 +154,26 @@ 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.'
|
||||
if (reason?.indexOf('undefined is not an object') !== -1) {
|
||||
console.error(error, reason)
|
||||
return 'An error occurred when trying to execute this swap. You may need to increase your slippage tolerance. If that does not work, there may be an incompatibility with the token you are trading. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.'
|
||||
}
|
||||
return `Unknown error${
|
||||
reason ? `: "${reason}"` : ''
|
||||
}. Try increasing your slippage tolerance. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,8 +282,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 +313,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])
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { useActiveWeb3React } from '.'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
export function useTimestampFromBlock(block: number | undefined): number | undefined {
|
||||
const { library } = useActiveWeb3React()
|
||||
const [timestamp, setTimestamp] = useState<number>()
|
||||
useEffect(() => {
|
||||
async function fetchTimestamp() {
|
||||
if (block) {
|
||||
const blockData = await library?.getBlock(block)
|
||||
blockData && setTimestamp(blockData.timestamp)
|
||||
}
|
||||
}
|
||||
if (!timestamp) {
|
||||
fetchTimestamp()
|
||||
}
|
||||
}, [block, library, timestamp])
|
||||
return timestamp
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
import { ChainId, Currency, CurrencyAmount, currencyEquals, Price, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { ChainId, Currency, CurrencyAmount, Price, Token } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { USDC } from '../constants'
|
||||
import { PairState, useV2Pairs } from './useV2Pairs'
|
||||
import { useActiveWeb3React } from '../hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { USDC } from '../constants/tokens'
|
||||
import { useV2TradeExactOut } from './useV2Trade'
|
||||
import { useBestV3TradeExactOut, V3TradeState } from './useBestV3Trade'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
|
||||
// USDC amount used when calculating spot price for a given currency.
|
||||
// The amount is large enough to filter low liquidity pairs.
|
||||
const usdcCurrencyAmount = CurrencyAmount.fromRawAmount(USDC, 10_000e6)
|
||||
|
||||
/**
|
||||
* Returns the price in USDC of the input currency
|
||||
@@ -12,23 +15,15 @@ import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
*/
|
||||
export default function useUSDCPrice(currency?: Currency): Price<Currency, Token> | undefined {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const wrapped = wrappedCurrency(currency, chainId)
|
||||
const weth = WETH9[chainId as ChainId]
|
||||
|
||||
const tokenPairs: [Currency | undefined, Currency | undefined][] = useMemo(
|
||||
() => [
|
||||
[chainId && wrapped && currencyEquals(weth, wrapped) ? undefined : currency, chainId ? weth : undefined],
|
||||
[wrapped?.equals(USDC) ? undefined : wrapped, chainId === ChainId.MAINNET ? USDC : undefined],
|
||||
[chainId ? weth : undefined, chainId === ChainId.MAINNET ? USDC : undefined],
|
||||
],
|
||||
[chainId, currency, weth, wrapped]
|
||||
)
|
||||
const [[ethPairState, ethPair], [usdcPairState, usdcPair], [usdcEthPairState, usdcEthPair]] = useV2Pairs(tokenPairs)
|
||||
const v2USDCTrade = useV2TradeExactOut(currency, chainId === ChainId.MAINNET ? usdcCurrencyAmount : undefined)
|
||||
const v3USDCTrade = useBestV3TradeExactOut(currency, chainId === ChainId.MAINNET ? usdcCurrencyAmount : undefined)
|
||||
|
||||
return useMemo(() => {
|
||||
if (!currency || !wrapped || !chainId) {
|
||||
if (!currency || !chainId) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
// return some fake price data for non-mainnet
|
||||
if (chainId !== ChainId.MAINNET) {
|
||||
const fakeUSDC = new Token(chainId, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'fUSDC', 'Fake USDC')
|
||||
@@ -40,40 +35,17 @@ export default function useUSDCPrice(currency?: Currency): Price<Currency, Token
|
||||
)
|
||||
}
|
||||
|
||||
// handle weth/eth
|
||||
if (wrapped.equals(weth)) {
|
||||
if (usdcPair) {
|
||||
const price = usdcPair.priceOf(weth)
|
||||
return new Price(currency, USDC, price.denominator, price.numerator)
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
// handle usdc
|
||||
if (wrapped.equals(USDC)) {
|
||||
return new Price(USDC, USDC, '1', '1')
|
||||
// use v2 price if available, v3 as fallback
|
||||
if (v2USDCTrade) {
|
||||
const { numerator, denominator } = v2USDCTrade.route.midPrice
|
||||
return new Price(currency, USDC, denominator, numerator)
|
||||
} else if (v3USDCTrade.state === V3TradeState.VALID && v3USDCTrade.trade) {
|
||||
const { numerator, denominator } = v3USDCTrade.trade.route.midPrice
|
||||
return new Price(currency, USDC, denominator, numerator)
|
||||
}
|
||||
|
||||
const ethPairETHAmount = ethPair?.reserveOf(weth)
|
||||
const ethPairETHUSDCValue: JSBI =
|
||||
ethPairETHAmount && usdcEthPair ? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).quotient : JSBI.BigInt(0)
|
||||
|
||||
// all other tokens
|
||||
// first try the usdc pair
|
||||
if (usdcPairState === PairState.EXISTS && usdcPair && usdcPair.reserveOf(USDC).greaterThan(ethPairETHUSDCValue)) {
|
||||
const price = usdcPair.priceOf(wrapped)
|
||||
return new Price(currency, USDC, price.denominator, price.numerator)
|
||||
}
|
||||
if (ethPairState === PairState.EXISTS && ethPair && usdcEthPairState === PairState.EXISTS && usdcEthPair) {
|
||||
if (usdcEthPair.reserveOf(USDC).greaterThan('0') && ethPair.reserveOf(weth).greaterThan('0')) {
|
||||
const ethUsdcPrice = usdcEthPair.priceOf(USDC)
|
||||
const currencyEthPrice = ethPair.priceOf(weth)
|
||||
const usdcPrice = ethUsdcPrice.multiply(currencyEthPrice).invert()
|
||||
return new Price(currency, USDC, usdcPrice.denominator, usdcPrice.numerator)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}, [chainId, currency, ethPair, ethPairState, usdcEthPair, usdcEthPairState, usdcPair, usdcPairState, weth, wrapped])
|
||||
}, [chainId, currency, v2USDCTrade, v3USDCTrade])
|
||||
}
|
||||
|
||||
export function useUSDCValue(currencyAmount: CurrencyAmount<Currency> | undefined | null) {
|
||||
@@ -81,6 +53,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])
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Pair } from '@uniswap/v2-sdk'
|
||||
import { useMemo } from 'react'
|
||||
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useMultipleContractSingleData } from '../state/multicall/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
@@ -61,5 +61,6 @@ export function useV2Pairs(currencies: [Currency | undefined, Currency | undefin
|
||||
}
|
||||
|
||||
export function useV2Pair(tokenA?: Currency, tokenB?: Currency): [PairState, Pair | null] {
|
||||
return useV2Pairs([[tokenA, tokenB]])[0]
|
||||
const inputs: [[Currency | undefined, Currency | undefined]] = useMemo(() => [[tokenA, tokenB]], [tokenA, tokenB])
|
||||
return useV2Pairs(inputs)[0]
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Pair, Trade } from '@uniswap/v2-sdk'
|
||||
import { useMemo } from 'react'
|
||||
import { useUserSingleHopOnly } from 'state/user/hooks'
|
||||
import { isTradeBetter } from 'utils/isTradeBetter'
|
||||
import { BETTER_TRADE_LESS_HOPS_THRESHOLD } from '../constants'
|
||||
import { BETTER_TRADE_LESS_HOPS_THRESHOLD } from '../constants/misc'
|
||||
import { useAllCurrencyCombinations } from './useAllCurrencyCombinations'
|
||||
import { PairState, useV2Pairs } from './useV2Pairs'
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useMemo } from 'react'
|
||||
import { tryParseAmount } from '../state/swap/hooks'
|
||||
import { useTransactionAdder } from '../state/transactions/hooks'
|
||||
import { useCurrencyBalance } from '../state/wallet/hooks'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useWETHContract } from './useContract'
|
||||
|
||||
export enum WrapType {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Web3ReactContextInterface } from '@web3-react/core/dist/types'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { isMobile } from 'react-device-detect'
|
||||
import { injected } from '../connectors'
|
||||
import { NetworkContextName } from '../constants'
|
||||
import { NetworkContextName } from '../constants/misc'
|
||||
|
||||
export function useActiveWeb3React(): Web3ReactContextInterface<Web3Provider> & { chainId?: ChainId } {
|
||||
const context = useWeb3ReactCore<Web3Provider>()
|
||||
@@ -7,7 +7,7 @@ import ReactGA from 'react-ga'
|
||||
import { Provider } from 'react-redux'
|
||||
import { HashRouter } from 'react-router-dom'
|
||||
import Blocklist from './components/Blocklist'
|
||||
import { NetworkContextName } from './constants'
|
||||
import { NetworkContextName } from './constants/misc'
|
||||
import './i18n'
|
||||
import App from './pages/App'
|
||||
import store from './state'
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import { AutoRow } from '../../components/Row'
|
||||
import { ONE_BIPS } from '../../constants'
|
||||
import { ONE_BIPS } from '../../constants/misc'
|
||||
import { Field } from '../../state/mint/v3/actions'
|
||||
import { TYPE } from '../../theme'
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useCallback, useContext, useMemo, useState, useEffect } from 'react'
|
||||
import React, { useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { WETH9 } from '@uniswap/sdk-core'
|
||||
import { AlertTriangle, AlertCircle } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
import { ZERO_PERCENT } from '../../constants'
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from '../../constants/addresses'
|
||||
import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
|
||||
import { RouteComponentProps } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
@@ -17,8 +18,9 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import { RowBetween, RowFixed } from '../../components/Row'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import Review from './Review'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
@@ -42,7 +44,6 @@ import {
|
||||
useV3DerivedMintInfo,
|
||||
} from 'state/mint/v3/hooks'
|
||||
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from 'constants/v3'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { useDerivedPositionInfo } from 'hooks/useDerivedPositionInfo'
|
||||
import { PositionPreview } from 'components/PositionPreview'
|
||||
@@ -50,7 +51,6 @@ import FeeSelector from 'components/FeeSelector'
|
||||
import RangeSelector from 'components/RangeSelector'
|
||||
import RateToggle from 'components/RateToggle'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { calculateGasMargin } from 'utils'
|
||||
import { AddRemoveTabs } from 'components/NavigationTabs'
|
||||
import HoverInlineText from 'components/HoverInlineText'
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function AddLiquidity({
|
||||
const currencyB = useCurrency(currencyIdB)
|
||||
|
||||
// keep track for UI display purposes of user selected base currency
|
||||
const [baseCurrency, setBaseCurrency] = useState(currencyA)
|
||||
const baseCurrency = currencyA
|
||||
const quoteCurrency = useMemo(
|
||||
() =>
|
||||
currencyA && currencyB && baseCurrency
|
||||
@@ -99,14 +99,6 @@ export default function AddLiquidity({
|
||||
[currencyA, currencyB, baseCurrency]
|
||||
)
|
||||
|
||||
// url params are the source truth, so we have to do this
|
||||
useEffect(() => {
|
||||
setBaseCurrency(currencyA)
|
||||
return () => {
|
||||
setBaseCurrency(undefined)
|
||||
}
|
||||
}, [currencyA, currencyB])
|
||||
|
||||
// mint state
|
||||
const { independentField, typedValue, startPriceTypedValue } = useV3MintState()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import React from 'react'
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom'
|
||||
import AddLiquidity from './index'
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import { AutoRow } from '../../components/Row'
|
||||
import { ONE_BIPS } from '../../constants'
|
||||
import { ONE_BIPS } from '../../constants/misc'
|
||||
import { Field } from '../../state/mint/actions'
|
||||
import { TYPE } from '../../theme'
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ import { AddRemoveTabs } from '../../components/NavigationTabs'
|
||||
import { MinimalPositionCard } from '../../components/PositionCard'
|
||||
import Row, { RowBetween, RowFlat } from '../../components/Row'
|
||||
|
||||
import { V2_ROUTER_ADDRESS, ZERO_PERCENT } from '../../constants'
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { useV2RouterContract } from '../../hooks/useContract'
|
||||
import { PairState } from '../../hooks/useV2Pairs'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
@@ -32,7 +32,8 @@ import { useDerivedMintInfo, useMintActionHandlers, useMintState } from '../../s
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useIsExpertMode, useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { TYPE } from '../../theme'
|
||||
import { calculateGasMargin, calculateSlippageAmount } from '../../utils'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { calculateSlippageAmount } from '../../utils/calculateSlippageAmount'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { wrappedCurrency } from '../../utils/wrappedCurrency'
|
||||
import AppBody from '../AppBody'
|
||||
@@ -122,14 +123,14 @@ export default function AddLiquidity({
|
||||
{}
|
||||
)
|
||||
|
||||
const router = useV2RouterContract()
|
||||
|
||||
// check whether the user has approved the router on the tokens
|
||||
const [approvalA, approveACallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_A], V2_ROUTER_ADDRESS)
|
||||
const [approvalB, approveBCallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_B], V2_ROUTER_ADDRESS)
|
||||
const [approvalA, approveACallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_A], router?.address)
|
||||
const [approvalB, approveBCallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_B], router?.address)
|
||||
|
||||
const addTransaction = useTransactionAdder()
|
||||
|
||||
const router = useV2RouterContract()
|
||||
|
||||
async function onAdd() {
|
||||
if (!chainId || !library || !account || !router) return
|
||||
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useStakingInfo } from '../../state/stake/hooks'
|
||||
import UnstakingModal from '../../components/earn/UnstakingModal'
|
||||
import ClaimRewardModal from '../../components/earn/ClaimRewardModal'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useColor } from '../../hooks/useColor'
|
||||
import { CountUp } from 'use-count-up'
|
||||
|
||||
@@ -28,7 +28,7 @@ import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
import { useV2Pair } from '../../hooks/useV2Pairs'
|
||||
import usePrevious from '../../hooks/usePrevious'
|
||||
import useUSDCPrice from '../../hooks/useUSDCPrice'
|
||||
import { BIG_INT_ZERO, BIG_INT_SECONDS_IN_WEEK } from '../../constants'
|
||||
import { BIG_INT_ZERO, BIG_INT_SECONDS_IN_WEEK } from '../../constants/misc'
|
||||
|
||||
const PageWrapper = styled(AutoColumn)`
|
||||
max-width: 640px;
|
||||
|
||||
@@ -9,8 +9,8 @@ import { RowBetween } from '../../components/Row'
|
||||
import { CardSection, DataCard, CardNoise, CardBGImage } from '../../components/earn/styled'
|
||||
import { Countdown } from './Countdown'
|
||||
import Loader from '../../components/Loader'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { BIG_INT_ZERO } from '../../constants'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { BIG_INT_ZERO } from '../../constants/misc'
|
||||
import { OutlineCard } from '../../components/Card'
|
||||
|
||||
const PageWrapper = styled(AutoColumn)`
|
||||
|
||||
@@ -10,15 +10,16 @@ import FormattedCurrencyAmount from '../../components/FormattedCurrencyAmount'
|
||||
import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
|
||||
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useToken } from '../../hooks/Tokens'
|
||||
import { usePairContract, useV2MigratorContract } from '../../hooks/useContract'
|
||||
import { NEVER_RELOAD, useSingleCallResult } from '../../state/multicall/hooks'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { BackArrow, ExternalLink, TYPE } from '../../theme'
|
||||
import { calculateGasMargin, getEtherscanLink, isAddress } from '../../utils'
|
||||
import { isAddress } from '../../utils'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
import { BodyWrapper } from '../AppBody'
|
||||
import { V3_MIGRATOR_ADDRESSES } from 'constants/v3'
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk'
|
||||
import { BlueCard, DarkGreyCard, LightCard, YellowCard } from 'components/Card'
|
||||
@@ -208,6 +209,7 @@ function V2PairMigration({
|
||||
tickUpper,
|
||||
amount0: token0Value.quotient,
|
||||
amount1: token1Value.quotient,
|
||||
useFullPrecision: false, // we don't want full precision as this is used to calculate slippage amounts
|
||||
})
|
||||
: undefined
|
||||
|
||||
@@ -253,9 +255,8 @@ function V2PairMigration({
|
||||
const migrator = useV2MigratorContract()
|
||||
|
||||
// approvals
|
||||
const migratorAddress = chainId && V3_MIGRATOR_ADDRESSES[chainId]
|
||||
const [approval, approveManually] = useApproveCallback(pairBalance, migratorAddress)
|
||||
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(pairBalance, migratorAddress)
|
||||
const [approval, approveManually] = useApproveCallback(pairBalance, migrator?.address)
|
||||
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(pairBalance, migrator?.address)
|
||||
|
||||
const approve = useCallback(async () => {
|
||||
if (isNotUniswap) {
|
||||
@@ -395,8 +396,8 @@ function V2PairMigration({
|
||||
<TYPE.body my={9} style={{ fontWeight: 400 }}>
|
||||
This tool will safely migrate your {isNotUniswap ? 'SushiSwap' : 'V2'} liquidity to V3. The process is
|
||||
completely trustless thanks to the{' '}
|
||||
{chainId && migratorAddress && (
|
||||
<ExternalLink href={getEtherscanLink(chainId, migratorAddress, 'address')}>
|
||||
{chainId && migrator && (
|
||||
<ExternalLink href={getExplorerLink(chainId, migrator.address, ExplorerDataType.ADDRESS)}>
|
||||
<TYPE.blue display="inline">Uniswap migration contract↗</TYPE.blue>
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ThemeContext } from 'styled-components'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import { AutoRow } from '../../components/Row'
|
||||
import { Text } from 'rebass'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useTokenBalancesWithLoadingIndicator } from '../../state/wallet/hooks'
|
||||
import { BackArrow, StyledInternalLink, TYPE } from '../../theme'
|
||||
import { LightCard } from '../../components/Card'
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
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 { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
import { LoadingRows } from './styleds'
|
||||
import styled from 'styled-components/macro'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
@@ -14,7 +16,6 @@ import { RowBetween, RowFixed } from 'components/Row'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import { ExternalLink, HideExtraSmall, TYPE } from 'theme'
|
||||
import Badge from 'components/Badge'
|
||||
import { calculateGasMargin, getEtherscanLink } from 'utils'
|
||||
import { ButtonConfirmed, ButtonPrimary, ButtonGray } from 'components/Button'
|
||||
import { DarkCard, LightCard } from 'components/Card'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
@@ -23,8 +24,18 @@ 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 { useActiveWeb3React } from 'hooks'
|
||||
import {
|
||||
Token,
|
||||
Currency,
|
||||
CurrencyAmount,
|
||||
Percent,
|
||||
Fraction,
|
||||
Price,
|
||||
Ether,
|
||||
currencyEquals,
|
||||
ETHER,
|
||||
} from '@uniswap/sdk-core'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
import ReactGA from 'react-ga'
|
||||
@@ -38,6 +49,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;
|
||||
@@ -172,6 +184,28 @@ function CurrentPriceCard({
|
||||
)
|
||||
}
|
||||
|
||||
function LinkedCurrency({ chainId, currency }: { chainId?: number; currency?: Currency }) {
|
||||
const address = (currency as Token)?.address
|
||||
|
||||
if (typeof chainId === 'number' && address) {
|
||||
return (
|
||||
<ExternalLink href={getExplorerLink(chainId, address, ExplorerDataType.ADDRESS)}>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currency} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{currency?.symbol} ↗</TYPE.main>
|
||||
</RowFixed>
|
||||
</ExternalLink>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currency} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{currency?.symbol}</TYPE.main>
|
||||
</RowFixed>
|
||||
)
|
||||
}
|
||||
|
||||
function getRatio(
|
||||
lower: Price<Currency, Currency>,
|
||||
current: Price<Currency, Currency>,
|
||||
@@ -200,20 +234,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 +256,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 +318,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 +356,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 +372,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 +419,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 +444,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 +454,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>
|
||||
@@ -525,7 +568,7 @@ export function PositionPage({
|
||||
<NFT image={metadata.result.image} height={400} />
|
||||
</div>
|
||||
{typeof chainId === 'number' && owner && !ownsNFT ? (
|
||||
<ExternalLink href={getEtherscanLink(chainId, owner, 'address')}>Owner</ExternalLink>
|
||||
<ExternalLink href={getExplorerLink(chainId, owner, ExplorerDataType.ADDRESS)}>Owner</ExternalLink>
|
||||
) : null}
|
||||
</DarkCard>
|
||||
) : (
|
||||
@@ -547,7 +590,7 @@ export function PositionPage({
|
||||
<Label>Liquidity</Label>
|
||||
{fiatValueOfLiquidity?.greaterThan(new Fraction(1, 100)) ? (
|
||||
<TYPE.largeHeader fontSize="36px" fontWeight={500}>
|
||||
${fiatValueOfLiquidity.toFixed(2)}
|
||||
${fiatValueOfLiquidity.toFixed(2, { groupSeparator: ',' })}
|
||||
</TYPE.largeHeader>
|
||||
) : (
|
||||
<TYPE.largeHeader color={theme.text1} fontSize="36px" fontWeight={500}>
|
||||
@@ -558,10 +601,7 @@ export function PositionPage({
|
||||
<LightCard padding="12px 16px">
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currencyQuote} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{currencyQuote?.symbol}</TYPE.main>
|
||||
</RowFixed>
|
||||
<LinkedCurrency chainId={chainId} currency={currencyQuote} />
|
||||
<RowFixed>
|
||||
<TYPE.main>
|
||||
{inverted ? position?.amount0.toSignificant(4) : position?.amount1.toSignificant(4)}
|
||||
@@ -574,10 +614,7 @@ export function PositionPage({
|
||||
</RowFixed>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<RowFixed>
|
||||
<CurrencyLogo currency={currencyBase} size={'20px'} style={{ marginRight: '0.5rem' }} />
|
||||
<TYPE.main>{currencyBase?.symbol}</TYPE.main>
|
||||
</RowFixed>
|
||||
<LinkedCurrency chainId={chainId} currency={currencyBase} />
|
||||
<RowFixed>
|
||||
<TYPE.main>
|
||||
{inverted ? position?.amount1.toSignificant(4) : position?.amount0.toSignificant(4)}
|
||||
@@ -603,7 +640,7 @@ export function PositionPage({
|
||||
<Label>Unclaimed fees</Label>
|
||||
{fiatValueOfFees?.greaterThan(new Fraction(1, 100)) ? (
|
||||
<TYPE.largeHeader color={theme.green1} fontSize="36px" fontWeight={500}>
|
||||
${fiatValueOfFees.toFixed(2)}
|
||||
${fiatValueOfFees.toFixed(2, { groupSeparator: ',' })}
|
||||
</TYPE.largeHeader>
|
||||
) : (
|
||||
<TYPE.largeHeader color={theme.text1} fontSize="36px" fontWeight={500}>
|
||||
@@ -640,40 +677,49 @@ 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)) &&
|
||||
currency0 &&
|
||||
currency1 &&
|
||||
(currencyEquals(currency0, ETHER) || currencyEquals(currency1, ETHER)) &&
|
||||
!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>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { FlyoutAlignment, NewMenu } from 'components/Menu'
|
||||
import { SwapPoolTabs } from 'components/NavigationTabs'
|
||||
import PositionList from 'components/PositionList'
|
||||
import { RowBetween, RowFixed } from 'components/Row'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { useV3Positions } from 'hooks/useV3Positions'
|
||||
import { BookOpen, ChevronDown, Download, Inbox, PlusCircle, ChevronsRight, Layers } from 'react-feather'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -14,13 +14,13 @@ import { ChevronsRight } from 'react-feather'
|
||||
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useV2Pairs } from '../../hooks/useV2Pairs'
|
||||
import { toV2LiquidityToken, useTrackedTokenPairs } from '../../state/user/hooks'
|
||||
import { Dots } from '../../components/swap/styleds'
|
||||
import { CardSection, DataCard, CardNoise, CardBGImage } from '../../components/earn/styled'
|
||||
import { useStakingInfo } from '../../state/stake/hooks'
|
||||
import { BIG_INT_ZERO } from '../../constants'
|
||||
import { BIG_INT_ZERO } from '../../constants/misc'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
|
||||
const PageWrapper = styled(AutoColumn)`
|
||||
|
||||
@@ -12,7 +12,7 @@ import { MinimalPositionCard } from '../../components/PositionCard'
|
||||
import Row from '../../components/Row'
|
||||
import CurrencySearchModal from '../../components/SearchModal/CurrencySearchModal'
|
||||
import { PairState, useV2Pair } from '../../hooks/useV2Pairs'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { usePairAdder } from '../../state/user/hooks'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { StyledInternalLink } from '../../theme'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user