Commit cb00e0ba authored by Noah Zinsmeister's avatar Noah Zinsmeister Committed by GitHub

migrate full away from ethers v4 to v5 (#728)

move some pacakges from dependencies to dev dependencies

bump versions
parent 4ccbd0c3
......@@ -5,28 +5,29 @@
"homepage": "https://uniswap.exchange",
"private": true,
"dependencies": {
"@ethersproject/address": "^5.0.0-beta.134",
"@ethersproject/bignumber": "^5.0.0-beta.138",
"@ethersproject/constants": "^5.0.0-beta.133",
"@ethersproject/contracts": "^5.0.0-beta.151",
"@ethersproject/providers": "5.0.0-beta.162",
"@ethersproject/strings": "^5.0.0-beta.136",
"@ethersproject/units": "^5.0.0-beta.132",
"@material-ui/core": "^4.9.5",
"@reach/dialog": "^0.2.8",
"@reach/tooltip": "^0.2.0",
"@types/jest": "^25.1.3",
"@types/node": "^13.7.4",
"@types/react": "^16.9.21",
"@types/react-dom": "^16.9.5",
"@uniswap/sdk": "^2.0.3",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "1.0.0-beta.0",
"@web3-react/core": "^6.0.2",
"@web3-react/fortmatic-connector": "^6.0.2",
"@web3-react/injected-connector": "^6.0.3",
"@web3-react/network-connector": "^6.0.4",
"@web3-react/portis-connector": "^6.0.2",
"@web3-react/walletconnect-connector": "^6.0.2",
"@web3-react/walletlink-connector": "^6.0.2",
"@web3-react/core": "^6.0.9",
"@web3-react/fortmatic-connector": "^6.0.9",
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/network-connector": "^6.0.9",
"@web3-react/portis-connector": "^6.0.9",
"@web3-react/walletconnect-connector": "^6.0.9",
"@web3-react/walletlink-connector": "^6.0.9",
"copy-to-clipboard": "^3.2.0",
"cross-env": "^7.0.2",
"escape-string-regexp": "^2.0.0",
"ethers": "^4.0.44",
"history": "^4.9.0",
"i18next": "^15.0.9",
"i18next-browser-languagedetector": "^3.0.1",
......@@ -35,22 +36,28 @@
"polished": "^3.3.2",
"prettier": "^1.17.0",
"qrcode.react": "^0.9.3",
"react": "^16.8.6",
"react": "^16.13.1",
"react-device-detect": "^1.6.2",
"react-dom": "^16.8.6",
"react-dom": "^16.13.1",
"react-feather": "^2.0.8",
"react-ga": "^2.5.7",
"react-i18next": "^10.7.0",
"react-router-dom": "^5.0.0",
"react-scripts": "^3.0.1",
"react-scripts": "^3.4.1",
"react-spring": "^8.0.27",
"react-switch": "^5.0.1",
"react-use-gesture": "^6.0.14",
"rebass": "^4.0.7",
"styled-components": "^4.2.0",
"typescript": "^3.7.5",
"use-media": "^1.4.0"
},
"devDependencies": {
"@types/jest": "^25.2.1",
"@types/node": "^13.13.5",
"@types/react": "^16.9.34",
"@types/react-dom": "^16.9.7",
"prettier": "^1.17.0",
"typescript": "^3.8.3"
},
"scripts": {
"start": "cross-env REACT_APP_GIT_COMMIT_HASH=$(git show -s --format=%H) react-scripts start",
"build": "cross-env REACT_APP_GIT_COMMIT_HASH=$(git show -s --format=%H) react-scripts build",
......
This diff is collapsed.
......@@ -2,8 +2,7 @@ import React from 'react'
import ReactDOM from 'react-dom'
import ReactGA from 'react-ga'
import { Web3ReactProvider, createWeb3ReactRoot } from '@web3-react/core'
import { ethers } from 'ethers'
import { Web3Provider } from 'ethers/providers'
import { Web3Provider } from '@ethersproject/providers'
import { NetworkContextName } from './constants'
import { isMobile } from 'react-device-detect'
......@@ -21,7 +20,7 @@ import './i18n'
const Web3ProviderNetwork = createWeb3ReactRoot(NetworkContextName)
function getLibrary(provider): Web3Provider {
const library = new ethers.providers.Web3Provider(provider)
const library = new Web3Provider(provider)
library.pollingInterval = 10000
return library
}
......@@ -58,9 +57,9 @@ function ContextProviders({ children }) {
function Updaters() {
return (
<>
<ApplicationContextUpdater/>
<TransactionContextUpdater/>
<BalancesContextUpdater/>
<ApplicationContextUpdater />
<TransactionContextUpdater />
<BalancesContextUpdater />
</>
)
}
......@@ -69,11 +68,11 @@ ReactDOM.render(
<Web3ReactProvider getLibrary={getLibrary}>
<Web3ProviderNetwork getLibrary={getLibrary}>
<ContextProviders>
<Updaters/>
<Updaters />
<ThemeProvider>
<>
<GlobalStyle/>
<App/>
<GlobalStyle />
<App />
</>
</ThemeProvider>
</ContextProviders>
......
import React, { useReducer, useState, useCallback, useEffect } from 'react'
import styled from 'styled-components'
import { ethers } from 'ethers'
import { withRouter } from 'react-router-dom'
import { parseUnits, parseEther } from '@ethersproject/units'
import { MaxUint256, Zero } from '@ethersproject/constants'
import { Contract } from '@ethersproject/contracts'
import { WETH, TokenAmount, JSBI, Percent, Route, Token, Pair, Price } from '@uniswap/sdk'
import TokenLogo from '../../components/TokenLogo'
......@@ -26,9 +27,9 @@ import { usePair, useTotalSupply } from '../../contexts/Pairs'
import { useWeb3React, useTokenContract } from '../../hooks'
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
import { BigNumber } from 'ethers/utils'
import { ROUTER_ADDRESS } from '../../constants'
import { getRouterContract, calculateGasMargin, isWETH } from '../../utils'
import { BigNumber } from '@ethersproject/bignumber'
// denominated in bips
const ALLOWED_SLIPPAGE = 50
......@@ -36,8 +37,6 @@ const ALLOWED_SLIPPAGE = 50
// denominated in seconds
const DEADLINE_FROM_NOW = 60 * 20
const GAS_MARGIN: BigNumber = ethers.utils.bigNumberify(1000)
const Wrapper = styled.div`
position: relative;
`
......@@ -179,8 +178,8 @@ function AddLiquidity({ token0, token1, step = false }) {
}
// token contracts for approvals and direct sends
const tokenContractInput: ethers.Contract = useTokenContract(tokens[Field.INPUT]?.address)
const tokenContractOutput: ethers.Contract = useTokenContract(tokens[Field.OUTPUT]?.address)
const tokenContractInput: Contract = useTokenContract(tokens[Field.INPUT]?.address)
const tokenContractOutput: Contract = useTokenContract(tokens[Field.OUTPUT]?.address)
// check on pending approvals for token amounts
const pendingApprovalInput = usePendingApproval(tokens[Field.INPUT]?.address)
......@@ -409,7 +408,7 @@ function AddLiquidity({ token0, token1, step = false }) {
// format ETH value for transaction
function hex(value: JSBI) {
return ethers.utils.bigNumberify(value.toString())
return BigNumber.from(value.toString())
}
// calculate slippage bounds based on current reserves
......@@ -435,7 +434,7 @@ function AddLiquidity({ token0, token1, step = false }) {
if (tokens[Field.INPUT] === WETH[chainId] || tokens[Field.OUTPUT] === WETH[chainId]) {
method = router.addLiquidityETH
estimate = router.estimate.addLiquidityETH
estimate = router.estimateGas.addLiquidityETH
args = [
tokens[Field.OUTPUT] === WETH[chainId] ? tokens[Field.INPUT].address : tokens[Field.OUTPUT].address, // token
......@@ -454,7 +453,7 @@ function AddLiquidity({ token0, token1, step = false }) {
)
} else {
method = router.addLiquidity
estimate = router.estimate.addLiquidity
estimate = router.estimateGas.addLiquidity
args = [
tokens[Field.INPUT].address,
tokens[Field.OUTPUT].address,
......@@ -465,32 +464,32 @@ function AddLiquidity({ token0, token1, step = false }) {
account,
deadline
]
value = ethers.constants.Zero
value = Zero
}
const estimatedGasLimit = await estimate(...args, {
value: value
})
method(...args, {
gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN),
await estimate(...args, {
value: value
})
.then(response => {
setTxHash(response.hash)
addTransaction(
response,
'Add ' +
parsedAmounts[Field.INPUT]?.toSignificant(3) +
' ' +
tokens[Field.INPUT]?.symbol +
' and ' +
parsedAmounts[Field.OUTPUT]?.toSignificant(3) +
' ' +
tokens[Field.OUTPUT]?.symbol
)
setPendingConfirmation(false)
})
.then(estimatedGasLimit =>
method(...args, {
gasLimit: calculateGasMargin(estimatedGasLimit),
value: value
}).then(response => {
setTxHash(response.hash)
addTransaction(
response,
'Add ' +
parsedAmounts[Field.INPUT]?.toSignificant(3) +
' ' +
tokens[Field.INPUT]?.symbol +
' and ' +
parsedAmounts[Field.OUTPUT]?.toSignificant(3) +
' ' +
tokens[Field.OUTPUT]?.symbol
)
setPendingConfirmation(false)
})
)
.catch((e: Error) => {
console.log(e)
setPendingConfirmation(true)
......@@ -500,21 +499,18 @@ function AddLiquidity({ token0, token1, step = false }) {
}
async function approveAmount(field) {
let estimatedGas
let useUserBalance = false
const tokenContract = field === Field.INPUT ? tokenContractInput : tokenContractOutput
estimatedGas = await tokenContract.estimate.approve(ROUTER_ADDRESS, ethers.constants.MaxUint256).catch(e => {
console.log('Error setting max token approval.')
})
if (!estimatedGas) {
const estimatedGas = await tokenContract.estimateGas.approve(ROUTER_ADDRESS, MaxUint256).catch(() => {
// general fallback for tokens who restrict approval amounts
estimatedGas = await tokenContract.estimate.approve(ROUTER_ADDRESS, userBalances[field])
useUserBalance = true
}
return tokenContract.estimateGas.approve(ROUTER_ADDRESS, userBalances[field])
})
tokenContract
.approve(ROUTER_ADDRESS, useUserBalance ? userBalances[field] : ethers.constants.MaxUint256, {
gasLimit: calculateGasMargin(estimatedGas, GAS_MARGIN)
.approve(ROUTER_ADDRESS, useUserBalance ? userBalances[field] : MaxUint256, {
gasLimit: calculateGasMargin(estimatedGas)
})
.then(response => {
addTransaction(response, 'Approve ' + tokens[field]?.symbol, { approval: tokens[field]?.address })
......
import React, { useReducer, useState, useCallback, useEffect } from 'react'
import styled from 'styled-components'
import { ethers } from 'ethers'
import { parseUnits } from '@ethersproject/units'
import { Zero } from '@ethersproject/constants'
import { Contract } from '@ethersproject/contracts'
import { TokenAmount, JSBI, Route, WETH, Percent, Token, Pair } from '@uniswap/sdk'
import Slider from '../../components/Slider'
......@@ -26,7 +27,6 @@ import { usePairContract } from '../../hooks'
import { useTransactionAdder } from '../../contexts/Transactions'
import { usePair, useTotalSupply } from '../../contexts/Pairs'
import { BigNumber } from 'ethers/utils'
import { splitSignature } from '@ethersproject/bytes'
import { ROUTER_ADDRESS } from '../../constants'
import { getRouterContract, calculateGasMargin } from '../../utils'
......@@ -34,8 +34,6 @@ import { getRouterContract, calculateGasMargin } from '../../utils'
// denominated in seconds
const DEADLINE_FROM_NOW = 60 * 20
const GAS_MARGIN: BigNumber = ethers.utils.bigNumberify(1000)
const Wrapper = styled.div`
position: relative;
`
......@@ -167,7 +165,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
}
const pair: Pair = usePair(inputToken, outputToken)
const pairContract: ethers.Contract = usePairContract(pair?.liquidityToken.address)
const pairContract: Contract = usePairContract(pair?.liquidityToken.address)
// pool token data
const totalPoolTokens: TokenAmount = useTotalSupply(tokens[Field.TOKEN0], tokens[Field.TOKEN1])
......@@ -435,7 +433,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
// removal with ETH
if (tokens[Field.TOKEN0] === WETH[chainId] || tokens[Field.TOKEN1] === WETH[chainId]) {
method = router.removeLiquidityETHWithPermit
estimate = router.estimate.removeLiquidityETHWithPermit
estimate = router.estimateGas.removeLiquidityETHWithPermit
args = [
tokens[Field.TOKEN1] === WETH[chainId] ? tokens[Field.TOKEN0].address : tokens[Field.TOKEN1].address,
parsedAmounts[Field.LIQUIDITY].raw.toString(),
......@@ -456,7 +454,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
//removal without ETH
else {
method = router.removeLiquidityWithPermit
estimate = router.estimate.removeLiquidityWithPermit
estimate = router.estimateGas.removeLiquidityWithPermit
args = [
tokens[Field.TOKEN0].address,
tokens[Field.TOKEN1].address,
......@@ -472,31 +470,28 @@ export default function RemoveLiquidity({ token0, token1 }) {
]
}
const estimatedGasLimit = await estimate(...args, {
value: ethers.constants.Zero
}).catch(() => {
resetModalState()
setShowConfirm(false)
})
method(...args, {
gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN)
await estimate(...args, {
value: Zero
})
.then(response => {
setPendingConfirmation(false)
setTxHash(response.hash)
addTransaction(
response,
'Remove ' +
parsedAmounts[Field.TOKEN0]?.toSignificant(3) +
' ' +
tokens[Field.TOKEN0]?.symbol +
' and ' +
parsedAmounts[Field.TOKEN1]?.toSignificant(3) +
' ' +
tokens[Field.TOKEN1]?.symbol
)
})
.then(estimatedGasLimit =>
method(...args, {
gasLimit: calculateGasMargin(estimatedGasLimit)
}).then(response => {
setPendingConfirmation(false)
setTxHash(response.hash)
addTransaction(
response,
'Remove ' +
parsedAmounts[Field.TOKEN0]?.toSignificant(3) +
' ' +
tokens[Field.TOKEN0]?.symbol +
' and ' +
parsedAmounts[Field.TOKEN1]?.toSignificant(3) +
' ' +
tokens[Field.TOKEN1]?.symbol
)
})
)
.catch(e => {
console.log(e)
resetModalState()
......
import { Contract } from '@ethersproject/contracts'
import { getAddress } from '@ethersproject/address'
import { AddressZero } from '@ethersproject/constants'
import { parseBytes32String } from '@ethersproject/strings'
import { BigNumber } from '@ethersproject/bignumber'
import { WETH } from '@uniswap/sdk'
import {abi as IUniswapV2PairABI} from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { abi as IUniswapV2Router01ABI } from '@uniswap/v2-periphery/build/IUniswapV2Router01.json'
import { Contract, ethers, Signer } from 'ethers'
import { JsonRpcProvider, Provider } from 'ethers/providers'
import { ROUTER_ADDRESS, SUPPORTED_THEMES } from '../constants'
import ERC20_ABI from '../constants/abis/erc20.json'
import ERC20_BYTES32_ABI from '../constants/abis/erc20_bytes32.json'
import UncheckedJsonRpcSigner from './signer'
export enum ERROR_CODES {
TOKEN_SYMBOL = 1,
TOKEN_DECIMALS = 2
......@@ -19,9 +20,9 @@ export enum ERROR_CODES {
export function safeAccess(object, path) {
return object
? path.reduce(
(accumulator, currentValue) => (accumulator && accumulator[currentValue] ? accumulator[currentValue] : null),
object
)
(accumulator, currentValue) => (accumulator && accumulator[currentValue] ? accumulator[currentValue] : null),
object
)
: null
}
......@@ -80,7 +81,7 @@ export function getAllQueryParams(): QueryParams {
inputTokenAddress: parseUrlAddress('inputTokenAddress'),
outputTokenAddress: parseUrlAddress('outputTokenAddress'),
inputTokenAmount: parseUrlTokenAmount('inputTokenAmount'),
outputTokenAmount: parseUrlTokenAmount('outputTokenAmount'),
outputTokenAmount: parseUrlTokenAmount('outputTokenAmount')
}
}
......@@ -125,34 +126,30 @@ export function shortenTransactionHash(hash, digits = 4) {
return `${hash.substring(0, digits + 2)}...${hash.substring(66 - digits)}`
}
export function isAddress(value): string | false {
export function isAddress(value: any): string | false {
try {
return ethers.utils.getAddress(value.toLowerCase())
return getAddress(value.toLowerCase())
} catch {
return false
}
}
export function calculateGasMargin(value, margin) {
if (value) {
const offset = value.mul(margin).div(ethers.utils.bigNumberify(10000))
return value.add(offset)
}
return null
export function calculateGasMargin(value: BigNumber) {
return value.mul(BigNumber.from(10000).add(BigNumber.from(1000))).div(BigNumber.from(10000)) // add 10%
}
// account is optional
export function getProviderOrSigner(library: JsonRpcProvider, account?: string): Signer | Provider {
return account ? new UncheckedJsonRpcSigner(library.getSigner(account)) : library
export function getProviderOrSigner(library: any, account?: string): any {
return account ? library.getSigner(account).connectUnchecked() : library
}
// account is optional
export function getContract(address: string, ABI: any, library: JsonRpcProvider, account?: string): Contract {
if (!isAddress(address) || address === ethers.constants.AddressZero) {
export function getContract(address: string, ABI: any, library: any, account?: string): Contract {
if (!isAddress(address) || address === AddressZero) {
throw Error(`Invalid 'address' parameter '${address}'.`)
}
return new ethers.Contract(address, ABI, getProviderOrSigner(library, account))
return new Contract(address, ABI, getProviderOrSigner(library, account))
}
// account is optional
......@@ -176,7 +173,7 @@ export async function getTokenName(tokenAddress, library) {
.catch(() =>
getContract(tokenAddress, ERC20_BYTES32_ABI, library)
.name()
.then(bytes32 => ethers.utils.parseBytes32String(bytes32))
.then(parseBytes32String)
)
.catch(error => {
error.code = ERROR_CODES.TOKEN_SYMBOL
......@@ -194,7 +191,7 @@ export async function getTokenSymbol(tokenAddress, library) {
.symbol()
.catch(() => {
const contractBytes32 = getContract(tokenAddress, ERC20_BYTES32_ABI, library)
return contractBytes32.symbol().then(bytes32 => ethers.utils.parseBytes32String(bytes32))
return contractBytes32.symbol().then(parseBytes32String)
})
.catch(error => {
error.code = ERROR_CODES.TOKEN_SYMBOL
......@@ -237,8 +234,8 @@ export async function getTokenBalance(tokenAddress, address, library) {
export async function getTokenAllowance(address, tokenAddress, spenderAddress, library) {
if (!isAddress(address) || !isAddress(tokenAddress) || !isAddress(spenderAddress)) {
throw Error(
'Invalid \'address\' or \'tokenAddress\' or \'spenderAddress\' parameter' +
`'${address}' or '${tokenAddress}' or '${spenderAddress}'.`
"Invalid 'address' or 'tokenAddress' or 'spenderAddress' parameter" +
`'${address}' or '${tokenAddress}' or '${spenderAddress}'.`
)
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment