Commit 8d3babd0 authored by Moody Salem's avatar Moody Salem

refactor: more separation by chain of addresses

parent 75ed4c5d
......@@ -83,7 +83,10 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
// approval data for stake
const deadline = useTransactionDeadline()
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(parsedAmountWrapped, V2_ROUTER_ADDRESS)
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(
parsedAmountWrapped,
chainId && V2_ROUTER_ADDRESS[chainId]
)
const [approval, approveCallback] = useApproveCallback(parsedAmount, stakingInfo.stakingRewardAddress)
const stakingContract = useStakingContract(stakingInfo.stakingRewardAddress)
......
......@@ -3,21 +3,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: { [chainId in ChainId]: string } = constructSameAddressMap(
'0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696'
)
export const V2_ROUTER_ADDRESS = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'
export const GOVERNANCE_ADDRESS = '0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F'
export const TIMELOCK_ADDRESS = '0x1a9C8182C09F50C8318d769245beA52c32BE35BC'
export const MULTICALL2_ADDRESSES = constructSameAddressMap('0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696')
export const V2_ROUTER_ADDRESS = constructSameAddressMap('0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D')
export const GOVERNANCE_ADDRESS = constructSameAddressMap('0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F')
export const TIMELOCK_ADDRESS = constructSameAddressMap('0x1a9C8182C09F50C8318d769245beA52c32BE35BC')
export const MERKLE_DISTRIBUTOR_ADDRESS: { [chainId in ChainId]?: string } = {
[ChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e',
}
export const ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS = '0xeca4B0bDBf7c55E9b7925919d03CbF8Dc82537E8'
export const ARGENT_WALLET_DETECTOR_ADDRESS: { [chainId in ChainId]?: string } = {
[ChainId.MAINNET]: '0xeca4B0bDBf7c55E9b7925919d03CbF8Dc82537E8',
}
export const V3_CORE_FACTORY_ADDRESSES = constructSameAddressMap(V3_FACTORY_ADDRESS)
export const QUOTER_ADDRESSES = constructSameAddressMap('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')
export const TICK_LENS_ADDRESSES = constructSameAddressMap('0xbfd8137f7d1516D3ea5cA83523914859ec47F573')
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = constructSameAddressMap(
'0xC36442b4a4522E871399CD717aBDD847Ab11FE88'
)
export const ENS_REGISTRAR_ADDRESSES = {
[ChainId.MAINNET]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
[ChainId.GÖRLI]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
[ChainId.RINKEBY]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
[ChainId.ROPSTEN]: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
}
export const SOCKS_CONTROLLER_ADDRESSES = {
[ChainId.MAINNET]: '0x65770b5283117639760beA3F867b69b3697a91dd',
}
export const SWAP_ROUTER_ADDRESSES = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564')
export const V3_MIGRATOR_ADDRESSES = constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34')
import { ChainId } from '@uniswap/sdk-core'
import { GOVERNANCE_ADDRESS, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses'
export const COMMON_CONTRACT_NAMES: { [address: string]: string } = {
[UNI_ADDRESS[ChainId.MAINNET]]: 'UNI',
[GOVERNANCE_ADDRESS]: 'Governance',
[TIMELOCK_ADDRESS]: 'Timelock',
export const COMMON_CONTRACT_NAMES: { [chainId in ChainId]?: { [address: string]: string } } = {
[ChainId.MAINNET]: {
[UNI_ADDRESS[ChainId.MAINNET]]: 'UNI',
[GOVERNANCE_ADDRESS[ChainId.MAINNET]]: 'Governance',
[TIMELOCK_ADDRESS[ChainId.MAINNET]]: 'Timelock',
},
[ChainId.RINKEBY]: {
[UNI_ADDRESS[ChainId.RINKEBY]]: 'Rinkeby UNI',
[GOVERNANCE_ADDRESS[ChainId.RINKEBY]]: 'Rinkeby Governance',
[TIMELOCK_ADDRESS[ChainId.RINKEBY]]: 'Rinkeby Timelock',
},
[ChainId.ROPSTEN]: {
[UNI_ADDRESS[ChainId.ROPSTEN]]: 'Ropsten UNI',
[GOVERNANCE_ADDRESS[ChainId.ROPSTEN]]: 'Ropsten Governance',
[TIMELOCK_ADDRESS[ChainId.ROPSTEN]]: 'Ropsten Timelock',
},
[ChainId.KOVAN]: {
[UNI_ADDRESS[ChainId.KOVAN]]: 'Kovan UNI',
[GOVERNANCE_ADDRESS[ChainId.KOVAN]]: 'Kovan Governance',
[TIMELOCK_ADDRESS[ChainId.KOVAN]]: 'Kovan Timelock',
},
[ChainId.GÖRLI]: {
[UNI_ADDRESS[ChainId.GÖRLI]]: 'Goerli UNI',
[GOVERNANCE_ADDRESS[ChainId.GÖRLI]]: 'Goerli Governance',
[TIMELOCK_ADDRESS[ChainId.GÖRLI]]: 'Goerli Timelock',
},
}
export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13
// Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time
export const AVERAGE_BLOCK_TIME_IN_SECS = 13
export const AVERAGE_BLOCK_TIME_IN_SECS: { [chainId in ChainId]?: number } = {
[ChainId.MAINNET]: DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS,
}
......@@ -3,8 +3,6 @@ import JSBI from 'jsbi'
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
export { PRELOADED_PROPOSALS } from './proposals'
export const NetworkContextName = 'NETWORK'
// 30 minutes, denominated in seconds
......
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,
}
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)*
......
......@@ -6,7 +6,7 @@ import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { useCallback, useMemo } from 'react'
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 './web3'
import { useTokenAllowance } from './useTokenAllowance'
......@@ -103,13 +103,19 @@ export function useApproveCallbackFromTrade(
allowedSlippage: Percent
) {
const { chainId } = useActiveWeb3React()
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
const v3SwapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
const amountToApprove = useMemo(
() => (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
[trade, allowedSlippage]
)
return useApproveCallback(
amountToApprove,
trade instanceof V2Trade ? V2_ROUTER_ADDRESS : trade instanceof V3Trade ? swapRouterAddress : undefined
chainId
? trade instanceof V2Trade
? V2_ROUTER_ADDRESS[chainId]
: trade instanceof V3Trade
? v3SwapRouterAddress
: undefined
: undefined
)
}
......@@ -29,11 +29,13 @@ import {
TICK_LENS_ADDRESSES,
V3_CORE_FACTORY_ADDRESSES,
V3_MIGRATOR_ADDRESSES,
ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS,
ARGENT_WALLET_DETECTOR_ADDRESS,
GOVERNANCE_ADDRESS,
MERKLE_DISTRIBUTOR_ADDRESS,
MULTICALL2_ADDRESSES,
V2_ROUTER_ADDRESS,
ENS_REGISTRAR_ADDRESSES,
SOCKS_CONTROLLER_ADDRESSES,
} from 'constants/addresses'
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import { useMemo } from 'react'
......@@ -41,67 +43,56 @@ import { Quoter, TickLens, UniswapV3Factory, UniswapV3Pool } from 'types/v3'
import { NonfungiblePositionManager } from 'types/v3/NonfungiblePositionManager'
import { V3Migrator } from 'types/v3/V3Migrator'
import { getContract } from 'utils'
import { Multicall2 } from '../abis/types'
import { ArgentWalletDetector, EnsPublicResolver, EnsRegistrar, Erc20, Multicall2, Weth } from '../abis/types'
import { UNI } from '../constants/tokens'
import { useActiveWeb3React } from './web3'
// returns null on errors
export function useContract(address: string | undefined, ABI: any, withSignerIfPossible = true): Contract | null {
const { library, account } = useActiveWeb3React()
export function useContract<T extends Contract = Contract>(
addressOrAddressMap: string | { [chainId in ChainId]?: string } | undefined,
ABI: any,
withSignerIfPossible = true
): T | null {
const { library, account, chainId } = useActiveWeb3React()
return useMemo(() => {
if (!address || !ABI || !library) return null
if (!addressOrAddressMap || !ABI || !library || !chainId) return null
let address: string | undefined
if (typeof addressOrAddressMap === 'string') address = addressOrAddressMap
else address = addressOrAddressMap[chainId]
if (!address) return null
try {
return getContract(address, ABI, library, withSignerIfPossible && account ? account : undefined)
} catch (error) {
console.error('Failed to get contract', error)
return null
}
}, [address, ABI, library, withSignerIfPossible, account])
}, [addressOrAddressMap, ABI, library, chainId, withSignerIfPossible, account]) as T
}
export function useV2MigratorContract(): V3Migrator | null {
const { chainId } = useActiveWeb3React()
return useContract(chainId && V3_MIGRATOR_ADDRESSES[chainId], V2MigratorABI, true) as V3Migrator | null
export function useV2MigratorContract() {
return useContract<V3Migrator>(V3_MIGRATOR_ADDRESSES, V2MigratorABI, true)
}
export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null {
return useContract(tokenAddress, ERC20_ABI, withSignerIfPossible)
export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean) {
return useContract<Erc20>(tokenAddress, ERC20_ABI, withSignerIfPossible)
}
export function useWETHContract(withSignerIfPossible?: boolean): Contract | null {
export function useWETHContract(withSignerIfPossible?: boolean) {
const { chainId } = useActiveWeb3React()
const address = chainId && chainId in WETH9 ? WETH9[chainId].address : undefined
return useContract(address, WETH_ABI, withSignerIfPossible)
return useContract<Weth>(chainId ? WETH9[chainId]?.address : undefined, WETH_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 useArgentWalletDetectorContract() {
return useContract<ArgentWalletDetector>(ARGENT_WALLET_DETECTOR_ADDRESS, 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 useENSRegistrarContract(withSignerIfPossible?: boolean) {
return useContract<EnsRegistrar>(ENS_REGISTRAR_ADDRESSES, 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 {
......@@ -120,61 +111,51 @@ export function useV2RouterContract(): Contract | null {
return useContract(V2_ROUTER_ADDRESS, IUniswapV2Router02ABI, true)
}
export function useMulticall2Contract(): Multicall2 | null {
const { chainId } = useActiveWeb3React()
return useContract(chainId && MULTICALL2_ADDRESSES[chainId], MULTICALL_ABI, false) as Multicall2
export function useMulticall2Contract() {
return useContract<Multicall2>(MULTICALL2_ADDRESSES, MULTICALL_ABI, false) as Multicall2
}
export function useMerkleDistributorContract(): Contract | null {
const { chainId } = useActiveWeb3React()
return useContract(chainId ? MERKLE_DISTRIBUTOR_ADDRESS[chainId] : undefined, MERKLE_DISTRIBUTOR_ABI, true)
export function useMerkleDistributorContract() {
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
}
export function useGovernanceContract(): Contract | null {
export function useGovernanceContract() {
return useContract(GOVERNANCE_ADDRESS, GOVERNANCE_ABI, true)
}
export function useUniContract(): Contract | null {
export function useUniContract() {
const { chainId } = useActiveWeb3React()
return useContract(chainId ? UNI[chainId].address : undefined, UNI_ABI, true)
return useContract(chainId ? UNI[chainId]?.address : undefined, UNI_ABI, true)
}
export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean): Contract | null {
export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
}
export function useSocksController(): Unisocks | null {
const { chainId } = useActiveWeb3React()
return useContract(
chainId === ChainId.MAINNET ? '0x65770b5283117639760beA3F867b69b3697a91dd' : undefined,
UNISOCKS_ABI,
false
) as Unisocks | null
return useContract<Unisocks>(SOCKS_CONTROLLER_ADDRESSES, UNISOCKS_ABI, false)
}
export function useV3NFTPositionManagerContract(withSignerIfPossible?: boolean): NonfungiblePositionManager | null {
const { chainId } = useActiveWeb3React()
const address = chainId ? NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[chainId] : undefined
return useContract(address, NFTPositionManagerABI, withSignerIfPossible) as NonfungiblePositionManager | null
return useContract<NonfungiblePositionManager>(
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
NFTPositionManagerABI,
withSignerIfPossible
)
}
export function useV3Factory(): UniswapV3Factory | null {
const { chainId } = useActiveWeb3React()
const address = chainId ? V3_CORE_FACTORY_ADDRESSES[chainId] : undefined
return useContract(address, V3FactoryABI) as UniswapV3Factory | null
export function useV3Factory() {
return useContract<UniswapV3Factory>(V3_CORE_FACTORY_ADDRESSES, V3FactoryABI) as UniswapV3Factory | null
}
export function useV3Pool(address: string | undefined): UniswapV3Pool | null {
return useContract(address, V3PoolABI) as UniswapV3Pool | null
export function useV3Pool(address: string | undefined) {
return useContract<UniswapV3Pool>(address, V3PoolABI)
}
export function useV3Quoter(): Quoter | null {
const { chainId } = useActiveWeb3React()
return useContract(chainId ? QUOTER_ADDRESSES[chainId] : undefined, QuoterABI) as Quoter | null
export function useV3Quoter() {
return useContract<Quoter>(QUOTER_ADDRESSES, QuoterABI)
}
export function useTickLens(): TickLens | null {
const { chainId } = useActiveWeb3React()
const address = chainId ? TICK_LENS_ADDRESSES[chainId] : undefined
return useContract(address, TickLensABI) as TickLens | null
return useContract<TickLens>(TICK_LENS_ADDRESSES, TickLensABI)
}
......@@ -4,9 +4,10 @@ import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
import { ChainId, Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { SWAP_ROUTER_ADDRESSES } from '../constants/addresses'
import { calculateGasMargin } from '../utils/calculateGasMargin'
import { getTradeVersion } from '../utils/getTradeVersion'
import { useTransactionAdder } from '../state/transactions/hooks'
import { calculateGasMargin, isAddress, shortenAddress } from '../utils'
import { isAddress, shortenAddress } from '../utils'
import isZero from '../utils/isZero'
import { useActiveWeb3React } from './web3'
import { useV2RouterContract } from './useContract'
......
......@@ -18,6 +18,7 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import { RowBetween, RowFixed } from '../../components/Row'
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
import { useUSDCValue } from '../../hooks/useUSDCPrice'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import Review from './Review'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCurrency } from '../../hooks/Tokens'
......@@ -50,7 +51,6 @@ import FeeSelector from 'components/FeeSelector'
import RangeSelector from 'components/RangeSelector'
import RateToggle from 'components/RateToggle'
import { BigNumber } from '@ethersproject/bignumber'
import { calculateGasMargin } from 'utils'
import { AddRemoveTabs } from 'components/NavigationTabs'
import HoverInlineText from 'components/HoverInlineText'
......
......@@ -18,7 +18,6 @@ import { MinimalPositionCard } from '../../components/PositionCard'
import Row, { RowBetween, RowFlat } from '../../components/Row'
import { ZERO_PERCENT } from '../../constants/misc'
import { V2_ROUTER_ADDRESS } from '../../constants/addresses'
import { useV2RouterContract } from '../../hooks/useContract'
import { PairState } from '../../hooks/useV2Pairs'
import { useActiveWeb3React } from '../../hooks/web3'
......@@ -33,7 +32,8 @@ import { useDerivedMintInfo, useMintActionHandlers, useMintState } from '../../s
import { useTransactionAdder } from '../../state/transactions/hooks'
import { useIsExpertMode, useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
import { TYPE } from '../../theme'
import { calculateGasMargin, calculateSlippageAmount } from '../../utils'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { calculateSlippageAmount } from '../../utils/calculateSlippageAmount'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { wrappedCurrency } from '../../utils/wrappedCurrency'
import AppBody from '../AppBody'
......@@ -123,14 +123,14 @@ export default function AddLiquidity({
{}
)
const router = useV2RouterContract()
// check whether the user has approved the router on the tokens
const [approvalA, approveACallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_A], V2_ROUTER_ADDRESS)
const [approvalB, approveBCallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_B], V2_ROUTER_ADDRESS)
const [approvalA, approveACallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_A], router?.address)
const [approvalB, approveBCallback] = useApproveCallback(parsedAmounts[Field.CURRENCY_B], router?.address)
const addTransaction = useTransactionAdder()
const router = useV2RouterContract()
async function onAdd() {
if (!chainId || !library || !account || !router) return
......
......@@ -8,7 +8,6 @@ import { AutoColumn } from '../../components/Column'
import CurrencyLogo from '../../components/CurrencyLogo'
import FormattedCurrencyAmount from '../../components/FormattedCurrencyAmount'
import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
import { V3_MIGRATOR_ADDRESSES } from '../../constants/addresses'
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks/web3'
......@@ -17,7 +16,8 @@ import { usePairContract, useV2MigratorContract } from '../../hooks/useContract'
import { NEVER_RELOAD, useSingleCallResult } from '../../state/multicall/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { BackArrow, ExternalLink, TYPE } from '../../theme'
import { calculateGasMargin, isAddress } from '../../utils'
import { isAddress } from '../../utils'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
import { BodyWrapper } from '../AppBody'
import { PoolState, usePool } from 'hooks/usePools'
......@@ -255,9 +255,8 @@ function V2PairMigration({
const migrator = useV2MigratorContract()
// approvals
const migratorAddress = chainId && V3_MIGRATOR_ADDRESSES[chainId]
const [approval, approveManually] = useApproveCallback(pairBalance, migratorAddress)
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(pairBalance, migratorAddress)
const [approval, approveManually] = useApproveCallback(pairBalance, migrator?.address)
const { signatureData, gatherPermitSignature } = useV2LiquidityTokenPermit(pairBalance, migrator?.address)
const approve = useCallback(async () => {
if (isNotUniswap) {
......@@ -397,8 +396,8 @@ function V2PairMigration({
<TYPE.body my={9} style={{ fontWeight: 400 }}>
This tool will safely migrate your {isNotUniswap ? 'SushiSwap' : 'V2'} liquidity to V3. The process is
completely trustless thanks to the{' '}
{chainId && migratorAddress && (
<ExternalLink href={getExplorerLink(chainId, migratorAddress, ExplorerDataType.ADDRESS)}>
{chainId && migrator && (
<ExternalLink href={getExplorerLink(chainId, migrator.address, ExplorerDataType.ADDRESS)}>
<TYPE.blue display="inline">Uniswap migration contract↗</TYPE.blue>
</ExternalLink>
)}
......
......@@ -7,6 +7,7 @@ import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import { Link, RouteComponentProps } from 'react-router-dom'
import { unwrappedToken, wrappedCurrencyAmount } from 'utils/wrappedCurrency'
import { usePositionTokenURI } from '../../hooks/usePositionTokenURI'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
import { LoadingRows } from './styleds'
import styled from 'styled-components/macro'
......@@ -15,7 +16,6 @@ import { RowBetween, RowFixed } from 'components/Row'
import DoubleCurrencyLogo from 'components/DoubleLogo'
import { ExternalLink, HideExtraSmall, TYPE } from 'theme'
import Badge from 'components/Badge'
import { calculateGasMargin } from 'utils'
import { ButtonConfirmed, ButtonPrimary, ButtonGray } from 'components/Button'
import { DarkCard, LightCard } from 'components/Card'
import CurrencyLogo from 'components/CurrencyLogo'
......
import React, { useCallback, useMemo, useState } from 'react'
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import { Redirect, RouteComponentProps } from 'react-router-dom'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import AppBody from '../AppBody'
import { BigNumber } from '@ethersproject/bignumber'
import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler'
......@@ -28,7 +29,6 @@ import Loader from 'components/Loader'
import DoubleCurrencyLogo from 'components/DoubleLogo'
import { Break } from 'components/earn/styled'
import { NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { calculateGasMargin } from 'utils'
import useTheme from 'hooks/useTheme'
import { AddRemoveTabs } from 'components/NavigationTabs'
import RangeBadge from 'components/Badge/RangeBadge'
......
......@@ -19,7 +19,6 @@ import Row, { RowBetween, RowFixed } from '../../components/Row'
import Slider from '../../components/Slider'
import CurrencyLogo from '../../components/CurrencyLogo'
import { V2_ROUTER_ADDRESS } from '../../constants/addresses'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCurrency } from '../../hooks/Tokens'
import { usePairContract, useV2RouterContract } from '../../hooks/useContract'
......@@ -28,7 +27,8 @@ import useTransactionDeadline from '../../hooks/useTransactionDeadline'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { StyledInternalLink, TYPE } from '../../theme'
import { calculateGasMargin, calculateSlippageAmount } from '../../utils'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { calculateSlippageAmount } from '../../utils/calculateSlippageAmount'
import { currencyId } from '../../utils/currencyId'
import useDebouncedChangeHandler from '../../hooks/useDebouncedChangeHandler'
import { wrappedCurrency } from '../../utils/wrappedCurrency'
......@@ -99,12 +99,14 @@ export default function RemoveLiquidity({
// pair contract
const pairContract: Contract | null = usePairContract(pair?.liquidityToken?.address)
const router = useV2RouterContract()
// allowance handling
const { gatherPermitSignature, signatureData } = useV2LiquidityTokenPermit(
parsedAmounts[Field.LIQUIDITY],
V2_ROUTER_ADDRESS
router?.address
)
const [approval, approveCallback] = useApproveCallback(parsedAmounts[Field.LIQUIDITY], V2_ROUTER_ADDRESS)
const [approval, approveCallback] = useApproveCallback(parsedAmounts[Field.LIQUIDITY], router?.address)
async function onAttemptToApprove() {
if (!pairContract || !pair || !library || !deadline) throw new Error('missing dependencies')
......@@ -145,7 +147,6 @@ export default function RemoveLiquidity({
// tx sending
const addTransaction = useTransactionAdder()
const router = useV2RouterContract()
async function onRemove() {
if (!chainId || !library || !account || !deadline || !router) throw new Error('missing dependencies')
......
......@@ -16,7 +16,11 @@ import { CardSection, DataCard } from '../../components/earn/styled'
import { RowBetween, RowFixed } from '../../components/Row'
import DelegateModal from '../../components/vote/DelegateModal'
import VoteModal from '../../components/vote/VoteModal'
import { AVERAGE_BLOCK_TIME_IN_SECS, COMMON_CONTRACT_NAMES } from '../../constants/governance'
import {
AVERAGE_BLOCK_TIME_IN_SECS,
COMMON_CONTRACT_NAMES,
DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS,
} from '../../constants/governance'
import { ZERO_ADDRESS } from '../../constants/misc'
import { UNI } from '../../constants/tokens'
import { useActiveWeb3React } from '../../hooks/web3'
......@@ -141,7 +145,11 @@ export default function VotePage({
proposalData && currentTimestamp && currentBlock
? DateTime.fromSeconds(
currentTimestamp
.add(BigNumber.from(AVERAGE_BLOCK_TIME_IN_SECS).mul(BigNumber.from(proposalData.endBlock - currentBlock)))
.add(
BigNumber.from(
(chainId && AVERAGE_BLOCK_TIME_IN_SECS[chainId]) ?? DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS
).mul(BigNumber.from(proposalData.endBlock - currentBlock))
)
.toNumber()
)
: undefined
......@@ -179,7 +187,7 @@ export default function VotePage({
// if content is contract with common name, replace address with common name
const linkIfAddress = (content: string) => {
if (isAddress(content) && chainId) {
const commonName = COMMON_CONTRACT_NAMES[content] ?? content
const commonName = COMMON_CONTRACT_NAMES[chainId]?.[content] ?? content
return (
<ExternalLink href={getExplorerLink(chainId, content, ExplorerDataType.ADDRESS)}>{commonName}</ExternalLink>
)
......
......@@ -5,8 +5,9 @@ import { useEffect, useState } from 'react'
import { UNI } from '../../constants/tokens'
import { useActiveWeb3React } from '../../hooks/web3'
import { useMerkleDistributorContract } from '../../hooks/useContract'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { useSingleCallResult } from '../multicall/hooks'
import { calculateGasMargin, isAddress } from '../../utils'
import { isAddress } from '../../utils'
import { useTransactionAdder } from '../transactions/hooks'
interface UserClaimData {
......
import { PRELOADED_PROPOSALS } from '../../constants/misc'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { isAddress } from 'ethers/lib/utils'
import { PROPOSAL_DESCRIPTION_TEXT } from '../../constants/proposals'
import { UNI } from '../../constants/tokens'
import { useGovernanceContract, useUniContract } from '../../hooks/useContract'
import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { ethers, utils } from 'ethers'
import { calculateGasMargin } from '../../utils'
import { TransactionResponse } from '@ethersproject/providers'
import { useTransactionAdder } from '../transactions/hooks'
import { useState, useEffect, useCallback, useMemo } from 'react'
......@@ -131,7 +131,7 @@ export function useAllProposalData() {
return Boolean(p.result) && Boolean(allProposalStates[i]?.result) && Boolean(formattedEvents[i])
})
.map((p, i) => {
const description = PRELOADED_PROPOSALS.get(allProposals.length - i - 1) || formattedEvents[i].description
const description = PROPOSAL_DESCRIPTION_TEXT[allProposals.length - i - 1] || formattedEvents[i].description
const formattedProposal: ProposalData = {
id: allProposals[i]?.result?.id.toString(),
title: description?.split(/# |\n/g)[1] || 'Untitled',
......
import { BigNumber } from '@ethersproject/bignumber'
import { calculateGasMargin } from './calculateGasMargin'
describe('#calculateGasMargin', () => {
it('adds 20%', () => {
expect(calculateGasMargin(BigNumber.from(1000)).toString()).toEqual('1200')
expect(calculateGasMargin(BigNumber.from(50)).toString()).toEqual('60')
})
})
import { BigNumber } from '@ethersproject/bignumber'
// add 20%
export function calculateGasMargin(value: BigNumber): BigNumber {
return value.mul(BigNumber.from(10000 + 2000)).div(BigNumber.from(10000))
}
import { AddressZero } from '@ethersproject/constants'
import { ChainId, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { calculateSlippageAmount } from './calculateSlippageAmount'
describe('#calculateSlippageAmount', () => {
it('bounds are correct', () => {
const tokenAmount = CurrencyAmount.fromRawAmount(new Token(ChainId.MAINNET, AddressZero, 0), '100')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(-1, 10_000))).toThrow('Unexpected slippage')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(10_001, 10_000))).toThrow('Unexpected slippage')
expect(calculateSlippageAmount(tokenAmount, new Percent(0, 10_000)).map((bound) => bound.toString())).toEqual([
'100',
'100',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(5, 100)).map((bound) => bound.toString())).toEqual([
'95',
'105',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(100, 10_000)).map((bound) => bound.toString())).toEqual([
'99',
'101',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(200, 10_000)).map((bound) => bound.toString())).toEqual([
'98',
'102',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(10000, 10_000)).map((bound) => bound.toString())).toEqual([
'0',
'200',
])
})
it('works for 18 decimals', () => {
const tokenAmount = CurrencyAmount.fromRawAmount(new Token(ChainId.MAINNET, AddressZero, 18), '100')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(-1, 10_000))).toThrow('Unexpected slippage')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(10_001, 10_000))).toThrow('Unexpected slippage')
expect(calculateSlippageAmount(tokenAmount, new Percent(0, 10_000)).map((bound) => bound.toString())).toEqual([
'100',
'100',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(5, 100)).map((bound) => bound.toString())).toEqual([
'95',
'105',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(100, 10_000)).map((bound) => bound.toString())).toEqual([
'99',
'101',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(200, 10_000)).map((bound) => bound.toString())).toEqual([
'98',
'102',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(10000, 10_000)).map((bound) => bound.toString())).toEqual([
'0',
'200',
])
})
})
import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
const ONE = new Fraction(1, 1)
export function calculateSlippageAmount(value: CurrencyAmount<Currency>, slippage: Percent): [JSBI, JSBI] {
if (slippage.lessThan(0) || slippage.greaterThan(ONE)) throw new Error('Unexpected slippage')
return [value.multiply(ONE.subtract(slippage)).quotient, value.multiply(ONE.add(slippage)).quotient]
}
import { ChainId } from '@uniswap/sdk-core'
import { ExplorerDataType, getExplorerLink } from './getExplorerLink'
describe('#getExplorerLink', () => {
it('correct for tx', () => {
expect(getExplorerLink(1, 'abc', ExplorerDataType.TRANSACTION)).toEqual('https://etherscan.io/tx/abc')
})
it('correct for token', () => {
expect(getExplorerLink(1, 'abc', ExplorerDataType.TOKEN)).toEqual('https://etherscan.io/token/abc')
})
it('correct for address', () => {
expect(getExplorerLink(1, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://etherscan.io/address/abc')
})
it('unrecognized chain id defaults to mainnet', () => {
expect(getExplorerLink(2, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://etherscan.io/address/abc')
})
it('ropsten', () => {
expect(getExplorerLink(3, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://ropsten.etherscan.io/address/abc')
})
it('enum', () => {
expect(getExplorerLink(ChainId.RINKEBY, 'abc', ExplorerDataType.ADDRESS)).toEqual(
'https://rinkeby.etherscan.io/address/abc'
)
})
})
import { BigNumber } from '@ethersproject/bignumber'
import { AddressZero } from '@ethersproject/constants'
import { ChainId, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { calculateGasMargin, calculateSlippageAmount, isAddress, shortenAddress } from '.'
import { ExplorerDataType, getExplorerLink } from './getExplorerLink'
import { isAddress, shortenAddress } from '.'
describe('utils', () => {
describe('#getExplorerLink', () => {
it('correct for tx', () => {
expect(getExplorerLink(1, 'abc', ExplorerDataType.TRANSACTION)).toEqual('https://etherscan.io/tx/abc')
})
it('correct for token', () => {
expect(getExplorerLink(1, 'abc', ExplorerDataType.TOKEN)).toEqual('https://etherscan.io/token/abc')
})
it('correct for address', () => {
expect(getExplorerLink(1, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://etherscan.io/address/abc')
})
it('unrecognized chain id defaults to mainnet', () => {
expect(getExplorerLink(2, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://etherscan.io/address/abc')
})
it('ropsten', () => {
expect(getExplorerLink(3, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://ropsten.etherscan.io/address/abc')
})
it('enum', () => {
expect(getExplorerLink(ChainId.RINKEBY, 'abc', ExplorerDataType.ADDRESS)).toEqual(
'https://rinkeby.etherscan.io/address/abc'
)
})
})
describe('#calculateSlippageAmount', () => {
it('bounds are correct', () => {
const tokenAmount = CurrencyAmount.fromRawAmount(new Token(ChainId.MAINNET, AddressZero, 0), '100')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(-1, 10_000))).toThrow('Unexpected slippage')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(10_001, 10_000))).toThrow('Unexpected slippage')
expect(calculateSlippageAmount(tokenAmount, new Percent(0, 10_000)).map((bound) => bound.toString())).toEqual([
'100',
'100',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(5, 100)).map((bound) => bound.toString())).toEqual([
'95',
'105',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(100, 10_000)).map((bound) => bound.toString())).toEqual([
'99',
'101',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(200, 10_000)).map((bound) => bound.toString())).toEqual([
'98',
'102',
])
expect(
calculateSlippageAmount(tokenAmount, new Percent(10000, 10_000)).map((bound) => bound.toString())
).toEqual(['0', '200'])
})
it('works for 18 decimals', () => {
const tokenAmount = CurrencyAmount.fromRawAmount(new Token(ChainId.MAINNET, AddressZero, 18), '100')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(-1, 10_000))).toThrow('Unexpected slippage')
expect(() => calculateSlippageAmount(tokenAmount, new Percent(10_001, 10_000))).toThrow('Unexpected slippage')
expect(calculateSlippageAmount(tokenAmount, new Percent(0, 10_000)).map((bound) => bound.toString())).toEqual([
'100',
'100',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(5, 100)).map((bound) => bound.toString())).toEqual([
'95',
'105',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(100, 10_000)).map((bound) => bound.toString())).toEqual([
'99',
'101',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(200, 10_000)).map((bound) => bound.toString())).toEqual([
'98',
'102',
])
expect(
calculateSlippageAmount(tokenAmount, new Percent(10000, 10_000)).map((bound) => bound.toString())
).toEqual(['0', '200'])
})
})
describe('#isAddress', () => {
it('returns false if not', () => {
expect(isAddress('')).toBe(false)
......@@ -118,11 +40,4 @@ describe('utils', () => {
expect(shortenAddress('0x2E1b342132A67Ea578e4E3B814bae2107dc254CC'.toLowerCase())).toBe('0x2E1b...54CC')
})
})
describe('#calculateGasMargin', () => {
it('adds 20%', () => {
expect(calculateGasMargin(BigNumber.from(1000)).toString()).toEqual('1200')
expect(calculateGasMargin(BigNumber.from(50)).toString()).toEqual('60')
})
})
})
import { getAddress } from '@ethersproject/address'
import { BigNumber } from '@ethersproject/bignumber'
import { AddressZero } from '@ethersproject/constants'
import { Contract } from '@ethersproject/contracts'
import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers'
import { ChainId, Currency, CurrencyAmount, Fraction, Percent, Token } from '@uniswap/sdk-core'
import { ChainId, Token } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk/dist/'
import JSBI from 'jsbi'
import { TokenAddressMap } from '../state/lists/hooks'
// returns the checksummed address if the address is valid, otherwise returns false
......@@ -26,17 +24,6 @@ export function shortenAddress(address: string, chars = 4): string {
return `${parsed.substring(0, chars + 2)}...${parsed.substring(42 - chars)}`
}
// add 20%
export function calculateGasMargin(value: BigNumber): BigNumber {
return value.mul(BigNumber.from(10000 + 2000)).div(BigNumber.from(10000))
}
const ONE = new Fraction(1, 1)
export function calculateSlippageAmount(value: CurrencyAmount<Currency>, slippage: Percent): [JSBI, JSBI] {
if (slippage.lessThan(0) || slippage.greaterThan(ONE)) throw new Error('Unexpected slippage')
return [value.multiply(ONE.subtract(slippage)).quotient, value.multiply(ONE.add(slippage)).quotient]
}
// account is not optional
export function getSigner(library: Web3Provider, account: string): JsonRpcSigner {
return library.getSigner(account).connectUnchecked()
......
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