Commit 1bb4db54 authored by Moody Salem's avatar Moody Salem Committed by GitHub

Make the hooks directory strict (#817)

* Make the hooks directory strict

* Move using the v1 factory contract to hooks

* Add a comment to why we copy the token map

* Fix another lint error and make AllTokens deep readonly

* Move ALL_TOKENS to constants directory
parent 536de89a
...@@ -3,8 +3,9 @@ import { transparentize } from 'polished' ...@@ -3,8 +3,9 @@ import { transparentize } from 'polished'
import React, { useMemo } from 'react' import React, { useMemo } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { ReactComponent as Close } from '../../assets/images/x.svg' import { ReactComponent as Close } from '../../assets/images/x.svg'
import { ALL_TOKENS } from '../../constants/tokens'
import { useActiveWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { ALL_TOKENS, useAllTokens } from '../../hooks/Tokens' import { useAllTokens } from '../../hooks/Tokens'
import { Field } from '../../state/swap/actions' import { Field } from '../../state/swap/actions'
import { useTokenWarningDismissal } from '../../state/user/hooks' import { useTokenWarningDismissal } from '../../state/user/hooks'
import { Link, TYPE } from '../../theme' import { Link, TYPE } from '../../theme'
......
import { ChainId, Token, WETH } from '@uniswap/sdk'
import KOVAN_TOKENS from './kovan'
import MAINNET_TOKENS from './mainnet'
import RINKEBY_TOKENS from './rinkeby'
import ROPSTEN_TOKENS from './ropsten'
type AllTokens = Readonly<{ [chainId in ChainId]: Readonly<{ [tokenAddress: string]: Token }> }>
export const ALL_TOKENS: AllTokens = [
// WETH on all chains
...Object.values(WETH),
// chain-specific tokens
...MAINNET_TOKENS,
...RINKEBY_TOKENS,
...KOVAN_TOKENS,
...ROPSTEN_TOKENS
]
// remap WETH to ETH
.map(token => {
if (token.equals(WETH[token.chainId])) {
;(token as any).symbol = 'ETH'
;(token as any).name = 'Ether'
}
return token
})
// put into an object
.reduce<AllTokens>(
(tokenMap, token) => {
if (tokenMap[token.chainId][token.address] !== undefined) throw Error('Duplicate tokens.')
return {
...tokenMap,
[token.chainId]: {
...tokenMap[token.chainId],
[token.address]: token
}
}
},
{
[ChainId.MAINNET]: {},
[ChainId.RINKEBY]: {},
[ChainId.GÖRLI]: {},
[ChainId.ROPSTEN]: {},
[ChainId.KOVAN]: {}
}
)
import { Contract } from '@ethersproject/contracts' import { Contract } from '@ethersproject/contracts'
import { Token, TokenAmount, Pair } from '@uniswap/sdk' import { Token, TokenAmount, Pair } from '@uniswap/sdk'
import useSWR from 'swr' import useSWR from 'swr'
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { SWRKeys, useKeepSWRDataLiveAsBlocksArrive } from '.' import { SWRKeys, useKeepSWRDataLiveAsBlocksArrive } from '.'
import { useContract } from '../hooks' import { usePairContract } from '../hooks'
function getReserves(contract: Contract, tokenA: Token, tokenB: Token): () => Promise<Pair | null> { function getReserves(contract: Contract, tokenA: Token, tokenB: Token): () => Promise<Pair | null> {
return async (): Promise<Pair | null> => return async (): Promise<Pair | null> =>
...@@ -28,7 +27,7 @@ function getReserves(contract: Contract, tokenA: Token, tokenB: Token): () => Pr ...@@ -28,7 +27,7 @@ function getReserves(contract: Contract, tokenA: Token, tokenB: Token): () => Pr
*/ */
export function usePair(tokenA?: Token, tokenB?: Token): undefined | Pair | null { export function usePair(tokenA?: Token, tokenB?: Token): undefined | Pair | null {
const pairAddress = !!tokenA && !!tokenB && !tokenA.equals(tokenB) ? Pair.getAddress(tokenA, tokenB) : undefined const pairAddress = !!tokenA && !!tokenB && !tokenA.equals(tokenB) ? Pair.getAddress(tokenA, tokenB) : undefined
const contract = useContract(pairAddress, IUniswapV2PairABI, false) const contract = usePairContract(pairAddress, false)
const shouldFetch = !!contract const shouldFetch = !!contract
const key = shouldFetch ? [pairAddress, tokenA.chainId, SWRKeys.Reserves] : null const key = shouldFetch ? [pairAddress, tokenA.chainId, SWRKeys.Reserves] : null
......
import { Contract } from '@ethersproject/contracts' import { Contract } from '@ethersproject/contracts'
import { Token, TokenAmount } from '@uniswap/sdk' import { Token, TokenAmount } from '@uniswap/sdk'
import useSWR from 'swr' import useSWR from 'swr'
import { abi as IERC20ABI } from '@uniswap/v2-core/build/IERC20.json'
import { SWRKeys, useKeepSWRDataLiveAsBlocksArrive } from '.' import { SWRKeys, useKeepSWRDataLiveAsBlocksArrive } from '.'
import { useContract } from '../hooks' import { useTokenContract } from '../hooks'
function getTotalSupply(contract: Contract, token: Token): () => Promise<TokenAmount> { function getTotalSupply(contract: Contract, token: Token): () => Promise<TokenAmount> {
return async (): Promise<TokenAmount> => return async (): Promise<TokenAmount> =>
...@@ -14,7 +13,7 @@ function getTotalSupply(contract: Contract, token: Token): () => Promise<TokenAm ...@@ -14,7 +13,7 @@ function getTotalSupply(contract: Contract, token: Token): () => Promise<TokenAm
} }
export function useTotalSupply(token?: Token): TokenAmount { export function useTotalSupply(token?: Token): TokenAmount {
const contract = useContract(token?.address, IERC20ABI, false) const contract = useTokenContract(token?.address, false)
const shouldFetch = !!contract const shouldFetch = !!contract
const { data, mutate } = useSWR( const { data, mutate } = useSWR(
......
...@@ -2,10 +2,7 @@ import { Contract } from '@ethersproject/contracts' ...@@ -2,10 +2,7 @@ import { Contract } from '@ethersproject/contracts'
import { Token, TokenAmount, Pair, Trade, ChainId, WETH, Route, TradeType, Percent } from '@uniswap/sdk' import { Token, TokenAmount, Pair, Trade, ChainId, WETH, Route, TradeType, Percent } from '@uniswap/sdk'
import useSWR from 'swr' import useSWR from 'swr'
import { useActiveWeb3React } from '../hooks' import { useActiveWeb3React } from '../hooks'
import { useV1FactoryContract } from '../hooks'
import IUniswapV1Factory from '../constants/abis/v1_factory.json'
import { V1_FACTORY_ADDRESS } from '../constants'
import { useContract } from '../hooks'
import { SWRKeys } from '.' import { SWRKeys } from '.'
import { useETHBalances, useTokenBalances } from '../state/wallet/hooks' import { useETHBalances, useTokenBalances } from '../state/wallet/hooks'
...@@ -16,7 +13,7 @@ function getV1PairAddress(contract: Contract): (tokenAddress: string) => Promise ...@@ -16,7 +13,7 @@ function getV1PairAddress(contract: Contract): (tokenAddress: string) => Promise
function useV1PairAddress(tokenAddress: string) { function useV1PairAddress(tokenAddress: string) {
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const contract = useContract(V1_FACTORY_ADDRESS, IUniswapV1Factory, false) const contract = useV1FactoryContract()
const shouldFetch = chainId === ChainId.MAINNET && typeof tokenAddress === 'string' && !!contract const shouldFetch = chainId === ChainId.MAINNET && typeof tokenAddress === 'string' && !!contract
const { data } = useSWR(shouldFetch ? [tokenAddress, SWRKeys.V1PairAddress] : null, getV1PairAddress(contract), { const { data } = useSWR(shouldFetch ? [tokenAddress, SWRKeys.V1PairAddress] : null, getV1PairAddress(contract), {
......
import { ChainId, Token, WETH } from '@uniswap/sdk' import { ChainId, Token } from '@uniswap/sdk'
import { useEffect, useMemo } from 'react' import { useEffect, useMemo } from 'react'
import { ALL_TOKENS } from '../constants/tokens'
import { useAddUserToken, useFetchTokenByAddress, useUserAddedTokens } from '../state/user/hooks' import { useAddUserToken, useFetchTokenByAddress, useUserAddedTokens } from '../state/user/hooks'
import { useActiveWeb3React } from './index' import { useActiveWeb3React } from './index'
import MAINNET_TOKENS from '../constants/tokens/mainnet'
import RINKEBY_TOKENS from '../constants/tokens/rinkeby'
import KOVAN_TOKENS from '../constants/tokens/kovan'
import ROPSTEN_TOKENS from '../constants/tokens/ropsten'
type AllTokens = { [chainId in ChainId]?: { [tokenAddress: string]: Token } }
export const ALL_TOKENS: Readonly<AllTokens> = [
// WETH on all chains
...Object.values(WETH),
// chain-specific tokens
...MAINNET_TOKENS,
...RINKEBY_TOKENS,
...KOVAN_TOKENS,
...ROPSTEN_TOKENS
]
// remap WETH to ETH
.map(token => {
if (token.equals(WETH[token.chainId])) {
;(token as any).symbol = 'ETH'
;(token as any).name = 'Ether'
}
return token
})
// put into an object
.reduce<AllTokens>((tokenMap, token) => {
if (tokenMap?.[token.chainId]?.[token.address] !== undefined) throw Error('Duplicate tokens.')
return {
...tokenMap,
[token.chainId]: {
...tokenMap?.[token.chainId],
[token.address]: token
}
}
}, {})
export function useAllTokens(): { [address: string]: Token } { export function useAllTokens(): { [address: string]: Token } {
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
...@@ -52,7 +19,9 @@ export function useAllTokens(): { [address: string]: Token } { ...@@ -52,7 +19,9 @@ export function useAllTokens(): { [address: string]: Token } {
tokenMap[token.address] = token tokenMap[token.address] = token
return tokenMap return tokenMap
}, },
{ ...ALL_TOKENS[chainId] } // must make a copy because reduce modifies the map, and we do not
// want to make a copy in every iteration
{ ...ALL_TOKENS[chainId as ChainId] }
) )
) )
}, [userAddedTokens, chainId]) }, [userAddedTokens, chainId])
...@@ -81,5 +50,5 @@ export function useTokenByAddressAndAutomaticallyAdd(tokenAddress?: string): Tok ...@@ -81,5 +50,5 @@ export function useTokenByAddressAndAutomaticallyAdd(tokenAddress?: string): Tok
} }
}, [tokenAddress, allTokens, fetchTokenByAddress, addToken]) }, [tokenAddress, allTokens, fetchTokenByAddress, addToken])
return allTokens?.[tokenAddress] return tokenAddress ? allTokens?.[tokenAddress] : undefined
} }
...@@ -12,28 +12,31 @@ function useAllCommonPairs(tokenA?: Token, tokenB?: Token): Pair[] { ...@@ -12,28 +12,31 @@ function useAllCommonPairs(tokenA?: Token, tokenB?: Token): Pair[] {
const pairBetween = usePair(tokenA, tokenB) const pairBetween = usePair(tokenA, tokenB)
// get token<->WETH pairs // get token<->WETH pairs
const aToETH = usePair(tokenA, WETH[chainId]) const aToETH = usePair(tokenA, WETH[chainId as ChainId])
const bToETH = usePair(tokenB, WETH[chainId]) const bToETH = usePair(tokenB, WETH[chainId as ChainId])
// get token<->DAI pairs // get token<->DAI pairs
const aToDAI = usePair(tokenA, chainId === ChainId.MAINNET ? DAI : null) const aToDAI = usePair(tokenA, chainId === ChainId.MAINNET ? DAI : undefined)
const bToDAI = usePair(tokenB, chainId === ChainId.MAINNET ? DAI : null) const bToDAI = usePair(tokenB, chainId === ChainId.MAINNET ? DAI : undefined)
// get token<->USDC pairs // get token<->USDC pairs
const aToUSDC = usePair(tokenA, chainId === ChainId.MAINNET ? USDC : null) const aToUSDC = usePair(tokenA, chainId === ChainId.MAINNET ? USDC : undefined)
const bToUSDC = usePair(tokenB, chainId === ChainId.MAINNET ? USDC : null) const bToUSDC = usePair(tokenB, chainId === ChainId.MAINNET ? USDC : undefined)
// get connecting pairs // get connecting pairs
const DAIToETH = usePair(chainId === ChainId.MAINNET ? DAI : null, WETH[chainId]) const DAIToETH = usePair(chainId === ChainId.MAINNET ? DAI : undefined, WETH[chainId as ChainId])
const USDCToETH = usePair(chainId === ChainId.MAINNET ? USDC : null, WETH[chainId]) const USDCToETH = usePair(chainId === ChainId.MAINNET ? USDC : undefined, WETH[chainId as ChainId])
const DAIToUSDC = usePair(chainId === ChainId.MAINNET ? DAI : null, chainId === ChainId.MAINNET ? USDC : null) const DAIToUSDC = usePair(
chainId === ChainId.MAINNET ? DAI : undefined,
chainId === ChainId.MAINNET ? USDC : undefined
)
// only pass along valid pairs, non-duplicated pairs // only pass along valid pairs, non-duplicated pairs
return useMemo( return useMemo(
() => () =>
[pairBetween, aToETH, bToETH, aToDAI, bToDAI, aToUSDC, bToUSDC, DAIToETH, USDCToETH, DAIToUSDC] [pairBetween, aToETH, bToETH, aToDAI, bToDAI, aToUSDC, bToUSDC, DAIToETH, USDCToETH, DAIToUSDC]
// filter out invalid pairs // filter out invalid pairs
.filter(p => !!p) .filter((p): p is Pair => !!p)
// filter out duplicated pairs // filter out duplicated pairs
.filter( .filter(
(p, i, pairs) => i === pairs.findIndex(pair => pair?.liquidityToken.address === p.liquidityToken.address) (p, i, pairs) => i === pairs.findIndex(pair => pair?.liquidityToken.address === p.liquidityToken.address)
......
interface Window {
ethereum?: {
isMetaMask?: true
on?: (...args: any[]) => void
removeListener?: (...args: any[]) => void
}
web3?: {}
}
...@@ -5,10 +5,12 @@ import { useWeb3React as useWeb3ReactCore } from '@web3-react/core' ...@@ -5,10 +5,12 @@ import { useWeb3React as useWeb3ReactCore } from '@web3-react/core'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import IUniswapV1Factory from '../constants/abis/v1_factory.json'
import ERC20_ABI from '../constants/abis/erc20.json' import ERC20_ABI from '../constants/abis/erc20.json'
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { injected } from '../connectors' import { injected } from '../connectors'
import { NetworkContextName } from '../constants' import { NetworkContextName, V1_FACTORY_ADDRESS } from '../constants'
import { getContract, getExchangeContract, isAddress } from '../utils' import { getContract, isAddress } from '../utils'
export function useActiveWeb3React() { export function useActiveWeb3React() {
const context = useWeb3ReactCore<Web3Provider>() const context = useWeb3ReactCore<Web3Provider>()
...@@ -66,7 +68,7 @@ export function useInactiveListener(suppress = false) { ...@@ -66,7 +68,7 @@ export function useInactiveListener(suppress = false) {
}) })
} }
const handleAccountsChanged = accounts => { const handleAccountsChanged = (accounts: string[]) => {
if (accounts.length > 0) { if (accounts.length > 0) {
// eat errors // eat errors
activate(injected, undefined, true).catch(error => { activate(injected, undefined, true).catch(error => {
...@@ -94,6 +96,7 @@ export function useInactiveListener(suppress = false) { ...@@ -94,6 +96,7 @@ export function useInactiveListener(suppress = false) {
} }
} }
} }
return
}, [active, error, suppress, activate]) }, [active, error, suppress, activate])
} }
...@@ -119,7 +122,7 @@ export function useDebounce<T>(value: T, delay: number): T { ...@@ -119,7 +122,7 @@ export function useDebounce<T>(value: T, delay: number): T {
} }
// modified from https://usehooks.com/useKeyPress/ // modified from https://usehooks.com/useKeyPress/
export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false) { export function useBodyKeyDown(targetKey: string, onKeyDown: () => void, suppressOnKeyDown = false) {
const downHandler = useCallback( const downHandler = useCallback(
event => { event => {
const { const {
...@@ -142,12 +145,13 @@ export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false) ...@@ -142,12 +145,13 @@ export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false)
}, [downHandler]) }, [downHandler])
} }
export function useENSName(address) { export function useENSName(address?: string): string | null {
const { library } = useActiveWeb3React() const { library } = useActiveWeb3React()
const [ENSName, setENSName] = useState<string | null>(null) const [ENSName, setENSName] = useState<string | null>(null)
useEffect(() => { useEffect(() => {
if (!library || !address) return
if (isAddress(address)) { if (isAddress(address)) {
let stale = false let stale = false
library library
...@@ -172,47 +176,37 @@ export function useENSName(address) { ...@@ -172,47 +176,37 @@ export function useENSName(address) {
setENSName(null) setENSName(null)
} }
} }
return
}, [library, address]) }, [library, address])
return ENSName return ENSName
} }
// returns null on errors // returns null on errors
export function useContract(address, ABI, withSignerIfPossible = true) { function useContract(address?: string, ABI?: any, withSignerIfPossible = true): Contract | null {
const { library, account } = useActiveWeb3React() const { library, account } = useActiveWeb3React()
return useMemo(() => { return useMemo(() => {
if (!address || !ABI || !library) return null
try { try {
return getContract(address, ABI, library, withSignerIfPossible ? account : undefined) return getContract(address, ABI, library, withSignerIfPossible && account ? account : undefined)
} catch { } catch {
return null return null
} }
}, [address, ABI, library, withSignerIfPossible, account]) }, [address, ABI, library, withSignerIfPossible, account])
} }
// returns null on errors export function useV1FactoryContract(): Contract | null {
export function useTokenContract(tokenAddress: string, withSignerIfPossible = true): Contract { return useContract(V1_FACTORY_ADDRESS, IUniswapV1Factory, false)
const { library, account } = useActiveWeb3React()
return useMemo(() => {
try {
return getContract(tokenAddress, ERC20_ABI, library, withSignerIfPossible ? account : undefined)
} catch {
return null
}
}, [tokenAddress, library, withSignerIfPossible, account])
} }
export function usePairContract(pairAddress, withSignerIfPossible = true) { // returns null on errors
const { library, account } = useActiveWeb3React() export function useTokenContract(tokenAddress?: string, withSignerIfPossible = true): Contract | null {
return useContract(tokenAddress, ERC20_ABI, withSignerIfPossible)
}
return useMemo(() => { export function usePairContract(pairAddress?: string, withSignerIfPossible = true): Contract | null {
try { return useContract(pairAddress, IUniswapV2PairABI, withSignerIfPossible)
return getExchangeContract(pairAddress, library, withSignerIfPossible ? account : undefined)
} catch {
return null
}
}, [pairAddress, library, withSignerIfPossible, account])
} }
export function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => void] { export function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => void] {
...@@ -233,16 +227,17 @@ export function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => v ...@@ -233,16 +227,17 @@ export function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => v
clearTimeout(hide) clearTimeout(hide)
} }
} }
return
}, [isCopied, setIsCopied, timeout]) }, [isCopied, setIsCopied, timeout])
return [isCopied, staticCopy] return [isCopied, staticCopy]
} }
// modified from https://usehooks.com/usePrevious/ // modified from https://usehooks.com/usePrevious/
export function usePrevious(value) { export function usePrevious<T>(value: T) {
// The ref object is a generic container whose current property is mutable ... // The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class // ... and can hold any value, similar to an instance property on a class
const ref = useRef() const ref = useRef<T>()
// Store current value in ref // Store current value in ref
useEffect(() => { useEffect(() => {
......
{
"extends": "../../tsconfig.strict.json",
"include": ["**/*"]
}
\ No newline at end of file
import { MaxUint256 } from '@ethersproject/constants' import { MaxUint256 } from '@ethersproject/constants'
import { TransactionResponse } from '@ethersproject/providers'
import { Trade, WETH, TokenAmount } from '@uniswap/sdk' import { Trade, WETH, TokenAmount } from '@uniswap/sdk'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import { ROUTER_ADDRESS } from '../constants' import { ROUTER_ADDRESS } from '../constants'
...@@ -9,7 +10,7 @@ import { computeSlippageAdjustedAmounts } from '../utils/prices' ...@@ -9,7 +10,7 @@ import { computeSlippageAdjustedAmounts } from '../utils/prices'
import { calculateGasMargin } from '../utils' import { calculateGasMargin } from '../utils'
import { useTokenContract, useActiveWeb3React } from './index' import { useTokenContract, useActiveWeb3React } from './index'
export enum Approval { export enum ApprovalState {
UNKNOWN, UNKNOWN,
NOT_APPROVED, NOT_APPROVED,
PENDING, PENDING,
...@@ -20,29 +21,40 @@ export enum Approval { ...@@ -20,29 +21,40 @@ export enum Approval {
export function useApproveCallback( export function useApproveCallback(
amountToApprove?: TokenAmount, amountToApprove?: TokenAmount,
addressToApprove?: string addressToApprove?: string
): [Approval, () => Promise<void>] { ): [ApprovalState, () => Promise<void>] {
const { account } = useActiveWeb3React() const { account } = useActiveWeb3React()
const currentAllowance = useTokenAllowance(amountToApprove?.token, account, addressToApprove) const currentAllowance = useTokenAllowance(amountToApprove?.token, account ?? undefined, addressToApprove)
const pendingApproval = useHasPendingApproval(amountToApprove?.token?.address) const pendingApproval = useHasPendingApproval(amountToApprove?.token?.address)
// check the current approval status // check the current approval status
const approval = useMemo(() => { const approval = useMemo(() => {
if (!amountToApprove) return ApprovalState.UNKNOWN
// we treat WETH as ETH which requires no approvals // we treat WETH as ETH which requires no approvals
if (amountToApprove?.token?.equals(WETH[amountToApprove?.token?.chainId])) return Approval.APPROVED if (amountToApprove.token.equals(WETH[amountToApprove.token.chainId])) return ApprovalState.APPROVED
// we might not have enough data to know whether or not we need to approve // we might not have enough data to know whether or not we need to approve
if (!currentAllowance) return Approval.UNKNOWN if (!currentAllowance) return ApprovalState.UNKNOWN
if (pendingApproval) return Approval.PENDING if (pendingApproval) return ApprovalState.PENDING
// amountToApprove will be defined if currentAllowance is // amountToApprove will be defined if currentAllowance is
return currentAllowance.lessThan(amountToApprove) ? Approval.NOT_APPROVED : Approval.APPROVED return currentAllowance.lessThan(amountToApprove) ? ApprovalState.NOT_APPROVED : ApprovalState.APPROVED
}, [amountToApprove, currentAllowance, pendingApproval]) }, [amountToApprove, currentAllowance, pendingApproval])
const tokenContract = useTokenContract(amountToApprove?.token?.address) const tokenContract = useTokenContract(amountToApprove?.token?.address)
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const approve = useCallback(async (): Promise<void> => { const approve = useCallback(async (): Promise<void> => {
if (approval !== Approval.NOT_APPROVED) { if (approval !== ApprovalState.NOT_APPROVED) {
console.error('approve was called unnecessarily, this is likely an error.') console.error('approve was called unnecessarily')
return
}
if (!tokenContract) {
console.error('tokenContract is null')
return
}
if (!amountToApprove) {
console.error('missing amount to approve')
return return
} }
...@@ -57,13 +69,13 @@ export function useApproveCallback( ...@@ -57,13 +69,13 @@ export function useApproveCallback(
.approve(addressToApprove, useExact ? amountToApprove.raw.toString() : MaxUint256, { .approve(addressToApprove, useExact ? amountToApprove.raw.toString() : MaxUint256, {
gasLimit: calculateGasMargin(estimatedGas) gasLimit: calculateGasMargin(estimatedGas)
}) })
.then(response => { .then((response: TransactionResponse) => {
addTransaction(response, { addTransaction(response, {
summary: 'Approve ' + amountToApprove?.token?.symbol, summary: 'Approve ' + amountToApprove?.token?.symbol,
approvalOfToken: amountToApprove?.token?.address approvalOfToken: amountToApprove?.token?.address
}) })
}) })
.catch(error => { .catch((error: Error) => {
console.debug('Failed to approve token', error) console.debug('Failed to approve token', error)
throw error throw error
}) })
...@@ -74,9 +86,9 @@ export function useApproveCallback( ...@@ -74,9 +86,9 @@ export function useApproveCallback(
// wraps useApproveCallback in the context of a swap // wraps useApproveCallback in the context of a swap
export function useApproveCallbackFromTrade(trade?: Trade, allowedSlippage = 0) { export function useApproveCallbackFromTrade(trade?: Trade, allowedSlippage = 0) {
const amountToApprove = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage)[Field.INPUT], [ const amountToApprove = useMemo(
trade, () => (trade ? computeSlippageAdjustedAmounts(trade, allowedSlippage)[Field.INPUT] : undefined),
allowedSlippage [trade, allowedSlippage]
]) )
return useApproveCallback(amountToApprove, ROUTER_ADDRESS) return useApproveCallback(amountToApprove, ROUTER_ADDRESS)
} }
...@@ -11,12 +11,14 @@ export default function useInterval(callback: () => void, delay: null | number) ...@@ -11,12 +11,14 @@ export default function useInterval(callback: () => void, delay: null | number)
// Set up the interval. // Set up the interval.
useEffect(() => { useEffect(() => {
function tick() { function tick() {
savedCallback.current() const current = savedCallback.current
current && current()
} }
if (delay !== null) { if (delay !== null) {
const id = setInterval(tick, delay) const id = setInterval(tick, delay)
return () => clearInterval(id) return () => clearInterval(id)
} }
return
}, [delay]) }, [delay])
} }
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { WETH, TokenAmount, JSBI } from '@uniswap/sdk' import { TransactionResponse } from '@ethersproject/providers'
import { WETH, TokenAmount, JSBI, ChainId } from '@uniswap/sdk'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useTransactionAdder } from '../state/transactions/hooks' import { useTransactionAdder } from '../state/transactions/hooks'
import { useTokenBalanceTreatingWETHasETH } from '../state/wallet/hooks' import { useTokenBalanceTreatingWETHasETH } from '../state/wallet/hooks'
...@@ -14,7 +15,7 @@ export function useSendCallback(amount?: TokenAmount, recipient?: string): null ...@@ -14,7 +15,7 @@ export function useSendCallback(amount?: TokenAmount, recipient?: string): null
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const ensName = useENSName(recipient) const ensName = useENSName(recipient)
const tokenContract = useTokenContract(amount?.token?.address) const tokenContract = useTokenContract(amount?.token?.address)
const balance = useTokenBalanceTreatingWETHasETH(account, amount?.token) const balance = useTokenBalanceTreatingWETHasETH(account ?? undefined, amount?.token)
return useMemo(() => { return useMemo(() => {
if (!amount) return null if (!amount) return null
...@@ -26,16 +27,19 @@ export function useSendCallback(amount?: TokenAmount, recipient?: string): null ...@@ -26,16 +27,19 @@ export function useSendCallback(amount?: TokenAmount, recipient?: string): null
const token = amount?.token const token = amount?.token
return async function onSend(): Promise<string> { return async function onSend(): Promise<string> {
if (token.equals(WETH[chainId])) { if (!chainId || !library || !account || !tokenContract) {
throw new Error('missing dependencies in onSend callback')
}
if (token.equals(WETH[chainId as ChainId])) {
return getSigner(library, account) return getSigner(library, account)
.sendTransaction({ to: recipient, value: BigNumber.from(amount.raw.toString()) }) .sendTransaction({ to: recipient, value: BigNumber.from(amount.raw.toString()) })
.then(response => { .then((response: TransactionResponse) => {
addTransaction(response, { addTransaction(response, {
summary: 'Send ' + amount.toSignificant(3) + ' ' + token?.symbol + ' to ' + (ensName ?? recipient) summary: 'Send ' + amount.toSignificant(3) + ' ' + token?.symbol + ' to ' + (ensName ?? recipient)
}) })
return response.hash return response.hash
}) })
.catch(error => { .catch((error: Error) => {
console.error('Failed to transfer ETH', error) console.error('Failed to transfer ETH', error)
throw error throw error
}) })
...@@ -47,7 +51,7 @@ export function useSendCallback(amount?: TokenAmount, recipient?: string): null ...@@ -47,7 +51,7 @@ export function useSendCallback(amount?: TokenAmount, recipient?: string): null
.transfer(recipient, amount.raw.toString(), { .transfer(recipient, amount.raw.toString(), {
gasLimit: calculateGasMargin(estimatedGasLimit) gasLimit: calculateGasMargin(estimatedGasLimit)
}) })
.then(response => { .then((response: TransactionResponse) => {
addTransaction(response, { addTransaction(response, {
summary: 'Send ' + amount.toSignificant(3) + ' ' + token.symbol + ' to ' + (ensName ?? recipient) summary: 'Send ' + amount.toSignificant(3) + ' ' + token.symbol + ' to ' + (ensName ?? recipient)
}) })
......
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { Contract } from '@ethersproject/contracts' import { Contract } from '@ethersproject/contracts'
import { Token, Trade, TradeType, WETH } from '@uniswap/sdk' import { ChainId, Token, Trade, TradeType, WETH } from '@uniswap/sdk'
import { useMemo } from 'react' import { useMemo } from 'react'
import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE, ROUTER_ADDRESS } from '../constants' import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE, ROUTER_ADDRESS } from '../constants'
import { useTokenAllowance } from '../data/Allowances' import { useTokenAllowance } from '../data/Allowances'
...@@ -21,17 +21,17 @@ enum SwapType { ...@@ -21,17 +21,17 @@ enum SwapType {
function getSwapType(tokens: { [field in Field]?: Token }, isExactIn: boolean, chainId: number): SwapType { function getSwapType(tokens: { [field in Field]?: Token }, isExactIn: boolean, chainId: number): SwapType {
if (isExactIn) { if (isExactIn) {
if (tokens[Field.INPUT]?.equals(WETH[chainId])) { if (tokens[Field.INPUT]?.equals(WETH[chainId as ChainId])) {
return SwapType.EXACT_ETH_FOR_TOKENS return SwapType.EXACT_ETH_FOR_TOKENS
} else if (tokens[Field.OUTPUT]?.equals(WETH[chainId])) { } else if (tokens[Field.OUTPUT]?.equals(WETH[chainId as ChainId])) {
return SwapType.EXACT_TOKENS_FOR_ETH return SwapType.EXACT_TOKENS_FOR_ETH
} else { } else {
return SwapType.EXACT_TOKENS_FOR_TOKENS return SwapType.EXACT_TOKENS_FOR_TOKENS
} }
} else { } else {
if (tokens[Field.INPUT]?.equals(WETH[chainId])) { if (tokens[Field.INPUT]?.equals(WETH[chainId as ChainId])) {
return SwapType.ETH_FOR_EXACT_TOKENS return SwapType.ETH_FOR_EXACT_TOKENS
} else if (tokens[Field.OUTPUT]?.equals(WETH[chainId])) { } else if (tokens[Field.OUTPUT]?.equals(WETH[chainId as ChainId])) {
return SwapType.TOKENS_FOR_EXACT_ETH return SwapType.TOKENS_FOR_EXACT_ETH
} else { } else {
return SwapType.TOKENS_FOR_EXACT_TOKENS return SwapType.TOKENS_FOR_EXACT_TOKENS
...@@ -48,27 +48,35 @@ export function useSwapCallback( ...@@ -48,27 +48,35 @@ export function useSwapCallback(
to?: string // recipient of output, optional to?: string // recipient of output, optional
): null | (() => Promise<string>) { ): null | (() => Promise<string>) {
const { account, chainId, library } = useActiveWeb3React() const { account, chainId, library } = useActiveWeb3React()
const inputAllowance = useTokenAllowance(trade?.inputAmount?.token, account, ROUTER_ADDRESS) const inputAllowance = useTokenAllowance(trade?.inputAmount?.token, account ?? undefined, ROUTER_ADDRESS)
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const recipient = to ? isAddress(to) : account const recipient = to ? isAddress(to) : account
const ensName = useENSName(to) const ensName = useENSName(to)
return useMemo(() => { return useMemo(() => {
if (!trade) return null if (!trade || !recipient) return null
if (!recipient) return null
// will always be defined // will always be defined
const slippageAdjustedAmounts = computeSlippageAdjustedAmounts(trade, allowedSlippage) const {
[Field.INPUT]: slippageAdjustedInput,
[Field.OUTPUT]: slippageAdjustedOutput
} = computeSlippageAdjustedAmounts(trade, allowedSlippage)
if (!slippageAdjustedInput || !slippageAdjustedOutput) return null
// no allowance // no allowance
if ( if (
!trade.inputAmount.token.equals(WETH[chainId]) && !trade.inputAmount.token.equals(WETH[chainId as ChainId]) &&
(!inputAllowance || slippageAdjustedAmounts[Field.INPUT].greaterThan(inputAllowance)) (!inputAllowance || slippageAdjustedInput.greaterThan(inputAllowance))
) { ) {
return null return null
} }
return async function onSwap() { return async function onSwap() {
if (!chainId || !library || !account) {
throw new Error('missing dependencies in onSwap callback')
}
const routerContract: Contract = getRouterContract(chainId, library, account) const routerContract: Contract = getRouterContract(chainId, library, account)
const path = trade.route.path.map(t => t.address) const path = trade.route.path.map(t => t.address)
...@@ -78,17 +86,17 @@ export function useSwapCallback( ...@@ -78,17 +86,17 @@ export function useSwapCallback(
const swapType = getSwapType( const swapType = getSwapType(
{ [Field.INPUT]: trade.inputAmount.token, [Field.OUTPUT]: trade.outputAmount.token }, { [Field.INPUT]: trade.inputAmount.token, [Field.OUTPUT]: trade.outputAmount.token },
trade.tradeType === TradeType.EXACT_INPUT, trade.tradeType === TradeType.EXACT_INPUT,
chainId chainId as ChainId
) )
let estimate, method, args, value let estimate, method: Function, args: Array<string | string[] | number>, value: BigNumber | null
switch (swapType) { switch (swapType) {
case SwapType.EXACT_TOKENS_FOR_TOKENS: case SwapType.EXACT_TOKENS_FOR_TOKENS:
estimate = routerContract.estimateGas.swapExactTokensForTokens estimate = routerContract.estimateGas.swapExactTokensForTokens
method = routerContract.swapExactTokensForTokens method = routerContract.swapExactTokensForTokens
args = [ args = [
slippageAdjustedAmounts[Field.INPUT].raw.toString(), slippageAdjustedInput.raw.toString(),
slippageAdjustedAmounts[Field.OUTPUT].raw.toString(), slippageAdjustedOutput.raw.toString(),
path, path,
recipient, recipient,
deadlineFromNow deadlineFromNow
...@@ -99,8 +107,8 @@ export function useSwapCallback( ...@@ -99,8 +107,8 @@ export function useSwapCallback(
estimate = routerContract.estimateGas.swapTokensForExactTokens estimate = routerContract.estimateGas.swapTokensForExactTokens
method = routerContract.swapTokensForExactTokens method = routerContract.swapTokensForExactTokens
args = [ args = [
slippageAdjustedAmounts[Field.OUTPUT].raw.toString(), slippageAdjustedOutput.raw.toString(),
slippageAdjustedAmounts[Field.INPUT].raw.toString(), slippageAdjustedInput.raw.toString(),
path, path,
recipient, recipient,
deadlineFromNow deadlineFromNow
...@@ -110,15 +118,15 @@ export function useSwapCallback( ...@@ -110,15 +118,15 @@ export function useSwapCallback(
case SwapType.EXACT_ETH_FOR_TOKENS: case SwapType.EXACT_ETH_FOR_TOKENS:
estimate = routerContract.estimateGas.swapExactETHForTokens estimate = routerContract.estimateGas.swapExactETHForTokens
method = routerContract.swapExactETHForTokens method = routerContract.swapExactETHForTokens
args = [slippageAdjustedAmounts[Field.OUTPUT].raw.toString(), path, recipient, deadlineFromNow] args = [slippageAdjustedOutput.raw.toString(), path, recipient, deadlineFromNow]
value = BigNumber.from(slippageAdjustedAmounts[Field.INPUT].raw.toString()) value = BigNumber.from(slippageAdjustedInput.raw.toString())
break break
case SwapType.TOKENS_FOR_EXACT_ETH: case SwapType.TOKENS_FOR_EXACT_ETH:
estimate = routerContract.estimateGas.swapTokensForExactETH estimate = routerContract.estimateGas.swapTokensForExactETH
method = routerContract.swapTokensForExactETH method = routerContract.swapTokensForExactETH
args = [ args = [
slippageAdjustedAmounts[Field.OUTPUT].raw.toString(), slippageAdjustedOutput.raw.toString(),
slippageAdjustedAmounts[Field.INPUT].raw.toString(), slippageAdjustedInput.raw.toString(),
path, path,
recipient, recipient,
deadlineFromNow deadlineFromNow
...@@ -129,8 +137,8 @@ export function useSwapCallback( ...@@ -129,8 +137,8 @@ export function useSwapCallback(
estimate = routerContract.estimateGas.swapExactTokensForETH estimate = routerContract.estimateGas.swapExactTokensForETH
method = routerContract.swapExactTokensForETH method = routerContract.swapExactTokensForETH
args = [ args = [
slippageAdjustedAmounts[Field.INPUT].raw.toString(), slippageAdjustedInput.raw.toString(),
slippageAdjustedAmounts[Field.OUTPUT].raw.toString(), slippageAdjustedOutput.raw.toString(),
path, path,
recipient, recipient,
deadlineFromNow deadlineFromNow
...@@ -140,8 +148,8 @@ export function useSwapCallback( ...@@ -140,8 +148,8 @@ export function useSwapCallback(
case SwapType.ETH_FOR_EXACT_TOKENS: case SwapType.ETH_FOR_EXACT_TOKENS:
estimate = routerContract.estimateGas.swapETHForExactTokens estimate = routerContract.estimateGas.swapETHForExactTokens
method = routerContract.swapETHForExactTokens method = routerContract.swapETHForExactTokens
args = [slippageAdjustedAmounts[Field.OUTPUT].raw.toString(), path, recipient, deadlineFromNow] args = [slippageAdjustedOutput.raw.toString(), path, recipient, deadlineFromNow]
value = BigNumber.from(slippageAdjustedAmounts[Field.INPUT].raw.toString()) value = BigNumber.from(slippageAdjustedInput.raw.toString())
break break
} }
...@@ -157,11 +165,11 @@ export function useSwapCallback( ...@@ -157,11 +165,11 @@ export function useSwapCallback(
addTransaction(response, { addTransaction(response, {
summary: summary:
'Swap ' + 'Swap ' +
slippageAdjustedAmounts[Field.INPUT].toSignificant(3) + slippageAdjustedInput.toSignificant(3) +
' ' + ' ' +
trade.inputAmount.token.symbol + trade.inputAmount.token.symbol +
' for ' + ' for ' +
slippageAdjustedAmounts[Field.OUTPUT].toSignificant(3) + slippageAdjustedOutput.toSignificant(3) +
' ' + ' ' +
trade.outputAmount.token.symbol trade.outputAmount.token.symbol
}) })
...@@ -169,11 +177,11 @@ export function useSwapCallback( ...@@ -169,11 +177,11 @@ export function useSwapCallback(
addTransaction(response, { addTransaction(response, {
summary: summary:
'Swap ' + 'Swap ' +
slippageAdjustedAmounts[Field.INPUT].toSignificant(3) + slippageAdjustedInput.toSignificant(3) +
' ' + ' ' +
trade.inputAmount.token.symbol + trade.inputAmount.token.symbol +
' for ' + ' for ' +
slippageAdjustedAmounts[Field.OUTPUT].toSignificant(3) + slippageAdjustedOutput.toSignificant(3) +
' ' + ' ' +
trade.outputAmount.token.symbol + trade.outputAmount.token.symbol +
' to ' + ' to ' +
......
...@@ -31,7 +31,7 @@ import { TYPE } from '../../theme' ...@@ -31,7 +31,7 @@ import { TYPE } from '../../theme'
import { calculateGasMargin, calculateSlippageAmount, getRouterContract } from '../../utils' import { calculateGasMargin, calculateSlippageAmount, getRouterContract } from '../../utils'
import AppBody from '../AppBody' import AppBody from '../AppBody'
import { ClickableText, FixedBottom, MaxButton, Wrapper } from '../Pool/styleds' import { ClickableText, FixedBottom, MaxButton, Wrapper } from '../Pool/styleds'
import { useApproveCallback, Approval } from '../../hooks/useApproveCallback' import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallback'
import { Dots } from '../../components/swap/styleds' import { Dots } from '../../components/swap/styleds'
// denominated in bips // denominated in bips
...@@ -446,7 +446,7 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro ...@@ -446,7 +446,7 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro
let estimate, method, args let estimate, method, args
// we have approval, use normal remove liquidity // we have approval, use normal remove liquidity
if (approval === Approval.APPROVED) { if (approval === ApprovalState.APPROVED) {
// removeLiquidityETH // removeLiquidityETH
if (oneTokenIsETH) { if (oneTokenIsETH) {
estimate = router.estimateGas.removeLiquidityETH estimate = router.estimateGas.removeLiquidityETH
...@@ -619,15 +619,15 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro ...@@ -619,15 +619,15 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro
<RowBetween mt="1rem"> <RowBetween mt="1rem">
<ButtonConfirmed <ButtonConfirmed
onClick={onAttemptToApprove} onClick={onAttemptToApprove}
confirmed={approval === Approval.APPROVED || signatureData !== null} confirmed={approval === ApprovalState.APPROVED || signatureData !== null}
disabled={approval !== Approval.NOT_APPROVED || signatureData !== null} disabled={approval !== ApprovalState.NOT_APPROVED || signatureData !== null}
mr="0.5rem" mr="0.5rem"
fontWeight={500} fontWeight={500}
fontSize={20} fontSize={20}
> >
{approval === Approval.PENDING ? ( {approval === ApprovalState.PENDING ? (
<Dots>Approving</Dots> <Dots>Approving</Dots>
) : approval === Approval.APPROVED || signatureData !== null ? ( ) : approval === ApprovalState.APPROVED || signatureData !== null ? (
'Approved' 'Approved'
) : ( ) : (
'Approve' 'Approve'
...@@ -635,7 +635,7 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro ...@@ -635,7 +635,7 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro
</ButtonConfirmed> </ButtonConfirmed>
<ButtonPrimary <ButtonPrimary
disabled={!(approval === Approval.APPROVED || signatureData !== null)} disabled={!(approval === ApprovalState.APPROVED || signatureData !== null)}
onClick={onRemove} onClick={onRemove}
ml="0.5rem" ml="0.5rem"
> >
......
...@@ -25,7 +25,7 @@ import TokenLogo from '../../components/TokenLogo' ...@@ -25,7 +25,7 @@ import TokenLogo from '../../components/TokenLogo'
import { TokenWarningCards } from '../../components/TokenWarningCard' import { TokenWarningCards } from '../../components/TokenWarningCard'
import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE, MIN_ETH } from '../../constants' import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE, MIN_ETH } from '../../constants'
import { useActiveWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useApproveCallbackFromTrade, Approval } from '../../hooks/useApproveCallback' import { useApproveCallbackFromTrade, ApprovalState } from '../../hooks/useApproveCallback'
import { useSendCallback } from '../../hooks/useSendCallback' import { useSendCallback } from '../../hooks/useSendCallback'
import { useSwapCallback } from '../../hooks/useSwapCallback' import { useSwapCallback } from '../../hooks/useSwapCallback'
import { useWalletModalToggle } from '../../state/application/hooks' import { useWalletModalToggle } from '../../state/application/hooks'
...@@ -153,7 +153,7 @@ export default function Send({ location: { search } }: RouteComponentProps) { ...@@ -153,7 +153,7 @@ export default function Send({ location: { search } }: RouteComponentProps) {
} }
const sendCallback = useSendCallback(parsedAmounts?.[Field.INPUT], recipient) const sendCallback = useSendCallback(parsedAmounts?.[Field.INPUT], recipient)
const isSendValid = sendCallback !== null && (sendingWithSwap === false || approval === Approval.APPROVED) const isSendValid = sendCallback !== null && (sendingWithSwap === false || approval === ApprovalState.APPROVED)
async function onSend() { async function onSend() {
setAttemptingTxn(true) setAttemptingTxn(true)
...@@ -465,9 +465,9 @@ export default function Send({ location: { search } }: RouteComponentProps) { ...@@ -465,9 +465,9 @@ export default function Send({ location: { search } }: RouteComponentProps) {
<GreyCard style={{ textAlign: 'center' }}> <GreyCard style={{ textAlign: 'center' }}>
<TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main> <TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main>
</GreyCard> </GreyCard>
) : approval === Approval.NOT_APPROVED || approval === Approval.PENDING ? ( ) : approval === ApprovalState.NOT_APPROVED || approval === ApprovalState.PENDING ? (
<ButtonLight onClick={approveCallback} disabled={approval === Approval.PENDING}> <ButtonLight onClick={approveCallback} disabled={approval === ApprovalState.PENDING}>
{approval === Approval.PENDING ? ( {approval === ApprovalState.PENDING ? (
<Dots>Approving {tokens[Field.INPUT]?.symbol}</Dots> <Dots>Approving {tokens[Field.INPUT]?.symbol}</Dots>
) : ( ) : (
'Approve ' + tokens[Field.INPUT]?.symbol 'Approve ' + tokens[Field.INPUT]?.symbol
......
...@@ -23,7 +23,7 @@ import V1TradeLink from '../../components/swap/V1TradeLink' ...@@ -23,7 +23,7 @@ import V1TradeLink from '../../components/swap/V1TradeLink'
import { TokenWarningCards } from '../../components/TokenWarningCard' import { TokenWarningCards } from '../../components/TokenWarningCard'
import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE, MIN_ETH } from '../../constants' import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE, MIN_ETH } from '../../constants'
import { useActiveWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useApproveCallbackFromTrade, Approval } from '../../hooks/useApproveCallback' import { useApproveCallbackFromTrade, ApprovalState } from '../../hooks/useApproveCallback'
import { useSwapCallback } from '../../hooks/useSwapCallback' import { useSwapCallback } from '../../hooks/useSwapCallback'
import { useWalletModalToggle } from '../../state/application/hooks' import { useWalletModalToggle } from '../../state/application/hooks'
import { Field } from '../../state/swap/actions' import { Field } from '../../state/swap/actions'
...@@ -270,9 +270,9 @@ export default function Swap({ location: { search } }: RouteComponentProps) { ...@@ -270,9 +270,9 @@ export default function Swap({ location: { search } }: RouteComponentProps) {
<GreyCard style={{ textAlign: 'center' }}> <GreyCard style={{ textAlign: 'center' }}>
<TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main> <TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main>
</GreyCard> </GreyCard>
) : approval === Approval.NOT_APPROVED || approval === Approval.PENDING ? ( ) : approval === ApprovalState.NOT_APPROVED || approval === ApprovalState.PENDING ? (
<ButtonLight onClick={approveCallback} disabled={approval === Approval.PENDING}> <ButtonLight onClick={approveCallback} disabled={approval === ApprovalState.PENDING}>
{approval === Approval.PENDING ? ( {approval === ApprovalState.PENDING ? (
<Dots>Approving {tokens[Field.INPUT]?.symbol}</Dots> <Dots>Approving {tokens[Field.INPUT]?.symbol}</Dots>
) : ( ) : (
'Approve ' + tokens[Field.INPUT]?.symbol 'Approve ' + tokens[Field.INPUT]?.symbol
......
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