Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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 }}
|
||||
@@ -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'
|
||||
|
||||
20
README.md
20
README.md
@@ -14,7 +14,10 @@ An open source interface for Uniswap -- a protocol for decentralized exchange of
|
||||
- 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
|
||||
|
||||
@@ -41,8 +44,17 @@ yarn start
|
||||
**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).
|
||||
|
||||
17
package.json
17
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,10 +49,10 @@
|
||||
"@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.4",
|
||||
"@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",
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { X } from 'react-feather'
|
||||
import styled, { keyframes } from 'styled-components'
|
||||
import tokenLogo from '../../assets/images/token-logo.png'
|
||||
import { ButtonPrimary } from '../../components/Button'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ApplicationModal } from '../../state/application/actions'
|
||||
import {
|
||||
useModalOpen,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Web3Provider } from '@ethersproject/providers'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { InjectedConnector } from '@web3-react/injected-connector'
|
||||
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
|
||||
import { WalletLinkConnector } from '@web3-react/walletlink-connector'
|
||||
@@ -20,20 +19,20 @@ if (typeof INFURA_KEY === 'undefined') {
|
||||
}
|
||||
|
||||
const NETWORK_URLS: {
|
||||
[chainId in ChainId]: string
|
||||
[chainId: number]: string
|
||||
} = {
|
||||
[ChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.RINKEBY]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.ROPSTEN]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.GÖRLI]: `https://goerli.infura.io/v3/${INFURA_KEY}`,
|
||||
[ChainId.KOVAN]: `https://kovan.infura.io/v3/${INFURA_KEY}`,
|
||||
[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 = [ChainId.MAINNET, ChainId.RINKEBY, ChainId.ROPSTEN, ChainId.KOVAN, ChainId.GÖRLI]
|
||||
const SUPPORTED_CHAIN_IDS = [1, 4, 3, 42, 5]
|
||||
|
||||
export const network = new NetworkConnector({
|
||||
urls: NETWORK_URLS,
|
||||
defaultChainId: ChainId.MAINNET,
|
||||
defaultChainId: 1,
|
||||
})
|
||||
|
||||
let networkLibrary: Web3Provider | undefined
|
||||
@@ -67,7 +66,7 @@ export const portis = new PortisConnector({
|
||||
|
||||
// mainnet only
|
||||
export const walletlink = new WalletLinkConnector({
|
||||
url: NETWORK_URLS[ChainId.MAINNET],
|
||||
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]
|
||||
)
|
||||
}
|
||||
@@ -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,5 +1,4 @@
|
||||
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'
|
||||
@@ -8,7 +7,7 @@ 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()
|
||||
@@ -16,10 +15,10 @@ export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean
|
||||
|
||||
const ensResolver = useCallback(
|
||||
async (ensName: string) => {
|
||||
if (!library || chainId !== ChainId.MAINNET) {
|
||||
if (!library || chainId !== 1) {
|
||||
const networkLibrary = getNetworkLibrary()
|
||||
const network = await networkLibrary.getNetwork()
|
||||
if (networkLibrary && network.chainId === ChainId.MAINNET) {
|
||||
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,
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,42 +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?.greaterThan(0) && usdcEthPair?.reserveOf(weth)?.greaterThan(0)
|
||||
? 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) {
|
||||
|
||||
@@ -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,9 +3,9 @@ import { useEffect, useState } from 'react'
|
||||
import { useV3NFTPositionManagerContract } from './useContract'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Pool } from '@uniswap/v3-sdk'
|
||||
import { CurrencyAmount, Token, currencyEquals, ETHER, Ether } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Currency } from '@uniswap/sdk-core'
|
||||
import { useBlockNumber } from 'state/application/hooks'
|
||||
import { unwrappedToken } from 'utils/wrappedCurrency'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
|
||||
const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)
|
||||
|
||||
@@ -14,18 +14,20 @@ export function useV3PositionFees(
|
||||
pool?: Pool,
|
||||
tokenId?: BigNumber,
|
||||
asWETH = false
|
||||
): [CurrencyAmount<Token | Ether>, CurrencyAmount<Token | Ether>] | [undefined, undefined] {
|
||||
): [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(
|
||||
@@ -38,19 +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 [
|
||||
!asWETH && currencyEquals(unwrappedToken(pool.token0), ETHER)
|
||||
? CurrencyAmount.ether(amounts[0].toString())
|
||||
: CurrencyAmount.fromRawAmount(pool.token0, amounts[0].toString()),
|
||||
!asWETH && currencyEquals(unwrappedToken(pool.token1), ETHER)
|
||||
? CurrencyAmount.ether(amounts[1].toString())
|
||||
: CurrencyAmount.fromRawAmount(pool.token1, amounts[1].toString()),
|
||||
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
|
||||
@@ -7,7 +7,7 @@ import ReactGA from 'react-ga'
|
||||
import { Provider } from 'react-redux'
|
||||
import { HashRouter } from 'react-router-dom'
|
||||
import Blocklist from './components/Blocklist'
|
||||
import { NetworkContextName } from './constants'
|
||||
import { NetworkContextName } from './constants/misc'
|
||||
import './i18n'
|
||||
import App from './pages/App'
|
||||
import store from './state'
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import { AutoRow } from '../../components/Row'
|
||||
import { ONE_BIPS } from '../../constants'
|
||||
import { ONE_BIPS } from '../../constants/misc'
|
||||
import { Field } from '../../state/mint/v3/actions'
|
||||
import { TYPE } from '../../theme'
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React, { useCallback, useContext, useMemo, useState, useEffect } from 'react'
|
||||
import React, { useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { WETH9 } from '@uniswap/sdk-core'
|
||||
import { AlertTriangle, AlertCircle } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
import { ZERO_PERCENT } from '../../constants'
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from '../../constants/addresses'
|
||||
import { useArgentWalletContract } from '../../hooks/useArgentWalletContract'
|
||||
import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
|
||||
import { RouteComponentProps } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
@@ -17,8 +19,10 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import { RowBetween, RowFixed } from '../../components/Row'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||
import approveAmountCalldata from '../../utils/approveAmountCalldata'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import Review from './Review'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
@@ -42,7 +46,6 @@ import {
|
||||
useV3DerivedMintInfo,
|
||||
} from 'state/mint/v3/hooks'
|
||||
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from 'constants/v3'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { useDerivedPositionInfo } from 'hooks/useDerivedPositionInfo'
|
||||
import { PositionPreview } from 'components/PositionPreview'
|
||||
@@ -50,7 +53,6 @@ import FeeSelector from 'components/FeeSelector'
|
||||
import RangeSelector from 'components/RangeSelector'
|
||||
import RateToggle from 'components/RateToggle'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { calculateGasMargin } from 'utils'
|
||||
import { AddRemoveTabs } from 'components/NavigationTabs'
|
||||
import HoverInlineText from 'components/HoverInlineText'
|
||||
|
||||
@@ -88,25 +90,13 @@ export default function AddLiquidity({
|
||||
const currencyB = useCurrency(currencyIdB)
|
||||
|
||||
// keep track for UI display purposes of user selected base currency
|
||||
const [baseCurrency, setBaseCurrency] = useState(currencyA)
|
||||
const baseCurrency = currencyA
|
||||
const quoteCurrency = useMemo(
|
||||
() =>
|
||||
currencyA && currencyB && baseCurrency
|
||||
? currencyEquals(baseCurrency, currencyA)
|
||||
? currencyB
|
||||
: currencyA
|
||||
: undefined,
|
||||
currencyA && currencyB && baseCurrency ? (baseCurrency.equals(currencyA) ? currencyB : currencyA) : undefined,
|
||||
[currencyA, currencyB, baseCurrency]
|
||||
)
|
||||
|
||||
// url params are the source truth, so we have to do this
|
||||
useEffect(() => {
|
||||
setBaseCurrency(currencyA)
|
||||
return () => {
|
||||
setBaseCurrency(undefined)
|
||||
}
|
||||
}, [currencyA, currencyB])
|
||||
|
||||
// mint state
|
||||
const { independentField, typedValue, startPriceTypedValue } = useV3MintState()
|
||||
|
||||
@@ -136,13 +126,8 @@ export default function AddLiquidity({
|
||||
existingPosition
|
||||
)
|
||||
|
||||
const {
|
||||
onFieldAInput,
|
||||
onFieldBInput,
|
||||
onLeftRangeInput,
|
||||
onRightRangeInput,
|
||||
onStartPriceInput,
|
||||
} = useV3MintActionHandlers(noLiquidity)
|
||||
const { onFieldAInput, onFieldBInput, onLeftRangeInput, onRightRangeInput, onStartPriceInput } =
|
||||
useV3MintActionHandlers(noLiquidity)
|
||||
|
||||
const isValid = !errorMessage && !invalidRange
|
||||
|
||||
@@ -187,13 +172,15 @@ export default function AddLiquidity({
|
||||
{}
|
||||
)
|
||||
|
||||
const argentWalletContract = useArgentWalletContract()
|
||||
|
||||
// check whether the user has approved the router on the tokens
|
||||
const [approvalA, approveACallback] = useApproveCallback(
|
||||
parsedAmounts[Field.CURRENCY_A],
|
||||
argentWalletContract ? undefined : parsedAmounts[Field.CURRENCY_A],
|
||||
chainId ? NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId] : undefined
|
||||
)
|
||||
const [approvalB, approveBCallback] = useApproveCallback(
|
||||
parsedAmounts[Field.CURRENCY_B],
|
||||
argentWalletContract ? undefined : parsedAmounts[Field.CURRENCY_B],
|
||||
chainId ? NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId] : undefined
|
||||
)
|
||||
|
||||
@@ -209,28 +196,53 @@ export default function AddLiquidity({
|
||||
}
|
||||
|
||||
if (position && account && deadline) {
|
||||
const useNative = currencyA.isNative ? currencyA : currencyB.isNative ? currencyB : undefined
|
||||
const { calldata, value } =
|
||||
hasExistingPosition && tokenId
|
||||
? NonfungiblePositionManager.addCallParameters(position, {
|
||||
tokenId,
|
||||
slippageTolerance: allowedSlippage,
|
||||
deadline: deadline.toString(),
|
||||
useEther: currencyA.isEther || currencyB.isEther,
|
||||
useNative,
|
||||
})
|
||||
: NonfungiblePositionManager.addCallParameters(position, {
|
||||
slippageTolerance: allowedSlippage,
|
||||
recipient: account,
|
||||
deadline: deadline.toString(),
|
||||
useEther: currencyA.isEther || currencyB.isEther,
|
||||
useNative,
|
||||
createPool: noLiquidity,
|
||||
})
|
||||
|
||||
const txn = {
|
||||
let txn: { to: string; data: string; value: string } = {
|
||||
to: NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId],
|
||||
data: calldata,
|
||||
value,
|
||||
}
|
||||
|
||||
if (argentWalletContract) {
|
||||
const amountA = parsedAmounts[Field.CURRENCY_A]
|
||||
const amountB = parsedAmounts[Field.CURRENCY_B]
|
||||
const batch = [
|
||||
...(amountA && amountA.currency.isToken
|
||||
? [approveAmountCalldata(amountA, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId])]
|
||||
: []),
|
||||
...(amountB && amountB.currency.isToken
|
||||
? [approveAmountCalldata(amountB, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId])]
|
||||
: []),
|
||||
{
|
||||
to: txn.to,
|
||||
data: txn.data,
|
||||
value: txn.value,
|
||||
},
|
||||
]
|
||||
const data = argentWalletContract.interface.encodeFunctionData('wc_multiCall', [batch])
|
||||
txn = {
|
||||
to: argentWalletContract.address,
|
||||
data,
|
||||
value: '0x0',
|
||||
}
|
||||
}
|
||||
|
||||
setAttemptingTxn(true)
|
||||
|
||||
library
|
||||
@@ -261,6 +273,7 @@ export default function AddLiquidity({
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to send transaction', error)
|
||||
setAttemptingTxn(false)
|
||||
// we only care if the error is something _other_ than the user rejected the tx
|
||||
if (error?.code !== 4001) {
|
||||
@@ -368,8 +381,10 @@ export default function AddLiquidity({
|
||||
)
|
||||
|
||||
// we need an existence check on parsed amounts for single-asset deposits
|
||||
const showApprovalA = approvalA !== ApprovalState.APPROVED && !!parsedAmounts[Field.CURRENCY_A]
|
||||
const showApprovalB = approvalB !== ApprovalState.APPROVED && !!parsedAmounts[Field.CURRENCY_B]
|
||||
const showApprovalA =
|
||||
!argentWalletContract && approvalA !== ApprovalState.APPROVED && !!parsedAmounts[Field.CURRENCY_A]
|
||||
const showApprovalB =
|
||||
!argentWalletContract && approvalB !== ApprovalState.APPROVED && !!parsedAmounts[Field.CURRENCY_B]
|
||||
|
||||
return (
|
||||
<ScrollablePage>
|
||||
@@ -435,7 +450,7 @@ export default function AddLiquidity({
|
||||
id="add-liquidity-input-tokena"
|
||||
showCommonBases
|
||||
/>
|
||||
<div style={{ width: '12px' }}></div>
|
||||
<div style={{ width: '12px' }} />
|
||||
|
||||
<CurrencyDropdown
|
||||
value={formattedAmounts[Field.CURRENCY_B]}
|
||||
@@ -588,7 +603,7 @@ export default function AddLiquidity({
|
||||
<TYPE.body fontWeight={500} textAlign="center" fontSize={20}>
|
||||
<HoverInlineText
|
||||
maxCharacters={20}
|
||||
text={invertPrice ? price.invert().toSignificant(5) : price.toSignificant(5)}
|
||||
text={invertPrice ? price.invert().toSignificant(6) : price.toSignificant(6)}
|
||||
/>{' '}
|
||||
</TYPE.body>
|
||||
<TYPE.main fontWeight={500} textAlign="center" fontSize={12}>
|
||||
@@ -714,8 +729,8 @@ export default function AddLiquidity({
|
||||
}}
|
||||
disabled={
|
||||
!isValid ||
|
||||
(approvalA !== ApprovalState.APPROVED && !depositADisabled) ||
|
||||
(approvalB !== ApprovalState.APPROVED && !depositBDisabled)
|
||||
(!argentWalletContract && approvalA !== ApprovalState.APPROVED && !depositADisabled) ||
|
||||
(!argentWalletContract && approvalB !== ApprovalState.APPROVED && !depositBDisabled)
|
||||
}
|
||||
error={!isValid && !!parsedAmounts[Field.CURRENCY_A] && !!parsedAmounts[Field.CURRENCY_B]}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import React from 'react'
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom'
|
||||
import AddLiquidity from './index'
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import { AutoRow } from '../../components/Row'
|
||||
import { ONE_BIPS } from '../../constants'
|
||||
import { ONE_BIPS } from '../../constants/misc'
|
||||
import { Field } from '../../state/mint/actions'
|
||||
import { TYPE } from '../../theme'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, CurrencyAmount, currencyEquals, Percent, WETH9 } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Percent, WETH9 } from '@uniswap/sdk-core'
|
||||
import React, { useCallback, useContext, useState } from 'react'
|
||||
import { Plus } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
@@ -17,10 +17,10 @@ import { AddRemoveTabs } from '../../components/NavigationTabs'
|
||||
import { MinimalPositionCard } from '../../components/PositionCard'
|
||||
import Row, { RowBetween, RowFlat } from '../../components/Row'
|
||||
|
||||
import { V2_ROUTER_ADDRESS, ZERO_PERCENT } from '../../constants'
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { useV2RouterContract } from '../../hooks/useContract'
|
||||
import { PairState } from '../../hooks/useV2Pairs'
|
||||
import { useActiveWeb3React } from '../../hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
@@ -32,9 +32,9 @@ import { useDerivedMintInfo, useMintActionHandlers, useMintState } from '../../s
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useIsExpertMode, useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { TYPE } from '../../theme'
|
||||
import { calculateGasMargin, calculateSlippageAmount } from '../../utils'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { calculateSlippageAmount } from '../../utils/calculateSlippageAmount'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { wrappedCurrency } from '../../utils/wrappedCurrency'
|
||||
import AppBody from '../AppBody'
|
||||
import { Dots, Wrapper } from '../Pool/styleds'
|
||||
import { ConfirmAddModalBottom } from './ConfirmAddModalBottom'
|
||||
@@ -57,9 +57,7 @@ export default function AddLiquidity({
|
||||
const currencyB = useCurrency(currencyIdB)
|
||||
|
||||
const oneCurrencyIsWETH = Boolean(
|
||||
chainId &&
|
||||
((currencyA && currencyEquals(currencyA, WETH9[chainId])) ||
|
||||
(currencyB && currencyEquals(currencyB, WETH9[chainId])))
|
||||
chainId && ((currencyA && currencyA.equals(WETH9[chainId])) || (currencyB && currencyB.equals(WETH9[chainId])))
|
||||
)
|
||||
|
||||
const toggleWalletModal = useWalletModalToggle() // toggle wallet when disconnected
|
||||
@@ -122,14 +120,14 @@ export default function AddLiquidity({
|
||||
{}
|
||||
)
|
||||
|
||||
const router = useV2RouterContract()
|
||||
|
||||
// check whether the user has approved the router on the tokens
|
||||
const [approvalA, approveACallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_A], V2_ROUTER_ADDRESS)
|
||||
const [approvalB, approveBCallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_B], V2_ROUTER_ADDRESS)
|
||||
const [approvalA, approveACallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_A], router?.address)
|
||||
const [approvalB, approveBCallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_B], router?.address)
|
||||
|
||||
const addTransaction = useTransactionAdder()
|
||||
|
||||
const router = useV2RouterContract()
|
||||
|
||||
async function onAdd() {
|
||||
if (!chainId || !library || !account || !router) return
|
||||
|
||||
@@ -147,12 +145,12 @@ export default function AddLiquidity({
|
||||
method: (...args: any) => Promise<TransactionResponse>,
|
||||
args: Array<string | string[] | number>,
|
||||
value: BigNumber | null
|
||||
if (currencyA.isEther || currencyB.isEther) {
|
||||
const tokenBIsETH = currencyB.isEther
|
||||
if (currencyA.isNative || currencyB.isNative) {
|
||||
const tokenBIsETH = currencyB.isNative
|
||||
estimate = router.estimateGas.addLiquidityETH
|
||||
method = router.addLiquidityETH
|
||||
args = [
|
||||
wrappedCurrency(tokenBIsETH ? currencyA : currencyB, chainId)?.address ?? '', // token
|
||||
(tokenBIsETH ? currencyA : currencyB)?.wrapped?.address ?? '', // token
|
||||
(tokenBIsETH ? parsedAmountA : parsedAmountB).quotient.toString(), // token desired
|
||||
amountsMin[tokenBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B].toString(), // token min
|
||||
amountsMin[tokenBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A].toString(), // eth min
|
||||
@@ -164,8 +162,8 @@ export default function AddLiquidity({
|
||||
estimate = router.estimateGas.addLiquidity
|
||||
method = router.addLiquidity
|
||||
args = [
|
||||
wrappedCurrency(currencyA, chainId)?.address ?? '',
|
||||
wrappedCurrency(currencyB, chainId)?.address ?? '',
|
||||
currencyA?.wrapped?.address ?? '',
|
||||
currencyB?.wrapped?.address ?? '',
|
||||
parsedAmountA.quotient.toString(),
|
||||
parsedAmountB.quotient.toString(),
|
||||
amountsMin[Field.CURRENCY_A].toString(),
|
||||
|
||||
@@ -9,9 +9,10 @@ const REWARDS_DURATION = DAY * REWARDS_DURATION_DAYS
|
||||
|
||||
export function Countdown({ exactEnd }: { exactEnd?: Date }) {
|
||||
// get end/beginning times
|
||||
const end = useMemo(() => (exactEnd ? Math.floor(exactEnd.getTime() / 1000) : STAKING_GENESIS + REWARDS_DURATION), [
|
||||
exactEnd,
|
||||
])
|
||||
const end = useMemo(
|
||||
() => (exactEnd ? Math.floor(exactEnd.getTime() / 1000) : STAKING_GENESIS + REWARDS_DURATION),
|
||||
[exactEnd]
|
||||
)
|
||||
const begin = useMemo(() => end - REWARDS_DURATION, [end])
|
||||
|
||||
// get current time
|
||||
@@ -58,9 +59,9 @@ export function Countdown({ exactEnd }: { exactEnd?: Date }) {
|
||||
{message}{' '}
|
||||
{Number.isFinite(timeRemaining) && (
|
||||
<code>
|
||||
{`${days}:${hours.toString().padStart(2, '0')}:${minutes
|
||||
{`${days}:${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds
|
||||
.toString()
|
||||
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`}
|
||||
.padStart(2, '0')}`}
|
||||
</code>
|
||||
)}
|
||||
</TYPE.black>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user