Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbbffd17a6 | ||
|
|
85d8b1e514 | ||
|
|
739986ba66 | ||
|
|
e9148b30c9 | ||
|
|
6e46f25bd4 | ||
|
|
02269e9376 | ||
|
|
9822e68d5a | ||
|
|
9d1556b777 | ||
|
|
858b6afb2f | ||
|
|
da14d8fd5b | ||
|
|
3aaa3fef89 | ||
|
|
bc243e1c07 | ||
|
|
679a58daf4 | ||
|
|
eff512deb8 | ||
|
|
562b402293 | ||
|
|
99ad4ae44c | ||
|
|
6e52a43584 | ||
|
|
d4c5d3e8c8 | ||
|
|
a6e46623ad | ||
|
|
9353c7838c | ||
|
|
816249b4b1 | ||
|
|
70292a5512 | ||
|
|
ecdbb4a49f | ||
|
|
536a5d99de | ||
|
|
ffc2015595 | ||
|
|
5e30a4b4ad | ||
|
|
b14da2844d | ||
|
|
d3c04b7246 | ||
|
|
307a995a50 | ||
|
|
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'
|
||||
|
||||
37
README.md
37
README.md
@@ -10,11 +10,14 @@ An open source interface for Uniswap -- a protocol for decentralized exchange of
|
||||
- Website: [uniswap.org](https://uniswap.org/)
|
||||
- Interface: [app.uniswap.org](https://app.uniswap.org)
|
||||
- Docs: [uniswap.org/docs/](https://uniswap.org/docs/)
|
||||
- Twitter: [@UniswapProtocol](https://twitter.com/UniswapProtocol)
|
||||
- Twitter: [@Uniswap](https://twitter.com/Uniswap)
|
||||
- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/)
|
||||
- Email: [contact@uniswap.org](mailto:contact@uniswap.org)
|
||||
- Discord: [Uniswap](https://discord.gg/FCfyBSbCU5)
|
||||
- Whitepaper: [Link](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig)
|
||||
- Whitepapers:
|
||||
- [V1](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig)
|
||||
- [V2](https://uniswap.org/whitepaper.pdf)
|
||||
- [V3](https://uniswap.org/whitepaper-v3.pdf)
|
||||
|
||||
## Accessing the Uniswap Interface
|
||||
|
||||
@@ -27,7 +30,7 @@ or visit [app.uniswap.org](https://app.uniswap.org).
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
yarn
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Run
|
||||
@@ -36,26 +39,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).
|
||||
|
||||
21
package.json
21
package.json
@@ -5,7 +5,8 @@
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@emotion/core": "^11.0.0",
|
||||
"@ethersproject/experimental": "^5.0.1",
|
||||
"@ethersproject/experimental": "^5.2.0",
|
||||
"@metamask/jazzicon": "^2.0.0",
|
||||
"@popperjs/core": "^2.4.4",
|
||||
"@reach/dialog": "^0.10.3",
|
||||
"@reach/portal": "^0.10.3",
|
||||
@@ -48,16 +49,16 @@
|
||||
"@uniswap/token-lists": "^1.0.0-beta.19",
|
||||
"@uniswap/v2-core": "1.0.0",
|
||||
"@uniswap/v2-periphery": "^1.1.0-beta.0",
|
||||
"@uniswap/v2-sdk": "^3.0.0-alpha.0",
|
||||
"@uniswap/v2-sdk": "^3.0.0-alpha.2",
|
||||
"@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.9",
|
||||
"@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",
|
||||
@@ -68,12 +69,11 @@
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-react": "^7.19.0",
|
||||
"eslint-plugin-react-hooks": "^4.0.0",
|
||||
"ethers": "^5.0.7",
|
||||
"ethers": "^5.2.0",
|
||||
"i18next": "^15.0.9",
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
"i18next-xhr-backend": "^2.0.1",
|
||||
"inter-ui": "^3.13.1",
|
||||
"jazzicon": "^1.5.0",
|
||||
"lightweight-charts": "^3.3.0",
|
||||
"lodash.flatmap": "^4.5.0",
|
||||
"luxon": "^1.25.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",
|
||||
|
||||
61
src/abis/argent-wallet-contract.json
Normal file
61
src/abis/argent-wallet-contract.json
Normal file
@@ -0,0 +1,61 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "_transactions",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"name": "wc_multiCall",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes[]",
|
||||
"name": "",
|
||||
"type": "bytes[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "_msgHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "_signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "isValidSignature",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes4",
|
||||
"name": "",
|
||||
"type": "bytes4"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
@@ -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={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()
|
||||
|
||||
@@ -24,8 +24,8 @@ export function FiatValue({
|
||||
|
||||
return (
|
||||
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
|
||||
{fiatValue ? '~' : ''}$
|
||||
<HoverInlineText text={fiatValue ? fiatValue?.toSignificant(6, { groupSeparator: ',' }) : '-'} />{' '}
|
||||
{fiatValue ? '~$' : ''}
|
||||
<HoverInlineText text={fiatValue ? fiatValue?.toSignificant(6, { groupSeparator: ',' }) : ''} />{' '}
|
||||
{priceImpact ? (
|
||||
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-1).toSignificant(3)}%)</span>
|
||||
) : null}
|
||||
|
||||
@@ -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'
|
||||
@@ -273,14 +273,14 @@ export default function CurrencyInputPanel({
|
||||
formatTokenAmount(selectedCurrencyBalance, 4) +
|
||||
' ' +
|
||||
currency.symbol
|
||||
: '-'}
|
||||
: ''}
|
||||
</TYPE.body>
|
||||
{showMaxButton && selectedCurrencyBalance ? (
|
||||
<StyledBalanceMax onClick={onMax}>(Max)</StyledBalanceMax>
|
||||
) : null}
|
||||
</RowFixed>
|
||||
) : (
|
||||
'-'
|
||||
<span></span>
|
||||
)}
|
||||
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
||||
</RowBetween>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import React, { useMemo } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import EthereumLogo from '../../assets/images/ethereum-logo.png'
|
||||
@@ -37,10 +37,10 @@ export default function CurrencyLogo({
|
||||
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
|
||||
|
||||
const srcs: string[] = useMemo(() => {
|
||||
if (!currency || currency.isEther) return []
|
||||
if (!currency || currency.isNative) return []
|
||||
|
||||
if (currency.isToken) {
|
||||
const defaultUrls = currency.chainId === ChainId.MAINNET ? [getTokenLogoURL(currency.address)] : []
|
||||
const defaultUrls = currency.chainId === 1 ? [getTokenLogoURL(currency.address)] : []
|
||||
if (currency instanceof WrappedTokenInfo) {
|
||||
return [...uriLocations, ...defaultUrls]
|
||||
}
|
||||
@@ -49,7 +49,7 @@ export default function CurrencyLogo({
|
||||
return []
|
||||
}, [currency, uriLocations])
|
||||
|
||||
if (currency?.isEther) {
|
||||
if (currency?.isNative) {
|
||||
return <StyledEthereumLogo src={EthereumLogo} size={size} style={style} {...rest} />
|
||||
}
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { ChainId, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
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'
|
||||
@@ -54,9 +54,7 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
|
||||
const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
|
||||
const circulation: CurrencyAmount<Token> | undefined = useMemo(
|
||||
() =>
|
||||
blockTimestamp && uni && chainId === ChainId.MAINNET
|
||||
? computeUniCirculation(uni, blockTimestamp, unclaimedUni)
|
||||
: totalSupply,
|
||||
blockTimestamp && uni && chainId === 1 ? computeUniCirculation(uni, blockTimestamp, unclaimedUni) : totalSupply,
|
||||
[blockTimestamp, chainId, totalSupply, unclaimedUni, uni]
|
||||
)
|
||||
|
||||
@@ -116,7 +114,7 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
|
||||
<TYPE.white color="white">Total Supply</TYPE.white>
|
||||
<TYPE.white color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
|
||||
</RowBetween>
|
||||
{uni && uni.chainId === ChainId.MAINNET ? (
|
||||
{uni && uni.chainId === 1 ? (
|
||||
<ExternalLink href={`https://info.uniswap.org/token/${uni.address}`}>View UNI Analytics</ExternalLink>
|
||||
) : null}
|
||||
</AutoColumn>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import useScrollPosition from '@react-hook/window-scroll'
|
||||
import React, { useState } from 'react'
|
||||
import { Text } from 'rebass'
|
||||
@@ -11,7 +10,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'
|
||||
@@ -301,11 +300,11 @@ export const StyledMenuButton = styled.button`
|
||||
}
|
||||
`
|
||||
|
||||
const NETWORK_LABELS: { [chainId in ChainId]?: string } = {
|
||||
[ChainId.RINKEBY]: 'Rinkeby',
|
||||
[ChainId.ROPSTEN]: 'Ropsten',
|
||||
[ChainId.GÖRLI]: 'Görli',
|
||||
[ChainId.KOVAN]: 'Kovan',
|
||||
const NETWORK_LABELS: { [chainId: number]: string } = {
|
||||
[4]: 'Rinkeby',
|
||||
[3]: 'Ropsten',
|
||||
[5]: 'Görli',
|
||||
[42]: 'Kovan',
|
||||
}
|
||||
|
||||
export default function Header() {
|
||||
|
||||
@@ -3,7 +3,6 @@ import React, { useState } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
const TextWrapper = styled.span<{ margin: boolean; link?: boolean; fontSize?: string; adjustSize?: boolean }>`
|
||||
cursor: auto;
|
||||
margin-left: ${({ margin }) => margin && '4px'};
|
||||
color: ${({ theme, link }) => (link ? theme.blue1 : theme.text1)};
|
||||
font-size: ${({ fontSize }) => fontSize ?? 'inherit'};
|
||||
@@ -22,7 +21,7 @@ const HoverInlineText = ({
|
||||
link,
|
||||
...rest
|
||||
}: {
|
||||
text: string
|
||||
text?: string
|
||||
maxCharacters?: number
|
||||
margin?: boolean
|
||||
adjustSize?: boolean
|
||||
|
||||
@@ -2,8 +2,8 @@ import React, { useEffect, useRef } from 'react'
|
||||
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import Jazzicon from 'jazzicon'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import Jazzicon from '@metamask/jazzicon'
|
||||
|
||||
const StyledIdenticonContainer = styled.div`
|
||||
height: 1rem;
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import React, { useEffect } from 'react'
|
||||
import React, { useCallback, useEffect } from 'react'
|
||||
import ReactGA from 'react-ga'
|
||||
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,
|
||||
@@ -62,6 +63,13 @@ export default function ClaimPopup() {
|
||||
// toggle for showing this modal
|
||||
const showClaimModal = useModalOpen(ApplicationModal.SELF_CLAIM)
|
||||
const toggleSelfClaimModal = useToggleSelfClaimModal()
|
||||
const handleToggleSelfClaimModal = useCallback(() => {
|
||||
ReactGA.event({
|
||||
category: 'MerkleDrop',
|
||||
action: 'Toggle self claim modal',
|
||||
})
|
||||
toggleSelfClaimModal()
|
||||
}, [toggleSelfClaimModal])
|
||||
|
||||
// const userHasAvailableclaim = useUserHasAvailableClaim()
|
||||
const userHasAvailableclaim: boolean = useUserHasAvailableClaim(account)
|
||||
@@ -70,6 +78,10 @@ export default function ClaimPopup() {
|
||||
// listen for available claim and show popup if needed
|
||||
useEffect(() => {
|
||||
if (userHasAvailableclaim) {
|
||||
ReactGA.event({
|
||||
category: 'MerkleDrop',
|
||||
action: 'Show claim popup',
|
||||
})
|
||||
toggleShowClaimPopup()
|
||||
}
|
||||
// the toggleShowClaimPopup function changes every time the popup changes, so this will cause an infinite loop.
|
||||
@@ -102,7 +114,7 @@ export default function ClaimPopup() {
|
||||
</TYPE.subHeader>
|
||||
</AutoColumn>
|
||||
<AutoColumn style={{ zIndex: 10 }} justify="center">
|
||||
<ButtonPrimary padding="8px" borderRadius="8px" width={'fit-content'} onClick={toggleSelfClaimModal}>
|
||||
<ButtonPrimary padding="8px" borderRadius="8px" width={'fit-content'} onClick={handleToggleSelfClaimModal}>
|
||||
Claim your UNI tokens
|
||||
</ButtonPrimary>
|
||||
</AutoColumn>
|
||||
|
||||
@@ -46,7 +46,11 @@ export default function ListUpdatePopup({
|
||||
removeThisPopup()
|
||||
}, [auto, dispatch, listUrl, removeThisPopup])
|
||||
|
||||
const { added: tokensAdded, changed: tokensChanged, removed: tokensRemoved } = useMemo(() => {
|
||||
const {
|
||||
added: tokensAdded,
|
||||
changed: tokensChanged,
|
||||
removed: tokensRemoved,
|
||||
} = useMemo(() => {
|
||||
return diffTokenLists(oldList.tokens, newList.tokens)
|
||||
}, [newList.tokens, oldList.tokens])
|
||||
const numTokensChanged = useMemo(
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Link } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { unwrappedToken } from '../../utils/wrappedCurrency'
|
||||
import { unwrappedToken } from '../../utils/unwrappedToken'
|
||||
import { ButtonEmpty } from '../Button'
|
||||
import { transparentize } from 'polished'
|
||||
import { CardNoise } from '../earn/styled'
|
||||
|
||||
@@ -8,10 +8,10 @@ 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'
|
||||
import { unwrappedToken } from '../../utils/unwrappedToken'
|
||||
import { ButtonPrimary, ButtonSecondary, ButtonEmpty } from '../Button'
|
||||
import { transparentize } from 'polished'
|
||||
import { CardNoise } from '../earn/styled'
|
||||
@@ -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,11 +9,11 @@ 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'
|
||||
import { unwrappedToken } from '../../utils/wrappedCurrency'
|
||||
import { unwrappedToken } from '../../utils/unwrappedToken'
|
||||
import { ButtonPrimary, ButtonSecondary, ButtonEmpty } from '../Button'
|
||||
import { transparentize } from 'polished'
|
||||
import { CardNoise } from '../earn/styled'
|
||||
@@ -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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import Badge from 'components/Badge'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
@@ -11,16 +11,18 @@ import { PositionDetails } from 'types/position'
|
||||
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 { unwrappedToken } from 'utils/unwrappedToken'
|
||||
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)`
|
||||
const LinkRow = styled(Link)`
|
||||
align-items: center;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
justify-content: space-between;
|
||||
color: ${({ theme }) => theme.text1};
|
||||
margin: 8px 0;
|
||||
@@ -50,6 +52,7 @@ const Row = styled(Link)`
|
||||
row-gap: 24px;
|
||||
`};
|
||||
`
|
||||
|
||||
const BadgeText = styled.div`
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
@@ -65,7 +68,6 @@ const DataLineItem = styled.div`
|
||||
const RangeLineItem = styled(DataLineItem)`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
justify-self: flex-end;
|
||||
|
||||
@@ -118,9 +120,7 @@ export interface PositionListItemProps {
|
||||
positionDetails: PositionDetails
|
||||
}
|
||||
|
||||
export function getPriceOrderingFromPositionForUI(
|
||||
position?: Position
|
||||
): {
|
||||
export function getPriceOrderingFromPositionForUI(position?: Position): {
|
||||
priceLower?: Price<Token, Token>
|
||||
priceUpper?: Price<Token, Token>
|
||||
quote?: Token
|
||||
@@ -201,25 +201,20 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
||||
}, [liquidity, pool, tickLower, tickUpper])
|
||||
|
||||
// prices
|
||||
let { priceLower, priceUpper, base, quote } = getPriceOrderingFromPositionForUI(position)
|
||||
const inverted = token1 ? base?.equals(token1) : undefined
|
||||
const currencyQuote = inverted ? currency1 : currency0
|
||||
const currencyBase = inverted ? currency0 : currency1
|
||||
const { priceLower, priceUpper, quote, base } = getPriceOrderingFromPositionForUI(position)
|
||||
|
||||
const currencyQuote = quote && unwrappedToken(quote)
|
||||
const currencyBase = base && unwrappedToken(base)
|
||||
|
||||
// check if price is within range
|
||||
const outOfRange: boolean = pool ? pool.tickCurrent < tickLower || pool.tickCurrent >= tickUpper : false
|
||||
|
||||
const positionSummaryLink = '/pool/' + positionDetails.tokenId
|
||||
|
||||
const [manuallyInverted, setManuallyInverted] = useState(true)
|
||||
if (manuallyInverted) {
|
||||
;[priceLower, priceUpper, base, quote] = [priceUpper?.invert(), priceLower?.invert(), quote, base]
|
||||
}
|
||||
|
||||
const removed = liquidity?.eq(0)
|
||||
|
||||
return (
|
||||
<Row to={positionSummaryLink}>
|
||||
<LinkRow to={positionSummaryLink}>
|
||||
<RowFixed>
|
||||
<PrimaryPositionIdData>
|
||||
<DoubleCurrencyLogo currency0={currencyBase} currency1={currencyQuote} size={18} margin />
|
||||
@@ -235,42 +230,27 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
||||
</RowFixed>
|
||||
|
||||
{priceLower && priceUpper ? (
|
||||
<>
|
||||
<RangeLineItem
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setManuallyInverted(!manuallyInverted)
|
||||
}}
|
||||
>
|
||||
<RangeText>
|
||||
<ExtentsText>Min: </ExtentsText>
|
||||
{formatPrice(priceLower, 5)}{' '}
|
||||
<HoverInlineText text={manuallyInverted ? currencyQuote?.symbol ?? '' : currencyBase?.symbol ?? ''} />{' '}
|
||||
{' per '}{' '}
|
||||
<HoverInlineText text={manuallyInverted ? currencyBase?.symbol ?? '' : currencyQuote?.symbol ?? ''} />
|
||||
</RangeText>{' '}
|
||||
<HideSmall>
|
||||
<DoubleArrow>⟷</DoubleArrow>{' '}
|
||||
</HideSmall>
|
||||
<SmallOnly>
|
||||
<DoubleArrow>↕</DoubleArrow>{' '}
|
||||
</SmallOnly>
|
||||
<RangeText>
|
||||
<ExtentsText>Max:</ExtentsText>
|
||||
{formatPrice(priceUpper, 5)}{' '}
|
||||
<HoverInlineText text={manuallyInverted ? currencyQuote?.symbol ?? '' : currencyBase?.symbol ?? ''} />{' '}
|
||||
{' per '}{' '}
|
||||
<HoverInlineText
|
||||
maxCharacters={10}
|
||||
text={manuallyInverted ? currencyBase?.symbol ?? '' : currencyQuote?.symbol ?? ''}
|
||||
/>
|
||||
</RangeText>{' '}
|
||||
</RangeLineItem>
|
||||
</>
|
||||
<RangeLineItem>
|
||||
<RangeText>
|
||||
<ExtentsText>Min: </ExtentsText>
|
||||
{formatPrice(priceLower, 5)} <HoverInlineText text={currencyQuote?.symbol} /> {' per '}{' '}
|
||||
<HoverInlineText text={currencyBase?.symbol ?? ''} />
|
||||
</RangeText>{' '}
|
||||
<HideSmall>
|
||||
<DoubleArrow>⟷</DoubleArrow>{' '}
|
||||
</HideSmall>
|
||||
<SmallOnly>
|
||||
<DoubleArrow>↕</DoubleArrow>{' '}
|
||||
</SmallOnly>
|
||||
<RangeText>
|
||||
<ExtentsText>Max:</ExtentsText>
|
||||
{formatPrice(priceUpper, 5)} <HoverInlineText text={currencyQuote?.symbol} /> {' per '}{' '}
|
||||
<HoverInlineText maxCharacters={10} text={currencyBase?.symbol} />
|
||||
</RangeText>
|
||||
</RangeLineItem>
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</Row>
|
||||
</LinkRow>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AutoColumn } from 'components/Column'
|
||||
import { TYPE } from 'theme'
|
||||
import { RowBetween, RowFixed } from 'components/Row'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
import { Break } from 'components/earn/styled'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
|
||||
@@ -2,8 +2,6 @@ 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 { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
|
||||
// currencyA is the base token
|
||||
export default function RangeSelector({
|
||||
@@ -31,9 +29,8 @@ export default function RangeSelector({
|
||||
currencyB?: Currency | null
|
||||
feeAmount?: number
|
||||
}) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const tokenA = wrappedCurrency(currencyA ?? undefined, chainId)
|
||||
const tokenB = wrappedCurrency(currencyB ?? undefined, chainId)
|
||||
const tokenA = (currencyA ?? undefined)?.wrapped
|
||||
const tokenB = (currencyB ?? undefined)?.wrapped
|
||||
const isSorted = tokenA && tokenB && tokenA.sortsBefore(tokenB)
|
||||
|
||||
const leftPrice = isSorted ? priceLower : priceUpper?.invert()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { ToggleElement, ToggleWrapper } from 'components/Toggle/MultiToggle'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
|
||||
// the order of displayed base currencies from left to right is always in sort order
|
||||
// currencyA is treated as the preferred base currency
|
||||
@@ -15,10 +13,8 @@ export default function RateToggle({
|
||||
currencyB: Currency
|
||||
handleRateToggle: () => void
|
||||
}) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
const tokenA = wrappedCurrency(currencyA, chainId)
|
||||
const tokenB = wrappedCurrency(currencyB, chainId)
|
||||
const tokenA = currencyA?.wrapped
|
||||
const tokenB = currencyB?.wrapped
|
||||
|
||||
const isSorted = tokenA && tokenB && tokenA.sortsBefore(tokenB)
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from 'react'
|
||||
import { Text } from 'rebass'
|
||||
import { ChainId, Currency, currencyEquals, Token, ETHER } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { SUGGESTED_BASES } from '../../constants'
|
||||
import { COMMON_BASES } from '../../constants/routing'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { AutoColumn } from '../Column'
|
||||
import QuestionHelper from '../QuestionHelper'
|
||||
import { AutoRow } from '../Row'
|
||||
@@ -30,11 +31,13 @@ export default function CommonBases({
|
||||
onSelect,
|
||||
selectedCurrency,
|
||||
}: {
|
||||
chainId?: ChainId
|
||||
chainId?: number
|
||||
selectedCurrency?: Currency | null
|
||||
onSelect: (currency: Currency) => void
|
||||
}) {
|
||||
return (
|
||||
const bases = typeof chainId !== 'undefined' ? COMMON_BASES[chainId] ?? [] : []
|
||||
|
||||
return bases.length > 0 ? (
|
||||
<AutoColumn gap="md">
|
||||
<AutoRow>
|
||||
<Text fontWeight={500} fontSize={14}>
|
||||
@@ -43,31 +46,22 @@ export default function CommonBases({
|
||||
<QuestionHelper text="These tokens are commonly paired with other tokens." />
|
||||
</AutoRow>
|
||||
<AutoRow gap="4px">
|
||||
<BaseWrapper
|
||||
onClick={() => {
|
||||
if (!selectedCurrency || !currencyEquals(selectedCurrency, ETHER)) {
|
||||
onSelect(ETHER)
|
||||
}
|
||||
}}
|
||||
disable={selectedCurrency?.isEther}
|
||||
>
|
||||
<CurrencyLogo currency={ETHER} style={{ marginRight: 8 }} />
|
||||
<Text fontWeight={500} fontSize={16}>
|
||||
ETH
|
||||
</Text>
|
||||
</BaseWrapper>
|
||||
{(typeof chainId === 'number' ? SUGGESTED_BASES[chainId] ?? [] : []).map((token: Token) => {
|
||||
const selected = selectedCurrency?.isToken && selectedCurrency.address === token.address
|
||||
{bases.map((currency: Currency) => {
|
||||
const isSelected = selectedCurrency?.equals(currency)
|
||||
return (
|
||||
<BaseWrapper onClick={() => !selected && onSelect(token)} disable={selected} key={token.address}>
|
||||
<CurrencyLogo currency={token} style={{ marginRight: 8 }} />
|
||||
<BaseWrapper
|
||||
onClick={() => !isSelected && onSelect(currency)}
|
||||
disable={isSelected}
|
||||
key={currencyId(currency)}
|
||||
>
|
||||
<CurrencyLogo currency={currency} style={{ marginRight: 8 }} />
|
||||
<Text fontWeight={500} fontSize={16}>
|
||||
{token.symbol}
|
||||
{currency.symbol}
|
||||
</Text>
|
||||
</BaseWrapper>
|
||||
)
|
||||
})}
|
||||
</AutoRow>
|
||||
</AutoColumn>
|
||||
)
|
||||
) : null
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Currency, CurrencyAmount, currencyEquals, Token } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
|
||||
import { FixedSizeList } from 'react-window'
|
||||
import { Text } from 'rebass'
|
||||
import styled from 'styled-components/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'
|
||||
@@ -17,7 +17,6 @@ import { MenuItem } from './styleds'
|
||||
import Loader from '../Loader'
|
||||
import { isTokenOnList } from '../../utils'
|
||||
import ImportRow from './ImportRow'
|
||||
import { wrappedCurrency } from 'utils/wrappedCurrency'
|
||||
import { LightGreyCard } from 'components/Card'
|
||||
import TokenListLogo from '../../assets/svg/tokenlist.svg'
|
||||
import QuestionHelper from 'components/QuestionHelper'
|
||||
@@ -133,7 +132,7 @@ function CurrencyRow({
|
||||
{currency.symbol}
|
||||
</Text>
|
||||
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
|
||||
{currency.name} {!currency.isEther && !isOnSelectedList && customAdded && '• Added by user'}
|
||||
{currency.name} {!currency.isNative && !isOnSelectedList && customAdded && '• Added by user'}
|
||||
</TYPE.darkGray>
|
||||
</Column>
|
||||
<TokenTags currency={currency} />
|
||||
@@ -197,8 +196,6 @@ export default function CurrencyList({
|
||||
return currencies
|
||||
}, [currencies, otherListTokens])
|
||||
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
const Row = useCallback(
|
||||
function TokenRow({ data, index, style }) {
|
||||
const row: Currency | BreakLine = data[index]
|
||||
@@ -209,11 +206,11 @@ export default function CurrencyList({
|
||||
|
||||
const currency = row
|
||||
|
||||
const isSelected = Boolean(currency && selectedCurrency && currencyEquals(selectedCurrency, currency))
|
||||
const otherSelected = Boolean(currency && otherCurrency && currencyEquals(otherCurrency, currency))
|
||||
const isSelected = Boolean(currency && selectedCurrency && selectedCurrency.equals(currency))
|
||||
const otherSelected = Boolean(currency && otherCurrency && otherCurrency.equals(currency))
|
||||
const handleSelect = () => currency && onCurrencySelect(currency)
|
||||
|
||||
const token = wrappedCurrency(currency, chainId)
|
||||
const token = currency?.wrapped
|
||||
|
||||
const showImport = index > currencies.length
|
||||
|
||||
@@ -235,7 +232,7 @@ export default function CurrencyList({
|
||||
return null
|
||||
}
|
||||
},
|
||||
[chainId, currencies.length, onCurrencySelect, otherCurrency, selectedCurrency, setImportToken, showImportView]
|
||||
[currencies.length, onCurrencySelect, otherCurrency, selectedCurrency, setImportToken, showImportView]
|
||||
)
|
||||
|
||||
const itemKey = useCallback((index: number, data: typeof itemData) => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Currency, ETHER, Token } from '@uniswap/sdk-core'
|
||||
import { Currency, Ether, Token } from '@uniswap/sdk-core'
|
||||
import React, { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
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'
|
||||
@@ -106,13 +106,15 @@ export function CurrencySearch({
|
||||
|
||||
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
|
||||
|
||||
const ether = useMemo(() => chainId && Ether.onChain(chainId), [chainId])
|
||||
|
||||
const filteredSortedTokensWithETH: Currency[] = useMemo(() => {
|
||||
const s = debouncedQuery.toLowerCase().trim()
|
||||
if (s === '' || s === 'e' || s === 'et' || s === 'eth') {
|
||||
return [ETHER, ...filteredSortedTokens]
|
||||
return ether ? [ether, ...filteredSortedTokens] : filteredSortedTokens
|
||||
}
|
||||
return filteredSortedTokens
|
||||
}, [debouncedQuery, filteredSortedTokens])
|
||||
}, [debouncedQuery, ether, filteredSortedTokens])
|
||||
|
||||
const handleCurrencySelect = useCallback(
|
||||
(currency: Currency) => {
|
||||
@@ -140,8 +142,8 @@ export function CurrencySearch({
|
||||
(e: KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
const s = debouncedQuery.toLowerCase().trim()
|
||||
if (s === 'eth') {
|
||||
handleCurrencySelect(ETHER)
|
||||
if (s === 'eth' && ether) {
|
||||
handleCurrencySelect(ether)
|
||||
} else if (filteredSortedTokensWithETH.length > 0) {
|
||||
if (
|
||||
filteredSortedTokensWithETH[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
|
||||
@@ -152,7 +154,7 @@ export function CurrencySearch({
|
||||
}
|
||||
}
|
||||
},
|
||||
[filteredSortedTokensWithETH, handleCurrencySelect, debouncedQuery]
|
||||
[debouncedQuery, ether, filteredSortedTokensWithETH, handleCurrencySelect]
|
||||
)
|
||||
|
||||
// menu ui
|
||||
|
||||
@@ -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 { 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`
|
||||
@@ -86,7 +86,7 @@ export function TransactionSubmittedContent({
|
||||
}: {
|
||||
onDismiss: () => void
|
||||
hash: string | undefined
|
||||
chainId: ChainId
|
||||
chainId: number
|
||||
currencyToAdd?: Currency | undefined
|
||||
inline?: boolean // not in modal
|
||||
}) {
|
||||
@@ -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%;
|
||||
|
||||
@@ -11,11 +11,11 @@ import { StakingInfo } from '../../state/stake/hooks'
|
||||
import { useColor } from '../../hooks/useColor'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { Break, CardNoise, CardBGImage } from './styled'
|
||||
import { unwrappedToken } from '../../utils/wrappedCurrency'
|
||||
import { unwrappedToken } from '../../utils/unwrappedToken'
|
||||
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;
|
||||
@@ -79,8 +79,8 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
|
||||
const isStaking = Boolean(stakingInfo.stakedAmount.greaterThan('0'))
|
||||
|
||||
// get the color of the token
|
||||
const token = currency0.isEther ? token1 : token0
|
||||
const WETH = currency0.isEther ? token0 : token1
|
||||
const token = currency0.isNative ? token1 : token0
|
||||
const WETH = currency0.isNative ? token0 : token1
|
||||
const backgroundColor = useColor(token)
|
||||
|
||||
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo.stakedAmount.currency)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import { V2_ROUTER_ADDRESS } from '../../constants'
|
||||
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import Modal from '../Modal'
|
||||
@@ -12,12 +11,11 @@ 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 { usePairContract, useStakingContract, useV2RouterContract } from '../../hooks/useContract'
|
||||
import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallback'
|
||||
import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
|
||||
import { wrappedCurrencyAmount } from '../../utils/wrappedCurrency'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { LoadingView, SubmittedView } from '../ModalViews'
|
||||
@@ -44,7 +42,7 @@ interface StakingModalProps {
|
||||
}
|
||||
|
||||
export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiquidityUnstaked }: StakingModalProps) {
|
||||
const { chainId, library } = useActiveWeb3React()
|
||||
const { library } = useActiveWeb3React()
|
||||
|
||||
// track and parse user input
|
||||
const [typedValue, setTypedValue] = useState('')
|
||||
@@ -53,7 +51,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
||||
stakingInfo.stakedAmount.currency,
|
||||
userLiquidityUnstaked
|
||||
)
|
||||
const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId)
|
||||
const parsedAmountWrapped = parsedAmount?.wrapped
|
||||
|
||||
let hypotheticalRewardRate: CurrencyAmount<Token> = CurrencyAmount.fromRawAmount(stakingInfo.rewardRate.currency, '0')
|
||||
if (parsedAmountWrapped?.greaterThan('0')) {
|
||||
@@ -83,7 +81,8 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
||||
|
||||
// approval data for stake
|
||||
const deadline = useTransactionDeadline()
|
||||
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(parsedAmountWrapped, V2_ROUTER_ADDRESS)
|
||||
const router = useV2RouterContract()
|
||||
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(parsedAmountWrapped, router?.address)
|
||||
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>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Currency, currencyEquals, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
@@ -21,9 +21,9 @@ function tradeMeaningfullyDiffers(
|
||||
const [tradeA, tradeB] = args
|
||||
return (
|
||||
tradeA.tradeType !== tradeB.tradeType ||
|
||||
!currencyEquals(tradeA.inputAmount.currency, tradeB.inputAmount.currency) ||
|
||||
!tradeA.inputAmount.currency.equals(tradeB.inputAmount.currency) ||
|
||||
!tradeA.inputAmount.equalTo(tradeB.inputAmount) ||
|
||||
!currencyEquals(tradeA.outputAmount.currency, tradeB.outputAmount.currency) ||
|
||||
!tradeA.outputAmount.currency.equals(tradeB.outputAmount.currency) ||
|
||||
!tradeA.outputAmount.equalTo(tradeB.outputAmount)
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ChevronRight } from 'react-feather'
|
||||
import { Flex } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { TYPE } from '../../theme'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
|
||||
function LabeledArrow({}: { fee: FeeAmount }) {
|
||||
const theme = useContext(ThemeContext)
|
||||
|
||||
@@ -7,11 +7,10 @@ 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);
|
||||
@@ -51,7 +50,7 @@ export default function UnsupportedCurrencyFooter({
|
||||
const tokens =
|
||||
chainId && currencies
|
||||
? currencies.map((currency) => {
|
||||
return wrappedCurrency(currency, chainId)
|
||||
return currency?.wrapped
|
||||
})
|
||||
: []
|
||||
|
||||
@@ -78,7 +77,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,15 +1,14 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { FortmaticConnector as FortmaticConnectorCore } from '@web3-react/fortmatic-connector'
|
||||
|
||||
export const OVERLAY_READY = 'OVERLAY_READY'
|
||||
|
||||
type FormaticSupportedChains = Extract<ChainId, ChainId.MAINNET | ChainId.ROPSTEN | ChainId.RINKEBY | ChainId.KOVAN>
|
||||
type FormaticSupportedChains = 1 | 3 | 4 | 42
|
||||
|
||||
const CHAIN_ID_NETWORK_ARGUMENT: { readonly [chainId in FormaticSupportedChains]: string | undefined } = {
|
||||
[ChainId.MAINNET]: undefined,
|
||||
[ChainId.ROPSTEN]: 'ropsten',
|
||||
[ChainId.RINKEBY]: 'rinkeby',
|
||||
[ChainId.KOVAN]: 'kovan',
|
||||
[1]: undefined,
|
||||
[3]: 'ropsten',
|
||||
[4]: 'rinkeby',
|
||||
[42]: 'kovan',
|
||||
}
|
||||
|
||||
export class FortmaticConnector extends FortmaticConnectorCore {
|
||||
|
||||
@@ -3,38 +3,50 @@ 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: number]: string
|
||||
} = {
|
||||
[1]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
|
||||
[4]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
|
||||
[3]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
|
||||
[5]: `https://goerli.infura.io/v3/${INFURA_KEY}`,
|
||||
[42]: `https://kovan.infura.io/v3/${INFURA_KEY}`,
|
||||
}
|
||||
|
||||
const SUPPORTED_CHAIN_IDS = [1, 4, 3, 42, 5]
|
||||
|
||||
export const network = new NetworkConnector({
|
||||
urls: { [NETWORK_CHAIN_ID]: NETWORK_URL },
|
||||
urls: NETWORK_URLS,
|
||||
defaultChainId: 1,
|
||||
})
|
||||
|
||||
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 +66,7 @@ export const portis = new PortisConnector({
|
||||
|
||||
// mainnet only
|
||||
export const walletlink = new WalletLinkConnector({
|
||||
url: NETWORK_URL,
|
||||
url: NETWORK_URLS[1],
|
||||
appName: 'Uniswap',
|
||||
appLogoUrl: UNISWAP_LOGO_URL,
|
||||
})
|
||||
|
||||
30
src/constants/addresses.ts
Normal file
30
src/constants/addresses.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
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: number]: string } = {
|
||||
[1]: '0x090D4613473dEE047c3f2706764f49E0821D256e',
|
||||
}
|
||||
export const ARGENT_WALLET_DETECTOR_ADDRESS: { [chainId: number]: string } = {
|
||||
[1]: '0xeca4B0bDBf7c55E9b7925919d03CbF8Dc82537E8',
|
||||
}
|
||||
export const V3_CORE_FACTORY_ADDRESSES = constructSameAddressMap(V3_FACTORY_ADDRESS)
|
||||
export const QUOTER_ADDRESSES = constructSameAddressMap('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')
|
||||
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = constructSameAddressMap(
|
||||
'0xC36442b4a4522E871399CD717aBDD847Ab11FE88'
|
||||
)
|
||||
export const ENS_REGISTRAR_ADDRESSES = {
|
||||
[1]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
[5]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
[4]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
[3]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
}
|
||||
export const SOCKS_CONTROLLER_ADDRESSES = {
|
||||
[1]: '0x65770b5283117639760beA3F867b69b3697a91dd',
|
||||
}
|
||||
export const SWAP_ROUTER_ADDRESSES = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564')
|
||||
export const V3_MIGRATOR_ADDRESSES = constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34')
|
||||
36
src/constants/governance.ts
Normal file
36
src/constants/governance.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { GOVERNANCE_ADDRESS, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses'
|
||||
|
||||
export const COMMON_CONTRACT_NAMES: { [chainId: number]: { [address: string]: string } } = {
|
||||
[1]: {
|
||||
[UNI_ADDRESS[1]]: 'UNI',
|
||||
[GOVERNANCE_ADDRESS[1]]: 'Governance',
|
||||
[TIMELOCK_ADDRESS[1]]: 'Timelock',
|
||||
},
|
||||
[4]: {
|
||||
[UNI_ADDRESS[4]]: 'Rinkeby UNI',
|
||||
[GOVERNANCE_ADDRESS[4]]: 'Rinkeby Governance',
|
||||
[TIMELOCK_ADDRESS[4]]: 'Rinkeby Timelock',
|
||||
},
|
||||
[3]: {
|
||||
[UNI_ADDRESS[3]]: 'Ropsten UNI',
|
||||
[GOVERNANCE_ADDRESS[3]]: 'Ropsten Governance',
|
||||
[TIMELOCK_ADDRESS[3]]: 'Ropsten Timelock',
|
||||
},
|
||||
[42]: {
|
||||
[UNI_ADDRESS[42]]: 'Kovan UNI',
|
||||
[GOVERNANCE_ADDRESS[42]]: 'Kovan Governance',
|
||||
[TIMELOCK_ADDRESS[42]]: 'Kovan Timelock',
|
||||
},
|
||||
[5]: {
|
||||
[UNI_ADDRESS[5]]: 'Goerli UNI',
|
||||
[GOVERNANCE_ADDRESS[5]]: 'Goerli Governance',
|
||||
[TIMELOCK_ADDRESS[5]]: '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: number]: number } = {
|
||||
[1]: 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)*
|
||||
|
||||
95
src/constants/routing.ts
Normal file
95
src/constants/routing.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
// a list of tokens by chain
|
||||
import { Currency, Ether, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import { AMPL, DAI, ETH2X_FLI, FEI, FRAX, FXS, MIR, renBTC, TRIBE, UMA, UNI, USDC, USDT, UST, WBTC } from './tokens'
|
||||
|
||||
type ChainTokenList = {
|
||||
readonly [chainId: number]: Token[]
|
||||
}
|
||||
|
||||
type ChainCurrencyList = {
|
||||
readonly [chainId: number]: Currency[]
|
||||
}
|
||||
|
||||
// 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 = {
|
||||
[1]: [WETH9[1]],
|
||||
[3]: [WETH9[3]],
|
||||
[4]: [WETH9[4]],
|
||||
[5]: [WETH9[5]],
|
||||
[42]: [WETH9[42]],
|
||||
}
|
||||
// used to construct intermediary pairs for trading
|
||||
export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
|
||||
...WETH_ONLY,
|
||||
[1]: [...WETH_ONLY[1], DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = {
|
||||
[1]: {
|
||||
...mAssetsAdditionalBases,
|
||||
'0xF16E4d813f4DcfDe4c5b44f305c908742De84eF0': [ETH2X_FLI],
|
||||
'0xA948E86885e12Fb09AfEF8C52142EBDbDf73cD18': [UNI[1]],
|
||||
'0x561a4717537ff4AF5c687328c0f7E90a319705C0': [UNI[1]],
|
||||
'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: number]: { [tokenAddress: string]: Token[] } } = {
|
||||
[1]: {
|
||||
[AMPL.address]: [DAI, WETH9[1]],
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows up in the currency select for swap and add liquidity
|
||||
*/
|
||||
export const COMMON_BASES: ChainCurrencyList = {
|
||||
[1]: [Ether.onChain(1), DAI, USDC, USDT, WBTC, WETH9[1]],
|
||||
[3]: [Ether.onChain(3), WETH9[3]],
|
||||
[4]: [Ether.onChain(4), WETH9[4]],
|
||||
[5]: [Ether.onChain(5), WETH9[5]],
|
||||
[42]: [Ether.onChain(42), WETH9[42]],
|
||||
}
|
||||
|
||||
// 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,
|
||||
[1]: [...WETH_ONLY[1], DAI, USDC, USDT, WBTC],
|
||||
}
|
||||
export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = {
|
||||
[1]: [
|
||||
[
|
||||
new Token(1, '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', 8, 'cDAI', 'Compound Dai'),
|
||||
new Token(1, '0x39AA39c021dfbaE8faC545936693aC917d5E7563', 8, 'cUSDC', 'Compound USD Coin'),
|
||||
],
|
||||
[USDC, USDT],
|
||||
[DAI, USDT],
|
||||
],
|
||||
}
|
||||
31
src/constants/tokens.ts
Normal file
31
src/constants/tokens.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import { UNI_ADDRESS } from './addresses'
|
||||
|
||||
export const AMPL = new Token(1, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
||||
export const DAI = new Token(1, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
||||
export const USDC = new Token(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C')
|
||||
export const USDT = new Token(1, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD')
|
||||
export const WBTC = new Token(1, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC')
|
||||
export const FEI = new Token(1, '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', 18, 'FEI', 'Fei USD')
|
||||
export const TRIBE = new Token(1, '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', 18, 'TRIBE', 'Tribe')
|
||||
export const FRAX = new Token(1, '0x853d955aCEf822Db058eb8505911ED77F175b99e', 18, 'FRAX', 'Frax')
|
||||
export const FXS = new Token(1, '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', 18, 'FXS', 'Frax Share')
|
||||
export const renBTC = new Token(1, '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', 8, 'renBTC', 'renBTC')
|
||||
export const UMA = new Token(1, '0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828', 18, 'UMA', 'UMA Voting Token v1')
|
||||
export const ETH2X_FLI = new Token(
|
||||
1,
|
||||
'0xAa6E8127831c9DE45ae56bB1b0d4D4Da6e5665BD',
|
||||
18,
|
||||
'ETH2x-FLI',
|
||||
'ETH 2x Flexible Leverage Index'
|
||||
)
|
||||
// Mirror Protocol compat.
|
||||
export const UST = new Token(1, '0xa47c8bf37f92abed4a126bda807a7b7498661acd', 18, 'UST', 'Wrapped UST')
|
||||
export const MIR = new Token(1, '0x09a3ecafa817268f77be1283176b946c4ff2e608', 18, 'MIR', 'Wrapped MIR')
|
||||
export const UNI: { [chainId: number]: Token } = {
|
||||
[1]: new Token(1, UNI_ADDRESS[1], 18, 'UNI', 'Uniswap'),
|
||||
[4]: new Token(4, UNI_ADDRESS[4], 18, 'UNI', 'Uniswap'),
|
||||
[3]: new Token(3, UNI_ADDRESS[3], 18, 'UNI', 'Uniswap'),
|
||||
[5]: new Token(5, UNI_ADDRESS[5], 18, 'UNI', 'Uniswap'),
|
||||
[42]: new Token(42, UNI_ADDRESS[42], 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,
|
||||
},
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parseBytes32String } from '@ethersproject/strings'
|
||||
import { Currency, currencyEquals, ETHER, Token } from '@uniswap/sdk-core'
|
||||
import { Currency, Ether, Token } from '@uniswap/sdk-core'
|
||||
import { arrayify } from 'ethers/lib/utils'
|
||||
import { useMemo } from 'react'
|
||||
import { createTokenFilterFunction } from '../components/SearchModal/filtering'
|
||||
@@ -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
|
||||
@@ -103,7 +103,7 @@ export function useIsUserAddedToken(currency: Currency | undefined | null): bool
|
||||
return false
|
||||
}
|
||||
|
||||
return !!userAddedTokens.find((token) => currencyEquals(currency, token))
|
||||
return !!userAddedTokens.find((token) => currency.equals(token))
|
||||
}
|
||||
|
||||
// parse a name or symbol from a token response
|
||||
@@ -172,7 +172,8 @@ export function useToken(tokenAddress?: string): Token | undefined | null {
|
||||
}
|
||||
|
||||
export function useCurrency(currencyId: string | undefined): Currency | null | undefined {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const isETH = currencyId?.toUpperCase() === 'ETH'
|
||||
const token = useToken(isETH ? undefined : currencyId)
|
||||
return isETH ? ETHER : token
|
||||
return isETH ? (chainId ? Ether.onChain(chainId) : undefined) : token
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
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
|
||||
): { addToken: () => void; success: boolean | undefined } {
|
||||
const { library, chainId } = useActiveWeb3React()
|
||||
export default function useAddTokenToMetamask(currencyToAdd: Currency | undefined): {
|
||||
addToken: () => void
|
||||
success: boolean | undefined
|
||||
} {
|
||||
const { library } = useActiveWeb3React()
|
||||
|
||||
const token: Token | undefined = wrappedCurrency(currencyToAdd, chainId)
|
||||
const token: Token | undefined = currencyToAdd?.wrapped
|
||||
|
||||
const [success, setSuccess] = useState<boolean | undefined>()
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
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 { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants/routing'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
|
||||
export function useAllCurrencyCombinations(currencyA?: Currency, currencyB?: Currency): [Token, Token][] {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
const [tokenA, tokenB] = chainId
|
||||
? [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
|
||||
: [undefined, undefined]
|
||||
const [tokenA, tokenB] = chainId ? [currencyA?.wrapped, currencyB?.wrapped] : [undefined, undefined]
|
||||
|
||||
const bases: Token[] = useMemo(() => {
|
||||
if (!chainId) return []
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
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(
|
||||
currencyIn: Currency,
|
||||
currencyOut: Currency,
|
||||
pools: Pool[],
|
||||
chainId: ChainId,
|
||||
chainId: number,
|
||||
currentPath: Pool[] = [],
|
||||
allPaths: Route<Currency, Currency>[] = [],
|
||||
startCurrencyIn: Currency = currencyIn,
|
||||
maxHops = 2
|
||||
): Route<Currency, Currency>[] {
|
||||
const tokenIn = wrappedCurrency(currencyIn, chainId)
|
||||
const tokenOut = wrappedCurrency(currencyOut, chainId)
|
||||
const tokenIn = currencyIn?.wrapped
|
||||
const tokenOut = currencyOut?.wrapped
|
||||
if (!tokenIn || !tokenOut) throw new Error('Missing tokenIn/tokenOut')
|
||||
|
||||
for (const pool of pools) {
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
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 { useEffect, useMemo, useState } from 'react'
|
||||
import { Result, useSingleCallResult, useSingleContractMultipleData } from 'state/multicall/hooks'
|
||||
import { useTickLens, useV3Factory } from './useContract'
|
||||
|
||||
function bitmapIndex(tick: number, tickSpacing: number) {
|
||||
return Math.floor(tick / tickSpacing / 256)
|
||||
}
|
||||
|
||||
const REFRESH_FREQUENCY = { blocksPerFetch: 2 }
|
||||
|
||||
interface TickData {
|
||||
tick: number
|
||||
liquidityNet: number
|
||||
liquidityGross: number
|
||||
}
|
||||
|
||||
// for now, reconsider using this function, it consumes a lot of data and cpu to fetch all the ticks.
|
||||
export function useAllV3Ticks(
|
||||
token0: Token | undefined,
|
||||
token1: Token | undefined,
|
||||
feeAmount: FeeAmount | undefined
|
||||
): {
|
||||
loading: boolean
|
||||
syncing: boolean
|
||||
error: boolean
|
||||
valid: boolean
|
||||
tickData: TickData[]
|
||||
} {
|
||||
const tickSpacing = feeAmount && TICK_SPACINGS[feeAmount]
|
||||
|
||||
const minIndex = useMemo(
|
||||
() => (tickSpacing ? bitmapIndex(nearestUsableTick(TickMath.MIN_TICK, tickSpacing), tickSpacing) : undefined),
|
||||
[tickSpacing]
|
||||
)
|
||||
const maxIndex = useMemo(
|
||||
() => (tickSpacing ? bitmapIndex(nearestUsableTick(TickMath.MAX_TICK, tickSpacing), tickSpacing) : undefined),
|
||||
[tickSpacing]
|
||||
)
|
||||
|
||||
const [tickDataLatestSynced, setTickDataLatestSynced] = useState<TickData[]>([])
|
||||
|
||||
// fetch the pool address
|
||||
const factoryContract = useV3Factory()
|
||||
const poolAddress = useSingleCallResult(factoryContract, 'getPool', [token0?.address, token1?.address, feeAmount])
|
||||
.result?.[0]
|
||||
|
||||
const tickLensArgs: [string, number][] = useMemo(
|
||||
() =>
|
||||
maxIndex && minIndex && poolAddress && poolAddress !== ZERO_ADDRESS
|
||||
? new Array(maxIndex - minIndex + 1)
|
||||
.fill(0)
|
||||
.map((_, i) => i + minIndex)
|
||||
.map((wordIndex) => [poolAddress, wordIndex])
|
||||
: [],
|
||||
[minIndex, maxIndex, poolAddress]
|
||||
)
|
||||
|
||||
const tickLens = useTickLens()
|
||||
const callStates = useSingleContractMultipleData(
|
||||
tickLensArgs.length > 0 ? tickLens : undefined,
|
||||
'getPopulatedTicksInWord',
|
||||
tickLensArgs,
|
||||
REFRESH_FREQUENCY,
|
||||
3_000_000
|
||||
)
|
||||
|
||||
const error = useMemo(() => callStates.some(({ error }) => error), [callStates])
|
||||
const loading = useMemo(() => callStates.some(({ loading }) => loading), [callStates])
|
||||
const syncing = useMemo(() => callStates.some(({ syncing }) => syncing), [callStates])
|
||||
const valid = useMemo(() => callStates.some(({ valid }) => valid), [callStates])
|
||||
|
||||
const tickData = useMemo(
|
||||
() =>
|
||||
callStates
|
||||
.map(({ result }) => (result as Result)?.populatedTicks)
|
||||
.reduce(
|
||||
(accumulator, current) => [
|
||||
...accumulator,
|
||||
...(current?.map((tickData: TickData) => {
|
||||
return {
|
||||
tick: tickData.tick,
|
||||
liquidityNet: tickData.liquidityNet,
|
||||
liquidityGross: tickData.liquidityGross,
|
||||
}
|
||||
}) ?? []),
|
||||
],
|
||||
[]
|
||||
),
|
||||
[callStates]
|
||||
)
|
||||
|
||||
// return the latest synced tickdata even if we are still loading the newest data
|
||||
useEffect(() => {
|
||||
if (!syncing && !loading && !error && valid) {
|
||||
setTickDataLatestSynced(tickData)
|
||||
}
|
||||
}, [error, loading, syncing, tickData, valid])
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
loading,
|
||||
syncing,
|
||||
error,
|
||||
valid,
|
||||
tickData: tickDataLatestSynced,
|
||||
}),
|
||||
[loading, syncing, error, valid, tickDataLatestSynced]
|
||||
)
|
||||
}
|
||||
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 }))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
import { MaxUint256 } from '@ethersproject/constants'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { CurrencyAmount, ChainId, Percent, Currency, TradeType } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Percent, Currency, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
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 {
|
||||
@@ -32,7 +31,7 @@ export function useApproveCallback(
|
||||
// check the current approval status
|
||||
const approvalState: ApprovalState = useMemo(() => {
|
||||
if (!amountToApprove || !spender) return ApprovalState.UNKNOWN
|
||||
if (amountToApprove.currency.isEther) return ApprovalState.APPROVED
|
||||
if (amountToApprove.currency.isNative) return ApprovalState.APPROVED
|
||||
// we might not have enough data to know whether or not we need to approve
|
||||
if (!currentAllowance) return ApprovalState.UNKNOWN
|
||||
|
||||
@@ -104,13 +103,19 @@ export function useApproveCallbackFromTrade(
|
||||
allowedSlippage: Percent
|
||||
) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
|
||||
const v3SwapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
15
src/hooks/useArgentWalletContract.ts
Normal file
15
src/hooks/useArgentWalletContract.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ArgentWalletContract } from '../abis/types'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useContract } from './useContract'
|
||||
import useIsArgentWallet from './useIsArgentWallet'
|
||||
import ArgentWalletContractABI from '../abis/argent-wallet-contract.json'
|
||||
|
||||
export function useArgentWalletContract(): ArgentWalletContract | null {
|
||||
const { account } = useActiveWeb3React()
|
||||
const isArgentWallet = useIsArgentWallet()
|
||||
return useContract(
|
||||
isArgentWallet ? account ?? undefined : undefined,
|
||||
ArgentWalletContractABI,
|
||||
true
|
||||
) as ArgentWalletContract
|
||||
}
|
||||
@@ -2,11 +2,11 @@ import { useState, useLayoutEffect } from 'react'
|
||||
import { shade } from 'polished'
|
||||
import Vibrant from 'node-vibrant'
|
||||
import { hex } from 'wcag-contrast'
|
||||
import { Token, ChainId } from '@uniswap/sdk-core'
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import uriToHttp from 'utils/uriToHttp'
|
||||
|
||||
async function getColorFromToken(token: Token): Promise<string | null> {
|
||||
if (token.chainId !== ChainId.MAINNET) {
|
||||
if (token.chainId !== 1) {
|
||||
return Promise.resolve('#FAAB14')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import { ChainId, WETH9 } from '@uniswap/sdk-core'
|
||||
import { WETH9 } from '@uniswap/sdk-core'
|
||||
import { abi as GOVERNANCE_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
|
||||
import { abi as UNI_ABI } from '@uniswap/governance/build/Uni.json'
|
||||
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
|
||||
@@ -9,7 +9,6 @@ import { abi as V3FactoryABI } from '@uniswap/v3-core/artifacts/contracts/Uniswa
|
||||
import { abi as V3PoolABI } from '@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json'
|
||||
import { abi as QuoterABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json'
|
||||
import { abi as V2MigratorABI } from '@uniswap/v3-periphery/artifacts/contracts/V3Migrator.sol/V3Migrator.json'
|
||||
import { abi as TickLensABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/TickLens.sol/TickLens.json'
|
||||
import { abi as IUniswapV2Router02ABI } from '@uniswap/v2-periphery/build/IUniswapV2Router02.json'
|
||||
|
||||
import ARGENT_WALLET_DETECTOR_ABI from 'abis/argent-wallet-detector.json'
|
||||
@@ -17,7 +16,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 +23,74 @@ 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,
|
||||
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 { Quoter, 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 { Erc20, ArgentWalletDetector, EnsPublicResolver, EnsRegistrar, 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: number]: 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 +109,47 @@ 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 useTickLens(): TickLens | null {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const address = chainId ? TICK_LENS_ADDRESSES[chainId] : undefined
|
||||
return useContract(address, TickLensABI) as TickLens | null
|
||||
export function useV3Quoter() {
|
||||
return useContract<Quoter>(QUOTER_ADDRESSES, QuoterABI)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ import { usePool } from 'hooks/usePools'
|
||||
import { PositionDetails } from 'types/position'
|
||||
import { useCurrency } from './Tokens'
|
||||
|
||||
export function useDerivedPositionInfo(
|
||||
positionDetails: PositionDetails | undefined
|
||||
): {
|
||||
export function useDerivedPositionInfo(positionDetails: PositionDetails | undefined): {
|
||||
position: Position | undefined
|
||||
pool: Pool | undefined
|
||||
} {
|
||||
|
||||
@@ -6,9 +6,11 @@ import useENSName from './useENSName'
|
||||
* Given a name or address, does a lookup to resolve to an address and name
|
||||
* @param nameOrAddress ENS name or address
|
||||
*/
|
||||
export default function useENS(
|
||||
nameOrAddress?: string | null
|
||||
): { loading: boolean; address: string | null; name: string | null } {
|
||||
export default function useENS(nameOrAddress?: string | null): {
|
||||
loading: boolean
|
||||
address: string | null
|
||||
name: string | null
|
||||
} {
|
||||
const validated = isAddress(nameOrAddress)
|
||||
const reverseLookup = useENSName(validated ? validated : undefined)
|
||||
const lookup = useENSAddress(nameOrAddress)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import JSBI from 'jsbi'
|
||||
import { ChainId, Percent, CurrencyAmount, Currency, TradeType, Token } from '@uniswap/sdk-core'
|
||||
import { Percent, CurrencyAmount, Currency, TradeType, Token } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { splitSignature } from 'ethers/lib/utils'
|
||||
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'
|
||||
@@ -29,28 +29,28 @@ interface PermitInfo {
|
||||
|
||||
// todo: read this information from extensions on token lists or elsewhere (permit registry?)
|
||||
const PERMITTABLE_TOKENS: {
|
||||
[chainId in ChainId]: {
|
||||
[chainId: number]: {
|
||||
[checksummedTokenAddress: string]: PermitInfo
|
||||
}
|
||||
} = {
|
||||
[ChainId.MAINNET]: {
|
||||
[1]: {
|
||||
[USDC.address]: { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
|
||||
[DAI.address]: { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
|
||||
[UNI[ChainId.MAINNET].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
[UNI[1].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
},
|
||||
[ChainId.RINKEBY]: {
|
||||
[4]: {
|
||||
['0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735']: { type: PermitType.ALLOWED, name: 'Dai Stablecoin', version: '1' },
|
||||
[UNI[ChainId.RINKEBY].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
[UNI[4].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
},
|
||||
[ChainId.ROPSTEN]: {
|
||||
[UNI[ChainId.ROPSTEN].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
[3]: {
|
||||
[UNI[3].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
['0x07865c6E87B9F70255377e024ace6630C1Eaa37F']: { type: PermitType.AMOUNT, name: 'USD Coin', version: '2' },
|
||||
},
|
||||
[ChainId.GÖRLI]: {
|
||||
[UNI[ChainId.GÖRLI].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
[5]: {
|
||||
[UNI[5].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
},
|
||||
[ChainId.KOVAN]: {
|
||||
[UNI[ChainId.KOVAN].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
[42]: {
|
||||
[UNI[42].address]: { type: PermitType.AMOUNT, name: 'Uniswap' },
|
||||
},
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ interface BaseSignatureData {
|
||||
nonce: number
|
||||
owner: string
|
||||
spender: string
|
||||
chainId: ChainId | number
|
||||
chainId: number
|
||||
tokenAddress: string
|
||||
permitType: PermitType
|
||||
}
|
||||
@@ -275,11 +275,11 @@ export function useERC20PermitFromTrade(
|
||||
allowedSlippage: Percent
|
||||
) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
|
||||
const amountToApprove = useMemo(() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined), [
|
||||
trade,
|
||||
allowedSlippage,
|
||||
])
|
||||
const swapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
|
||||
const amountToApprove = useMemo(
|
||||
() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined),
|
||||
[trade, allowedSlippage]
|
||||
)
|
||||
|
||||
return useERC20Permit(
|
||||
amountToApprove,
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import { nanoid } from '@reduxjs/toolkit'
|
||||
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) => {
|
||||
if (!library || chainId !== ChainId.MAINNET) {
|
||||
if (NETWORK_CHAIN_ID === ChainId.MAINNET) {
|
||||
const networkLibrary = getNetworkLibrary()
|
||||
if (networkLibrary) {
|
||||
return resolveENSContentHash(ensName, networkLibrary)
|
||||
}
|
||||
async (ensName: string) => {
|
||||
if (!library || chainId !== 1) {
|
||||
const networkLibrary = getNetworkLibrary()
|
||||
const network = await networkLibrary.getNetwork()
|
||||
if (networkLibrary && network.chainId === 1) {
|
||||
return resolveENSContentHash(ensName, networkLibrary)
|
||||
}
|
||||
throw new Error('Could not construct mainnet ENS resolver')
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useMemo } from 'react'
|
||||
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 {
|
||||
const { account } = useActiveWeb3React()
|
||||
const argentWalletDetector = useArgentWalletDetectorContract()
|
||||
const call = useSingleCallResult(argentWalletDetector, 'isArgentWallet', [account ?? undefined], NEVER_RELOAD)
|
||||
const inputs = useMemo(() => [account ?? undefined], [account])
|
||||
const call = useSingleCallResult(argentWalletDetector, 'isArgentWallet', inputs, NEVER_RELOAD)
|
||||
return call?.result?.[0] ?? false
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -28,8 +28,8 @@ export function usePools(
|
||||
return poolKeys.map(([currencyA, currencyB, feeAmount]) => {
|
||||
if (!chainId || !currencyA || !currencyB || !feeAmount) return null
|
||||
|
||||
const tokenA = wrappedCurrency(currencyA, chainId)
|
||||
const tokenB = wrappedCurrency(currencyB, chainId)
|
||||
const tokenA = currencyA?.wrapped
|
||||
const tokenB = currencyB?.wrapped
|
||||
if (!tokenA || !tokenB || tokenA.equals(tokenB)) return null
|
||||
const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
|
||||
return [token0, token1, feeAmount]
|
||||
|
||||
@@ -29,9 +29,10 @@ type UsePositionTokenURIResult =
|
||||
|
||||
export function usePositionTokenURI(tokenId: TokenId | undefined): UsePositionTokenURIResult {
|
||||
const contract = useV3NFTPositionManagerContract()
|
||||
const inputs = useMemo(() => [tokenId instanceof BigNumber ? tokenId.toHexString() : tokenId?.toString(16)], [
|
||||
tokenId,
|
||||
])
|
||||
const inputs = useMemo(
|
||||
() => [tokenId instanceof BigNumber ? tokenId.toHexString() : tokenId?.toString(16)],
|
||||
[tokenId]
|
||||
)
|
||||
const { result, error, loading, valid } = useSingleCallResult(contract, 'tokenURI', inputs, NEVER_RELOAD, 1_600_000)
|
||||
|
||||
return useMemo(() => {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
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 {
|
||||
const { account } = useActiveWeb3React()
|
||||
const socksContract = useSocksController()
|
||||
|
||||
const { result } = useSingleCallResult(socksContract, 'balanceOf', [account ?? undefined], NEVER_RELOAD)
|
||||
const inputs = useMemo(() => [account ?? undefined], [account])
|
||||
const { result } = useSingleCallResult(socksContract, 'balanceOf', inputs, NEVER_RELOAD)
|
||||
const data = result?.[0]
|
||||
return data ? JSBI.BigInt(data.toString()) : undefined
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Router, Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { ChainId, Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { 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 approveAmountCalldata from '../utils/approveAmountCalldata'
|
||||
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 { useArgentWalletContract } from './useArgentWalletContract'
|
||||
import { useV2RouterContract } from './useContract'
|
||||
import { SignatureData } from './useERC20Permit'
|
||||
import useTransactionDeadline from './useTransactionDeadline'
|
||||
@@ -60,6 +63,7 @@ function useSwapCallArguments(
|
||||
const recipient = recipientAddressOrName === null ? account : recipientAddress
|
||||
const deadline = useTransactionDeadline()
|
||||
const routerContract = useV2RouterContract()
|
||||
const argentWalletContract = useArgentWalletContract()
|
||||
|
||||
return useMemo(() => {
|
||||
if (!trade || !recipient || !library || !account || !chainId || !deadline) return []
|
||||
@@ -67,6 +71,7 @@ function useSwapCallArguments(
|
||||
if (trade instanceof V2Trade) {
|
||||
if (!routerContract) return []
|
||||
const swapMethods = []
|
||||
|
||||
swapMethods.push(
|
||||
Router.swapCallParameters(trade, {
|
||||
feeOnTransfer: false,
|
||||
@@ -86,14 +91,33 @@ function useSwapCallArguments(
|
||||
})
|
||||
)
|
||||
}
|
||||
return swapMethods.map(({ methodName, args, value }) => ({
|
||||
address: routerContract.address,
|
||||
calldata: routerContract.interface.encodeFunctionData(methodName, args),
|
||||
value,
|
||||
}))
|
||||
return swapMethods.map(({ methodName, args, value }) => {
|
||||
if (argentWalletContract && trade.inputAmount.currency.isToken) {
|
||||
return {
|
||||
address: argentWalletContract.address,
|
||||
calldata: argentWalletContract.interface.encodeFunctionData('wc_multiCall', [
|
||||
[
|
||||
approveAmountCalldata(trade.maximumAmountIn(allowedSlippage), routerContract.address),
|
||||
{
|
||||
to: routerContract.address,
|
||||
value: value,
|
||||
data: routerContract.interface.encodeFunctionData(methodName, args),
|
||||
},
|
||||
],
|
||||
]),
|
||||
value: '0x0',
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
address: routerContract.address,
|
||||
calldata: routerContract.interface.encodeFunctionData(methodName, args),
|
||||
value,
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// trade is V3Trade
|
||||
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
|
||||
const swapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
|
||||
if (!swapRouterAddress) return []
|
||||
|
||||
const { value, calldata } = SwapRouter.swapCallParameters(trade, {
|
||||
@@ -121,7 +145,24 @@ function useSwapCallArguments(
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
|
||||
if (argentWalletContract && trade.inputAmount.currency.isToken) {
|
||||
return [
|
||||
{
|
||||
address: argentWalletContract.address,
|
||||
calldata: argentWalletContract.interface.encodeFunctionData('wc_multiCall', [
|
||||
[
|
||||
approveAmountCalldata(trade.maximumAmountIn(allowedSlippage), swapRouterAddress),
|
||||
{
|
||||
to: swapRouterAddress,
|
||||
value: value,
|
||||
data: calldata,
|
||||
},
|
||||
],
|
||||
]),
|
||||
value: '0x0',
|
||||
},
|
||||
]
|
||||
}
|
||||
return [
|
||||
{
|
||||
address: swapRouterAddress,
|
||||
@@ -130,7 +171,18 @@ function useSwapCallArguments(
|
||||
},
|
||||
]
|
||||
}
|
||||
}, [account, allowedSlippage, chainId, deadline, library, recipient, routerContract, signatureData, trade])
|
||||
}, [
|
||||
account,
|
||||
allowedSlippage,
|
||||
argentWalletContract,
|
||||
chainId,
|
||||
deadline,
|
||||
library,
|
||||
recipient,
|
||||
routerContract,
|
||||
signatureData,
|
||||
trade,
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,16 +205,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 +333,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 +364,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
|
||||
}
|
||||
@@ -9,8 +9,8 @@ export function useTokenAllowance(token?: Token, owner?: string, spender?: strin
|
||||
const inputs = useMemo(() => [owner, spender], [owner, spender])
|
||||
const allowance = useSingleCallResult(contract, 'allowance', inputs).result
|
||||
|
||||
return useMemo(() => (token && allowance ? CurrencyAmount.fromRawAmount(token, allowance.toString()) : undefined), [
|
||||
token,
|
||||
allowance,
|
||||
])
|
||||
return useMemo(
|
||||
() => (token && allowance ? CurrencyAmount.fromRawAmount(token, allowance.toString()) : undefined),
|
||||
[token, allowance]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { ChainId, Currency, CurrencyAmount, currencyEquals, Price, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { 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, 100_000e6)
|
||||
|
||||
/**
|
||||
* Returns the price in USDC of the input currency
|
||||
@@ -12,25 +15,19 @@ 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 === 1 ? usdcCurrencyAmount : undefined, {
|
||||
maxHops: 2,
|
||||
})
|
||||
const v3USDCTrade = useBestV3TradeExactOut(currency, chainId === 1 ? 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) {
|
||||
if (chainId !== 1) {
|
||||
const fakeUSDC = new Token(chainId, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'fUSDC', 'Fake USDC')
|
||||
return new Price(
|
||||
currency,
|
||||
@@ -40,40 +37,22 @@ 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)) {
|
||||
if (currency?.wrapped.equals(USDC)) {
|
||||
return new Price(USDC, USDC, '1', '1')
|
||||
}
|
||||
|
||||
const ethPairETHAmount = ethPair?.reserveOf(weth)
|
||||
const ethPairETHUSDCValue: JSBI =
|
||||
ethPairETHAmount && usdcEthPair ? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).quotient : JSBI.BigInt(0)
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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 +60,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,9 +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 { useMultipleContractSingleData } from '../state/multicall/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
|
||||
const PAIR_INTERFACE = new Interface(IUniswapV2PairABI)
|
||||
@@ -17,15 +15,9 @@ export enum PairState {
|
||||
}
|
||||
|
||||
export function useV2Pairs(currencies: [Currency | undefined, Currency | undefined][]): [PairState, Pair | null][] {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
const tokens = useMemo(
|
||||
() =>
|
||||
currencies.map(([currencyA, currencyB]) => [
|
||||
wrappedCurrency(currencyA, chainId),
|
||||
wrappedCurrency(currencyB, chainId),
|
||||
]),
|
||||
[chainId, currencies]
|
||||
() => currencies.map(([currencyA, currencyB]) => [currencyA?.wrapped, currencyB?.wrapped]),
|
||||
[currencies]
|
||||
)
|
||||
|
||||
const pairAddresses = useMemo(
|
||||
@@ -61,5 +53,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]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { Pair, Trade } from '@uniswap/v2-sdk'
|
||||
import { useMemo } from 'react'
|
||||
import { useUserSingleHopOnly } from 'state/user/hooks'
|
||||
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'
|
||||
|
||||
@@ -36,15 +35,14 @@ const MAX_HOPS = 3
|
||||
*/
|
||||
export function useV2TradeExactIn(
|
||||
currencyAmountIn?: CurrencyAmount<Currency>,
|
||||
currencyOut?: Currency
|
||||
currencyOut?: Currency,
|
||||
{ maxHops = MAX_HOPS } = {}
|
||||
): Trade<Currency, Currency, TradeType.EXACT_INPUT> | null {
|
||||
const allowedPairs = useAllCommonPairs(currencyAmountIn?.currency, currencyOut)
|
||||
|
||||
const [singleHopOnly] = useUserSingleHopOnly()
|
||||
|
||||
return useMemo(() => {
|
||||
if (currencyAmountIn && currencyOut && allowedPairs.length > 0) {
|
||||
if (singleHopOnly) {
|
||||
if (maxHops === 1) {
|
||||
return (
|
||||
Trade.bestTradeExactIn(allowedPairs, currencyAmountIn, currencyOut, { maxHops: 1, maxNumResults: 1 })[0] ??
|
||||
null
|
||||
@@ -52,7 +50,7 @@ export function useV2TradeExactIn(
|
||||
}
|
||||
// search through trades with varying hops, find best trade out of them
|
||||
let bestTradeSoFar: Trade<Currency, Currency, TradeType.EXACT_INPUT> | null = null
|
||||
for (let i = 1; i <= MAX_HOPS; i++) {
|
||||
for (let i = 1; i <= maxHops; i++) {
|
||||
const currentTrade: Trade<Currency, Currency, TradeType.EXACT_INPUT> | null =
|
||||
Trade.bestTradeExactIn(allowedPairs, currencyAmountIn, currencyOut, { maxHops: i, maxNumResults: 1 })[0] ??
|
||||
null
|
||||
@@ -65,7 +63,7 @@ export function useV2TradeExactIn(
|
||||
}
|
||||
|
||||
return null
|
||||
}, [allowedPairs, currencyAmountIn, currencyOut, singleHopOnly])
|
||||
}, [allowedPairs, currencyAmountIn, currencyOut, maxHops])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,15 +71,14 @@ export function useV2TradeExactIn(
|
||||
*/
|
||||
export function useV2TradeExactOut(
|
||||
currencyIn?: Currency,
|
||||
currencyAmountOut?: CurrencyAmount<Currency>
|
||||
currencyAmountOut?: CurrencyAmount<Currency>,
|
||||
{ maxHops = MAX_HOPS } = {}
|
||||
): Trade<Currency, Currency, TradeType.EXACT_OUTPUT> | null {
|
||||
const allowedPairs = useAllCommonPairs(currencyIn, currencyAmountOut?.currency)
|
||||
|
||||
const [singleHopOnly] = useUserSingleHopOnly()
|
||||
|
||||
return useMemo(() => {
|
||||
if (currencyIn && currencyAmountOut && allowedPairs.length > 0) {
|
||||
if (singleHopOnly) {
|
||||
if (maxHops === 1) {
|
||||
return (
|
||||
Trade.bestTradeExactOut(allowedPairs, currencyIn, currencyAmountOut, { maxHops: 1, maxNumResults: 1 })[0] ??
|
||||
null
|
||||
@@ -89,7 +86,7 @@ export function useV2TradeExactOut(
|
||||
}
|
||||
// search through trades with varying hops, find best trade out of them
|
||||
let bestTradeSoFar: Trade<Currency, Currency, TradeType.EXACT_OUTPUT> | null = null
|
||||
for (let i = 1; i <= MAX_HOPS; i++) {
|
||||
for (let i = 1; i <= maxHops; i++) {
|
||||
const currentTrade =
|
||||
Trade.bestTradeExactOut(allowedPairs, currencyIn, currencyAmountOut, { maxHops: i, maxNumResults: 1 })[0] ??
|
||||
null
|
||||
@@ -100,5 +97,5 @@ export function useV2TradeExactOut(
|
||||
return bestTradeSoFar
|
||||
}
|
||||
return null
|
||||
}, [currencyIn, currencyAmountOut, allowedPairs, singleHopOnly])
|
||||
}, [currencyIn, currencyAmountOut, allowedPairs, maxHops])
|
||||
}
|
||||
|
||||
@@ -3,27 +3,31 @@ 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, Currency } from '@uniswap/sdk-core'
|
||||
import { useBlockNumber } from 'state/application/hooks'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
|
||||
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<Currency>, CurrencyAmount<Currency>] | [undefined, undefined] {
|
||||
const positionManager = useV3NFTPositionManagerContract(false)
|
||||
const owner = useSingleCallResult(tokenId ? positionManager : null, 'ownerOf', [tokenId]).result?.[0]
|
||||
const owner: string | undefined = useSingleCallResult(tokenId ? positionManager : null, 'ownerOf', [tokenId])
|
||||
.result?.[0]
|
||||
|
||||
const tokenIdHexString = tokenId?.toHexString()
|
||||
const latestBlockNumber = useBlockNumber()
|
||||
|
||||
// TODO find a way to get this into multicall
|
||||
// because these amounts don't ever go down, we don't actually need to clear this state
|
||||
// latestBlockNumber is included to ensure data stays up-to-date every block
|
||||
const [amounts, setAmounts] = useState<[BigNumber, BigNumber]>()
|
||||
useEffect(() => {
|
||||
let stale = false
|
||||
|
||||
if (positionManager && tokenIdHexString && owner && typeof latestBlockNumber === 'number') {
|
||||
positionManager.callStatic
|
||||
.collect(
|
||||
@@ -36,15 +40,19 @@ export function useV3PositionFees(
|
||||
{ from: owner } // need to simulate the call as the owner
|
||||
)
|
||||
.then((results) => {
|
||||
setAmounts([results.amount0, results.amount1])
|
||||
if (!stale) setAmounts([results.amount0, results.amount1])
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
stale = true
|
||||
}
|
||||
}, [positionManager, tokenIdHexString, owner, latestBlockNumber])
|
||||
|
||||
if (pool && amounts) {
|
||||
return [
|
||||
CurrencyAmount.fromRawAmount(pool.token0, amounts[0].toString()),
|
||||
CurrencyAmount.fromRawAmount(pool.token1, amounts[1].toString()),
|
||||
CurrencyAmount.fromRawAmount(!asWETH ? unwrappedToken(pool.token0) : pool.token0, amounts[0].toString()),
|
||||
CurrencyAmount.fromRawAmount(!asWETH ? unwrappedToken(pool.token1) : pool.token1, amounts[1].toString()),
|
||||
]
|
||||
} else {
|
||||
return [undefined, undefined]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Currency, currencyEquals, WETH9 } from '@uniswap/sdk-core'
|
||||
import { Currency, WETH9 } from '@uniswap/sdk-core'
|
||||
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 {
|
||||
@@ -33,11 +33,13 @@ export default function useWrapCallback(
|
||||
|
||||
return useMemo(() => {
|
||||
if (!wethContract || !chainId || !inputCurrency || !outputCurrency) return NOT_APPLICABLE
|
||||
const weth = WETH9[chainId]
|
||||
if (!weth) return NOT_APPLICABLE
|
||||
|
||||
const hasInputAmount = Boolean(inputAmount?.greaterThan('0'))
|
||||
const sufficientBalance = inputAmount && balance && !balance.lessThan(inputAmount)
|
||||
|
||||
if (inputCurrency.isEther && currencyEquals(WETH9[chainId], outputCurrency)) {
|
||||
if (inputCurrency.isNative && weth.equals(outputCurrency)) {
|
||||
return {
|
||||
wrapType: WrapType.WRAP,
|
||||
execute:
|
||||
@@ -53,7 +55,7 @@ export default function useWrapCallback(
|
||||
: undefined,
|
||||
inputError: sufficientBalance ? undefined : hasInputAmount ? 'Insufficient ETH balance' : 'Enter ETH amount',
|
||||
}
|
||||
} else if (currencyEquals(WETH9[chainId], inputCurrency) && outputCurrency.isEther) {
|
||||
} else if (weth.equals(inputCurrency) && outputCurrency.isNative) {
|
||||
return {
|
||||
wrapType: WrapType.UNWRAP,
|
||||
execute:
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Web3Provider } from '@ethersproject/providers'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React as useWeb3ReactCore } from '@web3-react/core'
|
||||
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 } {
|
||||
export function useActiveWeb3React(): Web3ReactContextInterface<Web3Provider> {
|
||||
const context = useWeb3ReactCore<Web3Provider>()
|
||||
const contextNetwork = useWeb3ReactCore<Web3Provider>(NetworkContextName)
|
||||
return context.active ? context : contextNetwork
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user