Commit 373b3180 authored by Noah Zinsmeister's avatar Noah Zinsmeister Committed by GitHub

manual approve fallback for remove liquidity (#806)

* generalize useApproveCallback

* show proper slippageAdjustedAmounts in dialog

* make confirmed button text readable in light mode

* default timeout from 15 -> 20 minutes

* add manual approve fallback to remove liquidity

* remove console log

* fix bad web3-react import introduced by refactor

* rename our wrapped version of useWeb3React

* return an enum from useApproveCallback

* fix comment
parent c35d8fc7
...@@ -2,7 +2,7 @@ import React from 'react' ...@@ -2,7 +2,7 @@ import React from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { Check, Triangle } from 'react-feather' import { Check, Triangle } from 'react-feather'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { getEtherscanLink } from '../../utils' import { getEtherscanLink } from '../../utils'
import { Link, Spinner } from '../../theme' import { Link, Spinner } from '../../theme'
import Circle from '../../assets/images/circle.svg' import Circle from '../../assets/images/circle.svg'
...@@ -53,7 +53,7 @@ const IconWrapper = styled.div` ...@@ -53,7 +53,7 @@ const IconWrapper = styled.div`
` `
export default function Transaction({ hash }: { hash: string }) { export default function Transaction({ hash }: { hash: string }) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const allTransactions = useAllTransactions() const allTransactions = useAllTransactions()
const summary = allTransactions?.[hash]?.summary const summary = allTransactions?.[hash]?.summary
......
import React, { useCallback, useContext } from 'react' import React, { useCallback, useContext } from 'react'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import styled, { ThemeContext } from 'styled-components' import styled, { ThemeContext } from 'styled-components'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { AppDispatch } from '../../state' import { AppDispatch } from '../../state'
import { clearAllTransactions } from '../../state/transactions/actions' import { clearAllTransactions } from '../../state/transactions/actions'
...@@ -242,7 +242,7 @@ export default function AccountDetails({ ...@@ -242,7 +242,7 @@ export default function AccountDetails({
ENSName, ENSName,
openOptions openOptions
}: AccountDetailsProps) { }: AccountDetailsProps) {
const { chainId, account, connector } = useWeb3React() const { chainId, account, connector } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
......
...@@ -2,7 +2,7 @@ import React, { useState, useEffect, useContext } from 'react' ...@@ -2,7 +2,7 @@ import React, { useState, useEffect, useContext } from 'react'
import styled, { ThemeContext } from 'styled-components' import styled, { ThemeContext } from 'styled-components'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { useWeb3React, useDebounce } from '../../hooks' import { useActiveWeb3React, useDebounce } from '../../hooks'
import { Link, TYPE } from '../../theme' import { Link, TYPE } from '../../theme'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import { RowBetween } from '../Row' import { RowBetween } from '../Row'
...@@ -72,7 +72,7 @@ export default function AddressInputPanel({ ...@@ -72,7 +72,7 @@ export default function AddressInputPanel({
onChange: (val: { address: string; name?: string }) => void onChange: (val: { address: string; name?: string }) => void
onError: (error: boolean, input: string) => void onError: (error: boolean, input: string) => void
}) { }) {
const { chainId, library } = useWeb3React() const { chainId, library } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const [input, setInput] = useState(initialInput ? initialInput : '') const [input, setInput] = useState(initialInput ? initialInput : '')
......
...@@ -201,6 +201,7 @@ export const ButtonWhite = styled(Base)` ...@@ -201,6 +201,7 @@ export const ButtonWhite = styled(Base)`
const ButtonConfirmedStyle = styled(Base)` const ButtonConfirmedStyle = styled(Base)`
background-color: ${({ theme }) => lighten(0.5, theme.green1)}; background-color: ${({ theme }) => lighten(0.5, theme.green1)};
color: ${({ theme }) => theme.green1};
border: 1px solid ${({ theme }) => theme.green1}; border: 1px solid ${({ theme }) => theme.green1};
&:disabled { &:disabled {
......
...@@ -12,7 +12,7 @@ import { ArrowUpCircle } from 'react-feather' ...@@ -12,7 +12,7 @@ import { ArrowUpCircle } from 'react-feather'
import { ButtonPrimary } from '../Button' import { ButtonPrimary } from '../Button'
import { AutoColumn, ColumnCenter } from '../Column' import { AutoColumn, ColumnCenter } from '../Column'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { getEtherscanLink } from '../../utils' import { getEtherscanLink } from '../../utils'
const Wrapper = styled.div` const Wrapper = styled.div`
...@@ -56,7 +56,7 @@ function ConfirmationModal({ ...@@ -56,7 +56,7 @@ function ConfirmationModal({
pendingText, pendingText,
title = '' title = ''
}: ConfirmationModalProps) { }: ConfirmationModalProps) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const dismissAndReturn = useCallback(() => { const dismissAndReturn = useCallback(() => {
......
...@@ -13,7 +13,7 @@ import { AutoColumn, ColumnCenter } from '../Column' ...@@ -13,7 +13,7 @@ import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button' import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { useToken } from '../../hooks/Tokens' import { useToken } from '../../hooks/Tokens'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { usePair } from '../../data/Reserves' import { usePair } from '../../data/Reserves'
const Fields = { const Fields = {
...@@ -28,7 +28,7 @@ const STEP = { ...@@ -28,7 +28,7 @@ const STEP = {
} }
function CreatePool({ history }: RouteComponentProps) { function CreatePool({ history }: RouteComponentProps) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const [showSearch, setShowSearch] = useState<boolean>(false) const [showSearch, setShowSearch] = useState<boolean>(false)
const [activeField, setActiveField] = useState<number>(Fields.TOKEN0) const [activeField, setActiveField] = useState<number>(Fields.TOKEN0)
......
...@@ -14,7 +14,7 @@ import { TYPE, CursorPointer } from '../../theme' ...@@ -14,7 +14,7 @@ import { TYPE, CursorPointer } from '../../theme'
import { Input as NumericalInput } from '../NumericalInput' import { Input as NumericalInput } from '../NumericalInput'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg' import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
const InputRow = styled.div<{ selected: boolean }>` const InputRow = styled.div<{ selected: boolean }>`
...@@ -161,7 +161,7 @@ export default function CurrencyInputPanel({ ...@@ -161,7 +161,7 @@ export default function CurrencyInputPanel({
const { t } = useTranslation() const { t } = useTranslation()
const [modalOpen, setModalOpen] = useState(false) const [modalOpen, setModalOpen] = useState(false)
const { account } = useWeb3React() const { account } = useActiveWeb3React()
const userTokenBalance = useTokenBalanceTreatingWETHasETH(account, token) const userTokenBalance = useTokenBalanceTreatingWETHasETH(account, token)
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
......
...@@ -13,7 +13,7 @@ import { Text } from 'rebass' ...@@ -13,7 +13,7 @@ import { Text } from 'rebass'
import { WETH, ChainId } from '@uniswap/sdk' import { WETH, ChainId } from '@uniswap/sdk'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { YellowCard } from '../Card' import { YellowCard } from '../Card'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useDarkModeManager } from '../../state/user/hooks' import { useDarkModeManager } from '../../state/user/hooks'
import Logo from '../../assets/svg/logo.svg' import Logo from '../../assets/svg/logo.svg'
...@@ -150,7 +150,7 @@ const VersionToggle = styled.a` ...@@ -150,7 +150,7 @@ const VersionToggle = styled.a`
` `
export default function Header() { export default function Header() {
const { account, chainId } = useWeb3React() const { account, chainId } = useActiveWeb3React()
const userEthBalance = useTokenBalanceTreatingWETHasETH(account, WETH[chainId]) const userEthBalance = useTokenBalanceTreatingWETHasETH(account, WETH[chainId])
const [isDark] = useDarkModeManager() const [isDark] = useDarkModeManager()
......
...@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react' ...@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import Jazzicon from 'jazzicon' import Jazzicon from 'jazzicon'
const StyledIdenticon = styled.div` const StyledIdenticon = styled.div`
...@@ -15,7 +15,7 @@ const StyledIdenticon = styled.div` ...@@ -15,7 +15,7 @@ const StyledIdenticon = styled.div`
export default function Identicon() { export default function Identicon() {
const ref = useRef<HTMLDivElement>() const ref = useRef<HTMLDivElement>()
const { account } = useWeb3React() const { account } = useActiveWeb3React()
useEffect(() => { useEffect(() => {
if (account && ref.current) { if (account && ref.current) {
......
...@@ -15,7 +15,7 @@ import { AutoColumn, ColumnCenter } from '../Column' ...@@ -15,7 +15,7 @@ import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button' import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { useToken } from '../../hooks/Tokens' import { useToken } from '../../hooks/Tokens'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { usePairAdder } from '../../state/user/hooks' import { usePairAdder } from '../../state/user/hooks'
import { usePair } from '../../data/Reserves' import { usePair } from '../../data/Reserves'
...@@ -25,7 +25,7 @@ const Fields = { ...@@ -25,7 +25,7 @@ const Fields = {
} }
function PoolFinder({ history }: RouteComponentProps) { function PoolFinder({ history }: RouteComponentProps) {
const { account } = useWeb3React() const { account } = useActiveWeb3React()
const [showSearch, setShowSearch] = useState<boolean>(false) const [showSearch, setShowSearch] = useState<boolean>(false)
const [activeField, setActiveField] = useState<number>(Fields.TOKEN0) const [activeField, setActiveField] = useState<number>(Fields.TOKEN0)
......
...@@ -4,7 +4,7 @@ import { darken } from 'polished' ...@@ -4,7 +4,7 @@ import { darken } from 'polished'
import { RouteComponentProps, withRouter } from 'react-router-dom' import { RouteComponentProps, withRouter } from 'react-router-dom'
import { Percent, Pair, JSBI } from '@uniswap/sdk' import { Percent, Pair, JSBI } from '@uniswap/sdk'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useTotalSupply } from '../../data/TotalSupply' import { useTotalSupply } from '../../data/TotalSupply'
import { useTokenBalance } from '../../state/wallet/hooks' import { useTokenBalance } from '../../state/wallet/hooks'
...@@ -36,7 +36,7 @@ interface PositionCardProps extends RouteComponentProps<{}> { ...@@ -36,7 +36,7 @@ interface PositionCardProps extends RouteComponentProps<{}> {
} }
function PositionCard({ pair, history, border, minimal = false }: PositionCardProps) { function PositionCard({ pair, history, border, minimal = false }: PositionCardProps) {
const { account } = useWeb3React() const { account } = useActiveWeb3React()
const token0 = pair?.token0 const token0 = pair?.token0
const token1 = pair?.token1 const token1 = pair?.token1
......
...@@ -23,7 +23,7 @@ import { Spinner, TYPE } from '../../theme' ...@@ -23,7 +23,7 @@ import { Spinner, TYPE } from '../../theme'
import { RowBetween, RowFixed, AutoRow } from '../Row' import { RowBetween, RowFixed, AutoRow } from '../Row'
import { isAddress, escapeRegExp } from '../../utils' import { isAddress, escapeRegExp } from '../../utils'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { import {
useAllDummyPairs, useAllDummyPairs,
useFetchTokenByAddress, useFetchTokenByAddress,
...@@ -174,7 +174,7 @@ function SearchModal({ ...@@ -174,7 +174,7 @@ function SearchModal({
showCommonBases = false showCommonBases = false
}: SearchModalProps) { }: SearchModalProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { account, chainId } = useWeb3React() const { account, chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const allTokens = useAllTokens() const allTokens = useAllTokens()
......
import React, { useState } from 'react' import React, { useState } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { WETH } from '@uniswap/sdk' import { WETH } from '@uniswap/sdk'
import { ReactComponent as EthereumLogo } from '../../assets/images/ethereum-logo.svg' import { ReactComponent as EthereumLogo } from '../../assets/images/ethereum-logo.svg'
...@@ -45,7 +45,7 @@ export default function TokenLogo({ ...@@ -45,7 +45,7 @@ export default function TokenLogo({
style?: React.CSSProperties style?: React.CSSProperties
}) { }) {
const [error, setError] = useState(false) const [error, setError] = useState(false)
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
// mock rinkeby DAI // mock rinkeby DAI
if (chainId === 4 && address === '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735') { if (chainId === 4 && address === '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735') {
......
...@@ -3,7 +3,7 @@ import { AlertCircle, CheckCircle } from 'react-feather' ...@@ -3,7 +3,7 @@ import { AlertCircle, CheckCircle } from 'react-feather'
import styled from 'styled-components' import styled from 'styled-components'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import useInterval from '../../hooks/useInterval' import useInterval from '../../hooks/useInterval'
import { useRemovePopup } from '../../state/application/hooks' import { useRemovePopup } from '../../state/application/hooks'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
...@@ -36,7 +36,7 @@ export default function TxnPopup({ ...@@ -36,7 +36,7 @@ export default function TxnPopup({
summary?: string summary?: string
popKey?: string popKey?: string
}) { }) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const [count, setCount] = useState(1) const [count, setCount] = useState(1)
const [isRunning, setIsRunning] = useState(true) const [isRunning, setIsRunning] = useState(true)
......
...@@ -2,8 +2,7 @@ import React, { useState, useEffect } from 'react' ...@@ -2,8 +2,7 @@ import React, { useState, useEffect } from 'react'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import styled from 'styled-components' import styled from 'styled-components'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { UnsupportedChainIdError } from '@web3-react/core' import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { useWeb3React } from '../../hooks'
import { URI_AVAILABLE } from '@web3-react/walletconnect-connector' import { URI_AVAILABLE } from '@web3-react/walletconnect-connector'
import { useWalletModalOpen, useWalletModalToggle } from '../../state/application/hooks' import { useWalletModalOpen, useWalletModalToggle } from '../../state/application/hooks'
...@@ -124,6 +123,7 @@ export default function WalletModal({ ...@@ -124,6 +123,7 @@ export default function WalletModal({
confirmedTransactions: string[] // hashes of confirmed confirmedTransactions: string[] // hashes of confirmed
ENSName?: string ENSName?: string
}) { }) {
// important that these are destructed from the account-specific web3-react context
const { active, account, connector, activate, error } = useWeb3React() const { active, account, connector, activate, error } = useWeb3React()
const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT) const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT)
......
...@@ -2,7 +2,7 @@ import { Token } from '@uniswap/sdk' ...@@ -2,7 +2,7 @@ import { Token } from '@uniswap/sdk'
import React, { useState } from 'react' import React, { useState } from 'react'
import styled, { keyframes } from 'styled-components' import styled, { keyframes } from 'styled-components'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useToken } from '../../hooks/Tokens' import { useToken } from '../../hooks/Tokens'
import { getEtherscanLink } from '../../utils' import { getEtherscanLink } from '../../utils'
...@@ -134,7 +134,7 @@ interface WarningCardProps { ...@@ -134,7 +134,7 @@ interface WarningCardProps {
export default function WarningCard({ onDismiss, urlAddedTokens, currency }: WarningCardProps) { export default function WarningCard({ onDismiss, urlAddedTokens, currency }: WarningCardProps) {
const [showPopup, setPopup] = useState<boolean>(false) const [showPopup, setPopup] = useState<boolean>(false)
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const { symbol: inputSymbol, name: inputName } = useToken(currency) const { symbol: inputSymbol, name: inputName } = useToken(currency)
const fromURL = urlAddedTokens.hasOwnProperty(currency) const fromURL = urlAddedTokens.hasOwnProperty(currency)
......
import { TokenAmount } from '@uniswap/sdk' import { TokenAmount } from '@uniswap/sdk'
import React from 'react' import React from 'react'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { Link, TYPE } from '../../theme' import { Link, TYPE } from '../../theme'
import { getEtherscanLink } from '../../utils' import { getEtherscanLink } from '../../utils'
import Copy from '../AccountDetails/Copy' import Copy from '../AccountDetails/Copy'
...@@ -18,7 +18,7 @@ export function TransferModalHeader({ ...@@ -18,7 +18,7 @@ export function TransferModalHeader({
ENSName: string ENSName: string
amount: TokenAmount amount: TokenAmount
}) { }) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
return ( return (
<AutoColumn gap="lg" style={{ marginTop: '40px' }}> <AutoColumn gap="lg" style={{ marginTop: '40px' }}>
<RowBetween> <RowBetween>
......
...@@ -106,8 +106,8 @@ export const NetworkContextName = 'NETWORK' ...@@ -106,8 +106,8 @@ export const NetworkContextName = 'NETWORK'
// default allowed slippage, in bips // default allowed slippage, in bips
export const INITIAL_ALLOWED_SLIPPAGE = 50 export const INITIAL_ALLOWED_SLIPPAGE = 50
// 15 minutes, denominated in seconds // 20 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 15 export const DEFAULT_DEADLINE_FROM_NOW = 60 * 20
// one basis point // one basis point
export const ONE_BIPS = new Percent(JSBI.BigInt(1), JSBI.BigInt(10000)) export const ONE_BIPS = new Percent(JSBI.BigInt(1), JSBI.BigInt(10000))
......
import { Contract } from '@ethersproject/contracts' 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 { useWeb3React } from '../hooks' import { useActiveWeb3React } from '../hooks'
import IUniswapV1Factory from '../constants/abis/v1_factory.json' import IUniswapV1Factory from '../constants/abis/v1_factory.json'
import { V1_FACTORY_ADDRESS } from '../constants' import { V1_FACTORY_ADDRESS } from '../constants'
...@@ -14,7 +14,7 @@ function getV1PairAddress(contract: Contract): (tokenAddress: string) => Promise ...@@ -14,7 +14,7 @@ function getV1PairAddress(contract: Contract): (tokenAddress: string) => Promise
} }
function useV1PairAddress(tokenAddress: string) { function useV1PairAddress(tokenAddress: string) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const contract = useContract(V1_FACTORY_ADDRESS, IUniswapV1Factory, false) const contract = useContract(V1_FACTORY_ADDRESS, IUniswapV1Factory, false)
...@@ -49,7 +49,7 @@ export function useV1TradeLinkIfBetter( ...@@ -49,7 +49,7 @@ export function useV1TradeLinkIfBetter(
v2Trade?: Trade, v2Trade?: Trade,
minimumDelta: Percent = new Percent('0') minimumDelta: Percent = new Percent('0')
): string { ): string {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const input = inputToken const input = inputToken
const output = outputToken const output = outputToken
......
...@@ -2,7 +2,7 @@ import { ChainId, Token, WETH } from '@uniswap/sdk' ...@@ -2,7 +2,7 @@ import { ChainId, Token, WETH } from '@uniswap/sdk'
import { useEffect, useMemo } from 'react' import { useEffect, useMemo } from 'react'
import { useAddUserToken, useFetchTokenByAddress, useUserAddedTokens } from '../state/user/hooks' import { useAddUserToken, useFetchTokenByAddress, useUserAddedTokens } from '../state/user/hooks'
import { useWeb3React } from './index' import { useActiveWeb3React } from './index'
import MAINNET_TOKENS from '../constants/tokens/mainnet' import MAINNET_TOKENS from '../constants/tokens/mainnet'
import RINKEBY_TOKENS from '../constants/tokens/rinkeby' import RINKEBY_TOKENS from '../constants/tokens/rinkeby'
import KOVAN_TOKENS from '../constants/tokens/kovan' import KOVAN_TOKENS from '../constants/tokens/kovan'
...@@ -39,7 +39,7 @@ export const ALL_TOKENS: Readonly<AllTokens> = [ ...@@ -39,7 +39,7 @@ export const ALL_TOKENS: Readonly<AllTokens> = [
}, {}) }, {})
export function useAllTokens(): { [address: string]: Token } { export function useAllTokens(): { [address: string]: Token } {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const userAddedTokens = useUserAddedTokens() const userAddedTokens = useUserAddedTokens()
return useMemo(() => { return useMemo(() => {
......
import { useMemo } from 'react' import { useMemo } from 'react'
import { WETH, Token, TokenAmount, Trade, ChainId, Pair } from '@uniswap/sdk' import { WETH, Token, TokenAmount, Trade, ChainId, Pair } from '@uniswap/sdk'
import { useWeb3React } from './index' import { useActiveWeb3React } from './index'
import { usePair } from '../data/Reserves' import { usePair } from '../data/Reserves'
const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin') const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
const USDC = new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C') const USDC = new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C')
function useAllCommonPairs(tokenA?: Token, tokenB?: Token): Pair[] { function useAllCommonPairs(tokenA?: Token, tokenB?: Token): Pair[] {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
// check for direct pair between tokens // check for direct pair between tokens
const pairBetween = usePair(tokenA, tokenB) const pairBetween = usePair(tokenA, tokenB)
......
...@@ -10,7 +10,7 @@ import { injected } from '../connectors' ...@@ -10,7 +10,7 @@ import { injected } from '../connectors'
import { NetworkContextName } from '../constants' import { NetworkContextName } from '../constants'
import { getContract, getExchangeContract, isAddress } from '../utils' import { getContract, getExchangeContract, isAddress } from '../utils'
export function useWeb3React() { export function useActiveWeb3React() {
const context = useWeb3ReactCore<Web3Provider>() const context = useWeb3ReactCore<Web3Provider>()
const contextNetwork = useWeb3ReactCore<Web3Provider>(NetworkContextName) const contextNetwork = useWeb3ReactCore<Web3Provider>(NetworkContextName)
return context.active ? context : contextNetwork return context.active ? context : contextNetwork
...@@ -143,7 +143,7 @@ export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false) ...@@ -143,7 +143,7 @@ export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false)
} }
export function useENSName(address) { export function useENSName(address) {
const { library } = useWeb3React() const { library } = useActiveWeb3React()
const [ENSName, setENSName] = useState<string | null>(null) const [ENSName, setENSName] = useState<string | null>(null)
...@@ -179,7 +179,7 @@ export function useENSName(address) { ...@@ -179,7 +179,7 @@ export function useENSName(address) {
// returns null on errors // returns null on errors
export function useContract(address, ABI, withSignerIfPossible = true) { export function useContract(address, ABI, withSignerIfPossible = true) {
const { library, account } = useWeb3React() const { library, account } = useActiveWeb3React()
return useMemo(() => { return useMemo(() => {
try { try {
...@@ -192,7 +192,7 @@ export function useContract(address, ABI, withSignerIfPossible = true) { ...@@ -192,7 +192,7 @@ export function useContract(address, ABI, withSignerIfPossible = true) {
// returns null on errors // returns null on errors
export function useTokenContract(tokenAddress: string, withSignerIfPossible = true): Contract { export function useTokenContract(tokenAddress: string, withSignerIfPossible = true): Contract {
const { library, account } = useWeb3React() const { library, account } = useActiveWeb3React()
return useMemo(() => { return useMemo(() => {
try { try {
...@@ -204,7 +204,7 @@ export function useTokenContract(tokenAddress: string, withSignerIfPossible = tr ...@@ -204,7 +204,7 @@ export function useTokenContract(tokenAddress: string, withSignerIfPossible = tr
} }
export function usePairContract(pairAddress, withSignerIfPossible = true) { export function usePairContract(pairAddress, withSignerIfPossible = true) {
const { library, account } = useWeb3React() const { library, account } = useActiveWeb3React()
return useMemo(() => { return useMemo(() => {
try { try {
......
import { MaxUint256 } from '@ethersproject/constants' import { MaxUint256 } from '@ethersproject/constants'
import { Trade, WETH } 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'
import { useTokenAllowance } from '../data/Allowances' import { useTokenAllowance } from '../data/Allowances'
import { Field } from '../state/swap/actions' import { Field } from '../state/swap/actions'
import { useTransactionAdder } from '../state/transactions/hooks' import { useTransactionAdder, useHasPendingApproval } from '../state/transactions/hooks'
import { computeSlippageAdjustedAmounts } from '../utils/prices' import { computeSlippageAdjustedAmounts } from '../utils/prices'
import { calculateGasMargin } from '../utils' import { calculateGasMargin } from '../utils'
import { useTokenContract, useWeb3React } from './index' import { useTokenContract, useActiveWeb3React } from './index'
// returns a function to approve the amount required to execute a trade if necessary, otherwise null export enum Approval {
export function useApproveCallback(trade?: Trade, allowedSlippage = 0): [undefined | boolean, () => Promise<void>] { UNKNOWN,
const { account, chainId } = useWeb3React() NOT_APPROVED,
const currentAllowance = useTokenAllowance(trade?.inputAmount?.token, account, ROUTER_ADDRESS) PENDING,
APPROVED
}
const slippageAdjustedAmountIn = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage)[Field.INPUT], [ // returns a variable indicating the state of the approval and a function which approves if necessary or early returns
trade, export function useApproveCallback(
allowedSlippage amountToApprove?: TokenAmount,
]) addressToApprove?: string
): [Approval, () => Promise<void>] {
const { account } = useActiveWeb3React()
const mustApprove = useMemo(() => { const currentAllowance = useTokenAllowance(amountToApprove?.token, account, addressToApprove)
const pendingApproval = useHasPendingApproval(amountToApprove?.token?.address)
// check the current approval status
const approval = useMemo(() => {
// we treat WETH as ETH which requires no approvals // we treat WETH as ETH which requires no approvals
if (trade?.inputAmount?.token?.equals(WETH[chainId])) return false if (amountToApprove?.token?.equals(WETH[amountToApprove?.token?.chainId])) return Approval.APPROVED
// return undefined if we don't 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 undefined if (!currentAllowance) return Approval.UNKNOWN
// slippageAdjustedAmountIn will be defined if currentAllowance is if (pendingApproval) return Approval.PENDING
return currentAllowance.lessThan(slippageAdjustedAmountIn) // amountToApprove will be defined if currentAllowance is
}, [trade, chainId, currentAllowance, slippageAdjustedAmountIn]) return currentAllowance.lessThan(amountToApprove) ? Approval.NOT_APPROVED : Approval.APPROVED
}, [amountToApprove, currentAllowance, pendingApproval])
const tokenContract = useTokenContract(trade?.inputAmount?.token?.address)
const tokenContract = useTokenContract(amountToApprove?.token?.address)
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const approve = useCallback(async (): Promise<void> => {
if (!mustApprove) return
let useUserBalance = false const approve = useCallback(async (): Promise<void> => {
if (approval !== Approval.NOT_APPROVED) {
console.error('approve was called unnecessarily, this is likely an error.')
return
}
const estimatedGas = await tokenContract.estimateGas.approve(ROUTER_ADDRESS, MaxUint256).catch(() => { let useExact = false
const estimatedGas = await tokenContract.estimateGas.approve(addressToApprove, MaxUint256).catch(() => {
// general fallback for tokens who restrict approval amounts // general fallback for tokens who restrict approval amounts
useUserBalance = true useExact = true
return tokenContract.estimateGas.approve(ROUTER_ADDRESS, slippageAdjustedAmountIn.raw.toString()) return tokenContract.estimateGas.approve(addressToApprove, amountToApprove.raw.toString())
}) })
return tokenContract return tokenContract
.approve(ROUTER_ADDRESS, useUserBalance ? slippageAdjustedAmountIn.raw.toString() : MaxUint256, { .approve(addressToApprove, useExact ? amountToApprove.raw.toString() : MaxUint256, {
gasLimit: calculateGasMargin(estimatedGas) gasLimit: calculateGasMargin(estimatedGas)
}) })
.then(response => { .then(response => {
addTransaction(response, { addTransaction(response, {
summary: 'Approve ' + trade?.inputAmount?.token?.symbol, summary: 'Approve ' + amountToApprove?.token?.symbol,
approvalOfToken: trade?.inputAmount?.token?.symbol approvalOfToken: amountToApprove?.token?.address
}) })
}) })
.catch(error => { .catch(error => {
console.debug('Failed to approve token', error) console.debug('Failed to approve token', error)
throw error throw error
}) })
}, [mustApprove, tokenContract, slippageAdjustedAmountIn, trade, addTransaction]) }, [approval, tokenContract, addressToApprove, amountToApprove, addTransaction])
return [approval, approve]
}
return [mustApprove, approve] // wraps useApproveCallback in the context of a swap
export function useApproveCallbackFromTrade(trade?: Trade, allowedSlippage = 0) {
const amountToApprove = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage)[Field.INPUT], [
trade,
allowedSlippage
])
return useApproveCallback(amountToApprove, ROUTER_ADDRESS)
} }
...@@ -5,12 +5,12 @@ import { useTransactionAdder } from '../state/transactions/hooks' ...@@ -5,12 +5,12 @@ import { useTransactionAdder } from '../state/transactions/hooks'
import { useTokenBalanceTreatingWETHasETH } from '../state/wallet/hooks' import { useTokenBalanceTreatingWETHasETH } from '../state/wallet/hooks'
import { calculateGasMargin, getSigner, isAddress } from '../utils' import { calculateGasMargin, getSigner, isAddress } from '../utils'
import { useENSName, useTokenContract, useWeb3React } from './index' import { useENSName, useTokenContract, useActiveWeb3React } from './index'
// returns a callback for sending a token amount, treating WETH as ETH // returns a callback for sending a token amount, treating WETH as ETH
// returns null with invalid arguments // returns null with invalid arguments
export function useSendCallback(amount?: TokenAmount, recipient?: string): null | (() => Promise<string>) { export function useSendCallback(amount?: TokenAmount, recipient?: string): null | (() => Promise<string>) {
const { library, account, chainId } = useWeb3React() const { library, account, chainId } = useActiveWeb3React()
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)
......
...@@ -8,7 +8,7 @@ import { Field } from '../state/swap/actions' ...@@ -8,7 +8,7 @@ import { Field } from '../state/swap/actions'
import { useTransactionAdder } from '../state/transactions/hooks' import { useTransactionAdder } from '../state/transactions/hooks'
import { computeSlippageAdjustedAmounts } from '../utils/prices' import { computeSlippageAdjustedAmounts } from '../utils/prices'
import { calculateGasMargin, getRouterContract, isAddress } from '../utils' import { calculateGasMargin, getRouterContract, isAddress } from '../utils'
import { useENSName, useWeb3React } from './index' import { useENSName, useActiveWeb3React } from './index'
enum SwapType { enum SwapType {
EXACT_TOKENS_FOR_TOKENS, EXACT_TOKENS_FOR_TOKENS,
...@@ -47,7 +47,7 @@ export function useSwapCallback( ...@@ -47,7 +47,7 @@ export function useSwapCallback(
deadline: number = DEFAULT_DEADLINE_FROM_NOW, // in seconds from now, optional deadline: number = DEFAULT_DEADLINE_FROM_NOW, // in seconds from now, optional
to?: string // recipient of output, optional to?: string // recipient of output, optional
): null | (() => Promise<string>) { ): null | (() => Promise<string>) {
const { account, chainId, library } = useWeb3React() const { account, chainId, library } = useActiveWeb3React()
const inputAllowance = useTokenAllowance(trade?.inputAmount?.token, account, ROUTER_ADDRESS) const inputAllowance = useTokenAllowance(trade?.inputAmount?.token, account, ROUTER_ADDRESS)
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const recipient = to ? isAddress(to) : account const recipient = to ? isAddress(to) : account
......
...@@ -25,7 +25,7 @@ import { ROUTER_ADDRESS } from '../../constants' ...@@ -25,7 +25,7 @@ import { ROUTER_ADDRESS } from '../../constants'
import { useTokenAllowance } from '../../data/Allowances' import { useTokenAllowance } from '../../data/Allowances'
import { usePair } from '../../data/Reserves' import { usePair } from '../../data/Reserves'
import { useTotalSupply } from '../../data/TotalSupply' import { useTotalSupply } from '../../data/TotalSupply'
import { useTokenContract, useWeb3React } from '../../hooks' import { useTokenContract, useActiveWeb3React } from '../../hooks'
import { useTokenByAddressAndAutomaticallyAdd } from '../../hooks/Tokens' import { useTokenByAddressAndAutomaticallyAdd } from '../../hooks/Tokens'
import { useHasPendingApproval, useTransactionAdder } from '../../state/transactions/hooks' import { useHasPendingApproval, useTransactionAdder } from '../../state/transactions/hooks'
...@@ -140,7 +140,7 @@ interface AddLiquidityProps extends RouteComponentProps { ...@@ -140,7 +140,7 @@ interface AddLiquidityProps extends RouteComponentProps {
} }
function AddLiquidity({ token0, token1 }: AddLiquidityProps) { function AddLiquidity({ token0, token1 }: AddLiquidityProps) {
const { account, chainId, library } = useWeb3React() const { account, chainId, library } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
// modal states // modal states
...@@ -535,7 +535,7 @@ function AddLiquidity({ token0, token1 }: AddLiquidityProps) { ...@@ -535,7 +535,7 @@ function AddLiquidity({ token0, token1 }: AddLiquidityProps) {
</RowFlat> </RowFlat>
<Row> <Row>
<Text fontSize="24px"> <Text fontSize="24px">
{tokens[Field.INPUT]?.symbol + ':' + tokens[Field.OUTPUT]?.symbol + ' Pool Tokens'} {tokens[Field.INPUT]?.symbol + '/' + tokens[Field.OUTPUT]?.symbol + ' Pool Tokens'}
</Text> </Text>
</Row> </Row>
<TYPE.italic fontSize={12} textAlign="left" padding={'8px 0 0 0 '}> <TYPE.italic fontSize={12} textAlign="left" padding={'8px 0 0 0 '}>
......
This diff is collapsed.
...@@ -14,7 +14,7 @@ import { RowBetween } from '../../components/Row' ...@@ -14,7 +14,7 @@ import { RowBetween } from '../../components/Row'
import { ButtonPrimary, ButtonSecondary } from '../../components/Button' import { ButtonPrimary, ButtonSecondary } from '../../components/Button'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { usePair } from '../../data/Reserves' import { usePair } from '../../data/Reserves'
import { useAllDummyPairs } from '../../state/user/hooks' import { useAllDummyPairs } from '../../state/user/hooks'
...@@ -36,7 +36,7 @@ function PositionCardWrapper({ dummyPair }: { dummyPair: Pair }) { ...@@ -36,7 +36,7 @@ function PositionCardWrapper({ dummyPair }: { dummyPair: Pair }) {
function Supply({ history }: RouteComponentProps) { function Supply({ history }: RouteComponentProps) {
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const { account } = useWeb3React() const { account } = useActiveWeb3React()
const [showPoolSearch, setShowPoolSearch] = useState(false) const [showPoolSearch, setShowPoolSearch] = useState(false)
// initiate listener for LP balances // initiate listener for LP balances
......
...@@ -23,14 +23,13 @@ import { TransferModalHeader } from '../../components/swap/TransferModalHeader' ...@@ -23,14 +23,13 @@ import { TransferModalHeader } from '../../components/swap/TransferModalHeader'
import V1TradeLink from '../../components/swap/V1TradeLink' import V1TradeLink from '../../components/swap/V1TradeLink'
import TokenLogo from '../../components/TokenLogo' import TokenLogo from '../../components/TokenLogo'
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 { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useApproveCallback } from '../../hooks/useApproveCallback' import { useApproveCallbackFromTrade, Approval } 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'
import { Field } from '../../state/swap/actions' import { Field } from '../../state/swap/actions'
import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../state/swap/hooks' import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../state/swap/hooks'
import { useHasPendingApproval } from '../../state/transactions/hooks'
import { useAllTokenBalancesTreatingWETHasETH } from '../../state/wallet/hooks' import { useAllTokenBalancesTreatingWETHasETH } from '../../state/wallet/hooks'
import { CursorPointer, TYPE } from '../../theme' import { CursorPointer, TYPE } from '../../theme'
import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices' import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices'
...@@ -40,7 +39,7 @@ export default function Send({ location: { search } }: RouteComponentProps) { ...@@ -40,7 +39,7 @@ export default function Send({ location: { search } }: RouteComponentProps) {
// text translation // text translation
// const { t } = useTranslation() // const { t } = useTranslation()
const { chainId, account } = useWeb3React() const { chainId, account } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
// toggle wallet when disconnected // toggle wallet when disconnected
...@@ -86,8 +85,7 @@ export default function Send({ location: { search } }: RouteComponentProps) { ...@@ -86,8 +85,7 @@ export default function Send({ location: { search } }: RouteComponentProps) {
const noRoute = !route const noRoute = !route
// check whether the user has approved the router on the input token // check whether the user has approved the router on the input token
const [mustApprove, approveCallback] = useApproveCallback(bestTrade, allowedSlippage) const [approval, approveCallback] = useApproveCallbackFromTrade(bestTrade, allowedSlippage)
const pendingApprovalInput = useHasPendingApproval(tokens[Field.INPUT]?.address)
const formattedAmounts = { const formattedAmounts = {
[independentField]: typedValue, [independentField]: typedValue,
...@@ -153,7 +151,7 @@ export default function Send({ location: { search } }: RouteComponentProps) { ...@@ -153,7 +151,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 || mustApprove === false) const isSendValid = sendCallback !== null && (sendingWithSwap === false || approval === Approval.APPROVED)
async function onSend() { async function onSend() {
setAttemptingTxn(true) setAttemptingTxn(true)
...@@ -459,9 +457,9 @@ export default function Send({ location: { search } }: RouteComponentProps) { ...@@ -459,9 +457,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>
) : mustApprove === true ? ( ) : approval === Approval.NOT_APPROVED || approval === Approval.PENDING ? (
<ButtonLight onClick={approveCallback} disabled={pendingApprovalInput}> <ButtonLight onClick={approveCallback} disabled={approval === Approval.PENDING}>
{pendingApprovalInput ? ( {approval === Approval.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
......
...@@ -21,13 +21,12 @@ import SwapModalHeader from '../../components/swap/SwapModalHeader' ...@@ -21,13 +21,12 @@ import SwapModalHeader from '../../components/swap/SwapModalHeader'
import TradePrice from '../../components/swap/TradePrice' import TradePrice from '../../components/swap/TradePrice'
import V1TradeLink from '../../components/swap/V1TradeLink' import V1TradeLink from '../../components/swap/V1TradeLink'
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 { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useApproveCallback } from '../../hooks/useApproveCallback' import { useApproveCallbackFromTrade, Approval } 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'
import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../state/swap/hooks' import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../state/swap/hooks'
import { useHasPendingApproval } from '../../state/transactions/hooks'
import { CursorPointer, TYPE } from '../../theme' import { CursorPointer, TYPE } from '../../theme'
import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices' import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices'
...@@ -35,7 +34,7 @@ export default function Swap({ location: { search } }: RouteComponentProps) { ...@@ -35,7 +34,7 @@ export default function Swap({ location: { search } }: RouteComponentProps) {
useDefaultsFromURL(search) useDefaultsFromURL(search)
// text translation // text translation
// const { t } = useTranslation() // const { t } = useTranslation()
const { chainId, account } = useWeb3React() const { chainId, account } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
// toggle wallet when disconnected // toggle wallet when disconnected
...@@ -66,8 +65,7 @@ export default function Swap({ location: { search } }: RouteComponentProps) { ...@@ -66,8 +65,7 @@ export default function Swap({ location: { search } }: RouteComponentProps) {
const noRoute = !route const noRoute = !route
// check whether the user has approved the router on the input token // check whether the user has approved the router on the input token
const [mustApprove, approveCallback] = useApproveCallback(bestTrade, allowedSlippage) const [approval, approveCallback] = useApproveCallbackFromTrade(bestTrade, allowedSlippage)
const pendingApprovalInput = useHasPendingApproval(tokens[Field.INPUT]?.address)
const formattedAmounts = { const formattedAmounts = {
[independentField]: typedValue, [independentField]: typedValue,
...@@ -264,9 +262,9 @@ export default function Swap({ location: { search } }: RouteComponentProps) { ...@@ -264,9 +262,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>
) : mustApprove === true ? ( ) : approval === Approval.NOT_APPROVED || approval === Approval.PENDING ? (
<ButtonLight onClick={approveCallback} disabled={pendingApprovalInput}> <ButtonLight onClick={approveCallback} disabled={approval === Approval.PENDING}>
{pendingApprovalInput ? ( {approval === Approval.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
......
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { addPopup, PopupContent, removePopup, toggleWalletModal } from './actions' import { addPopup, PopupContent, removePopup, toggleWalletModal } from './actions'
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import { AppState } from '../index' import { AppState } from '../index'
export function useBlockNumber(): number | undefined { export function useBlockNumber(): number | undefined {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
return useSelector((state: AppState) => state.application.blockNumber[chainId ?? -1]) return useSelector((state: AppState) => state.application.blockNumber[chainId ?? -1])
} }
......
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useDebounce, useWeb3React } from '../../hooks' import { useDebounce, useActiveWeb3React } from '../../hooks'
import { updateBlockNumber } from './actions' import { updateBlockNumber } from './actions'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
export default function Updater() { export default function Updater() {
const { library, chainId } = useWeb3React() const { library, chainId } = useActiveWeb3React()
const dispatch = useDispatch() const dispatch = useDispatch()
const [maxBlockNumber, setMaxBlockNumber] = useState<number | null>(null) const [maxBlockNumber, setMaxBlockNumber] = useState<number | null>(null)
......
...@@ -2,7 +2,7 @@ import { parseUnits } from '@ethersproject/units' ...@@ -2,7 +2,7 @@ import { parseUnits } from '@ethersproject/units'
import { JSBI, Token, TokenAmount, Trade } from '@uniswap/sdk' import { JSBI, Token, TokenAmount, Trade } from '@uniswap/sdk'
import { useCallback, useEffect } from 'react' import { useCallback, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useTokenByAddressAndAutomaticallyAdd } from '../../hooks/Tokens' import { useTokenByAddressAndAutomaticallyAdd } from '../../hooks/Tokens'
import { useTradeExactIn, useTradeExactOut } from '../../hooks/Trades' import { useTradeExactIn, useTradeExactOut } from '../../hooks/Trades'
import { AppDispatch, AppState } from '../index' import { AppDispatch, AppState } from '../index'
...@@ -78,7 +78,7 @@ export function useDerivedSwapInfo(): { ...@@ -78,7 +78,7 @@ export function useDerivedSwapInfo(): {
error?: string error?: string
v1TradeLinkIfBetter?: string v1TradeLinkIfBetter?: string
} { } {
const { account } = useWeb3React() const { account } = useActiveWeb3React()
const { const {
independentField, independentField,
...@@ -156,7 +156,7 @@ export function useDerivedSwapInfo(): { ...@@ -156,7 +156,7 @@ export function useDerivedSwapInfo(): {
// updates the swap state to use the defaults for a given network whenever the query // updates the swap state to use the defaults for a given network whenever the query
// string updates // string updates
export function useDefaultsFromURL(search?: string) { export function useDefaultsFromURL(search?: string) {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
useEffect(() => { useEffect(() => {
if (!chainId) return if (!chainId) return
......
...@@ -2,7 +2,7 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -2,7 +2,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { useCallback } from 'react' import { useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { AppDispatch, AppState } from '../index' import { AppDispatch, AppState } from '../index'
import { addTransaction } from './actions' import { addTransaction } from './actions'
import { TransactionDetails, TransactionState } from './reducer' import { TransactionDetails, TransactionState } from './reducer'
...@@ -12,7 +12,7 @@ export function useTransactionAdder(): ( ...@@ -12,7 +12,7 @@ export function useTransactionAdder(): (
response: TransactionResponse, response: TransactionResponse,
customData?: { summary?: string; approvalOfToken?: string } customData?: { summary?: string; approvalOfToken?: string }
) => void { ) => void {
const { chainId, account } = useWeb3React() const { chainId, account } = useActiveWeb3React()
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
return useCallback( return useCallback(
...@@ -35,7 +35,7 @@ export function useTransactionAdder(): ( ...@@ -35,7 +35,7 @@ export function useTransactionAdder(): (
// returns all the transactions for the current chain // returns all the transactions for the current chain
export function useAllTransactions(): { [txHash: string]: TransactionDetails } { export function useAllTransactions(): { [txHash: string]: TransactionDetails } {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const state = useSelector<AppState, TransactionState>(state => state.transactions) const state = useSelector<AppState, TransactionState>(state => state.transactions)
...@@ -43,13 +43,15 @@ export function useAllTransactions(): { [txHash: string]: TransactionDetails } { ...@@ -43,13 +43,15 @@ export function useAllTransactions(): { [txHash: string]: TransactionDetails } {
} }
// returns whether a token has a pending approval transaction // returns whether a token has a pending approval transaction
export function useHasPendingApproval(tokenAddress: string): boolean { export function useHasPendingApproval(tokenAddress?: string): boolean {
const allTransactions = useAllTransactions() const allTransactions = useAllTransactions()
return Object.keys(allTransactions).some(hash => { return typeof tokenAddress !== 'string'
if (allTransactions[hash]?.receipt) { ? false
return false : Object.keys(allTransactions).some(hash => {
} else { if (allTransactions[hash]?.receipt) {
return allTransactions[hash]?.approvalOfToken === tokenAddress return false
} } else {
}) return allTransactions[hash]?.approvalOfToken === tokenAddress
}
})
} }
import { useEffect } from 'react' import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useAddPopup, useBlockNumber } from '../application/hooks' import { useAddPopup, useBlockNumber } from '../application/hooks'
import { AppDispatch, AppState } from '../index' import { AppDispatch, AppState } from '../index'
import { finalizeTransaction } from './actions' import { finalizeTransaction } from './actions'
export default function Updater() { export default function Updater() {
const { chainId, library } = useWeb3React() const { chainId, library } = useActiveWeb3React()
const lastBlockNumber = useBlockNumber() const lastBlockNumber = useBlockNumber()
......
import { ChainId, JSBI, Pair, Token, TokenAmount, WETH } from '@uniswap/sdk' import { ChainId, JSBI, Pair, Token, TokenAmount, WETH } from '@uniswap/sdk'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import { shallowEqual, useDispatch, useSelector } from 'react-redux' import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { useAllTokens } from '../../hooks/Tokens' import { useAllTokens } from '../../hooks/Tokens'
...@@ -61,7 +61,7 @@ export function useDarkModeManager(): [boolean, () => void] { ...@@ -61,7 +61,7 @@ export function useDarkModeManager(): [boolean, () => void] {
} }
export function useFetchTokenByAddress(): (address: string) => Promise<Token | null> { export function useFetchTokenByAddress(): (address: string) => Promise<Token | null> {
const { library, chainId } = useWeb3React() const { library, chainId } = useActiveWeb3React()
return useCallback( return useCallback(
async (address: string): Promise<Token | null> => { async (address: string): Promise<Token | null> => {
...@@ -103,7 +103,7 @@ export function useRemoveUserAddedToken(): (chainId: number, address: string) => ...@@ -103,7 +103,7 @@ export function useRemoveUserAddedToken(): (chainId: number, address: string) =>
} }
export function useUserAddedTokens(): Token[] { export function useUserAddedTokens(): Token[] {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const serializedTokensMap = useSelector<AppState, AppState['user']['tokens']>(({ user: { tokens } }) => tokens) const serializedTokensMap = useSelector<AppState, AppState['user']['tokens']>(({ user: { tokens } }) => tokens)
return useMemo(() => { return useMemo(() => {
...@@ -139,7 +139,7 @@ const bases = [ ...@@ -139,7 +139,7 @@ const bases = [
] ]
export function useAllDummyPairs(): Pair[] { export function useAllDummyPairs(): Pair[] {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const tokens = useAllTokens() const tokens = useAllTokens()
const generatedPairs: Pair[] = useMemo( const generatedPairs: Pair[] = useMemo(
......
...@@ -3,7 +3,7 @@ import { ChainId, JSBI, Token, TokenAmount, WETH } from '@uniswap/sdk' ...@@ -3,7 +3,7 @@ import { ChainId, JSBI, Token, TokenAmount, WETH } from '@uniswap/sdk'
import { useEffect, useMemo } from 'react' import { useEffect, useMemo } from 'react'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { useAllTokens } from '../../hooks/Tokens' import { useAllTokens } from '../../hooks/Tokens'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { AppDispatch, AppState } from '../index' import { AppDispatch, AppState } from '../index'
import { import {
...@@ -20,7 +20,7 @@ import { balanceKey } from './reducer' ...@@ -20,7 +20,7 @@ import { balanceKey } from './reducer'
*/ */
export function useETHBalances(uncheckedAddresses?: (string | undefined)[]): { [address: string]: JSBI | undefined } { export function useETHBalances(uncheckedAddresses?: (string | undefined)[]): { [address: string]: JSBI | undefined } {
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const addresses: string[] = useMemo( const addresses: string[] = useMemo(
() => () =>
...@@ -70,7 +70,7 @@ export function useTokenBalances( ...@@ -70,7 +70,7 @@ export function useTokenBalances(
tokens?: (Token | undefined)[] tokens?: (Token | undefined)[]
): { [tokenAddress: string]: TokenAmount | undefined } { ): { [tokenAddress: string]: TokenAmount | undefined } {
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const validTokens: Token[] = useMemo( const validTokens: Token[] = useMemo(
() => tokens?.filter((t?: Token): t is Token => isAddress(t?.address) !== false) ?? [], () => tokens?.filter((t?: Token): t is Token => isAddress(t?.address) !== false) ?? [],
...@@ -125,7 +125,7 @@ export function useTokenBalancesTreatWETHAsETH( ...@@ -125,7 +125,7 @@ export function useTokenBalancesTreatWETHAsETH(
address?: string, address?: string,
tokens?: (Token | undefined)[] tokens?: (Token | undefined)[]
): { [tokenAddress: string]: TokenAmount | undefined } { ): { [tokenAddress: string]: TokenAmount | undefined } {
const { chainId } = useWeb3React() const { chainId } = useActiveWeb3React()
const { tokensWithoutWETH, includesWETH } = useMemo(() => { const { tokensWithoutWETH, includesWETH } = useMemo(() => {
if (!tokens || tokens.length === 0) { if (!tokens || tokens.length === 0) {
return { includesWETH: false, tokensWithoutWETH: [] } return { includesWETH: false, tokensWithoutWETH: [] }
...@@ -176,7 +176,7 @@ export function useTokenBalanceTreatingWETHasETH(account?: string, token?: Token ...@@ -176,7 +176,7 @@ export function useTokenBalanceTreatingWETHasETH(account?: string, token?: Token
export function useAllTokenBalancesTreatingWETHasETH(): { export function useAllTokenBalancesTreatingWETHasETH(): {
[account: string]: { [tokenAddress: string]: TokenAmount | undefined } [account: string]: { [tokenAddress: string]: TokenAmount | undefined }
} { } {
const { account } = useWeb3React() const { account } = useActiveWeb3React()
const allTokens = useAllTokens() const allTokens = useAllTokens()
const allTokensArray = useMemo(() => Object.values(allTokens ?? {}), [allTokens]) const allTokensArray = useMemo(() => Object.values(allTokens ?? {}), [allTokens])
const balances = useTokenBalancesTreatWETHAsETH(account ?? undefined, allTokensArray) const balances = useTokenBalancesTreatWETHAsETH(account ?? undefined, allTokensArray)
......
import { BalanceMap, getEtherBalances, getTokensBalance } from '@mycrypto/eth-scan' import { BalanceMap, getEtherBalances, getTokensBalance } from '@mycrypto/eth-scan'
import { useEffect, useMemo } from 'react' import { useEffect, useMemo } from 'react'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { useWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useBlockNumber } from '../application/hooks' import { useBlockNumber } from '../application/hooks'
import { AppDispatch, AppState } from '../index' import { AppDispatch, AppState } from '../index'
import { updateEtherBalances, updateTokenBalances } from './actions' import { updateEtherBalances, updateTokenBalances } from './actions'
...@@ -15,7 +15,7 @@ function convertBalanceMapValuesToString(balanceMap: BalanceMap): { [key: string ...@@ -15,7 +15,7 @@ function convertBalanceMapValuesToString(balanceMap: BalanceMap): { [key: string
} }
export default function Updater() { export default function Updater() {
const { chainId, library } = useWeb3React() const { chainId, library } = useActiveWeb3React()
const lastBlockNumber = useBlockNumber() const lastBlockNumber = useBlockNumber()
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
const ethBalanceListeners = useSelector<AppState, AppState['wallet']['balanceListeners']>(state => { const ethBalanceListeners = useSelector<AppState, AppState['wallet']['balanceListeners']>(state => {
......
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