diff --git a/src/components/Swap/Input.tsx b/src/components/Swap/Input.tsx index 32ef7ae71..08007496c 100644 --- a/src/components/Swap/Input.tsx +++ b/src/components/Swap/Input.tsx @@ -3,6 +3,7 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { TextButton } from 'components/Button' import { loadingTransitionCss } from 'css/loading' import { useIsSwapFieldIndependent, useSwapAmount, useSwapCurrency, useSwapInfo } from 'hooks/swap' +import { SwapApprovalState } from 'hooks/swap/useSwapApproval' import { useIsWrap } from 'hooks/swap/useWrapCallback' import { usePrefetchCurrencyColor } from 'hooks/useCurrencyColor' import { PriceImpact } from 'hooks/usePriceImpact' @@ -26,7 +27,7 @@ export const Balance = styled(ThemedText.Body2)` transition: color 0.25s ease-in-out; ` -const InputColumn = styled(Column)<{ approved?: boolean; disableHover?: boolean }>` +const InputColumn = styled(Column)<{ disableHover?: boolean }>` background-color: ${({ theme }) => theme.module}; border-radius: ${({ theme }) => theme.borderRadius - 0.25}em; margin-bottom: 4px; @@ -81,16 +82,18 @@ export function useFormattedFieldAmount({ interface FieldWrapperProps { field: Field - impact?: PriceImpact maxAmount?: string isSufficientBalance?: boolean + approved?: boolean + impact?: PriceImpact } export function FieldWrapper({ field, - impact, maxAmount, isSufficientBalance, + approved, + impact, className, }: FieldWrapperProps & { className?: string }) { const { @@ -138,13 +141,14 @@ export function FieldWrapper({ @@ -176,6 +180,7 @@ export function FieldWrapper({ export default function Input() { const { [Field.INPUT]: { balance, amount: currencyAmount }, + approval: { state: approvalState }, } = useSwapInfo() const isSufficientBalance = useMemo(() => { @@ -192,5 +197,12 @@ export default function Input() { return max.toExact() }, [balance, currencyAmount]) - return + return ( + + ) } diff --git a/src/components/Swap/SwapActionButton/ApproveButton.tsx b/src/components/Swap/SwapActionButton/ApproveButton.tsx index 78f6c5cf9..098895d1b 100644 --- a/src/components/Swap/SwapActionButton/ApproveButton.tsx +++ b/src/components/Swap/SwapActionButton/ApproveButton.tsx @@ -1,9 +1,8 @@ import { TransactionResponse } from '@ethersproject/providers' import { Trans } from '@lingui/macro' -import { Token } from '@uniswap/sdk-core' import ActionButton from 'components/ActionButton' import EtherscanLink from 'components/EtherscanLink' -import { ApproveOrPermitState } from 'hooks/swap/useSwapApproval' +import { SwapApprovalState } from 'hooks/swap/useSwapApproval' import { usePendingApproval } from 'hooks/transactions' import { Spinner } from 'icons' import { useCallback, useEffect, useMemo, useState } from 'react' @@ -12,10 +11,6 @@ import { ApprovalTransactionInfo, TransactionType } from 'state/transactions' import { Colors } from 'theme' import { ExplorerDataType } from 'utils/getExplorerLink' -export function useIsPendingApproval(token?: Token): boolean { - return Boolean(usePendingApproval(token)) -} - /** * An approving ActionButton. * Should only be rendered if a valid trade exists that is not yet approved. @@ -23,14 +18,14 @@ export function useIsPendingApproval(token?: Token): boolean { export default function ApproveButton({ color, trade, - approvalState, - handleApproveOrPermit, + state, + approve, onSubmit, }: { color: keyof Colors trade?: InterfaceTrade - approvalState: ApproveOrPermitState - handleApproveOrPermit: () => Promise<{ + state: SwapApprovalState + approve?: () => Promise<{ response: TransactionResponse tokenAddress: string spenderAddress: string @@ -41,13 +36,13 @@ export default function ApproveButton({ const onApprove = useCallback(async () => { setIsPending(true) await onSubmit(async () => { - const info = await handleApproveOrPermit() + const info = await approve?.() if (!info) return return { type: TransactionType.APPROVAL, ...info } }) setIsPending(false) - }, [handleApproveOrPermit, onSubmit]) + }, [approve, onSubmit]) const currency = trade?.inputAmount?.currency const symbol = currency?.symbol || '' @@ -58,8 +53,8 @@ export default function ApproveButton({ const pendingApprovalHash = usePendingApproval(currency?.isToken ? currency : undefined) const actionProps = useMemo(() => { - switch (approvalState) { - case ApproveOrPermitState.REQUIRES_APPROVAL: + switch (state) { + case SwapApprovalState.REQUIRES_APPROVAL: if (isPending) { return { message: Approve in your wallet, icon: Spinner } } @@ -68,7 +63,7 @@ export default function ApproveButton({ onClick: onApprove, children: Approve, } - case ApproveOrPermitState.REQUIRES_SIGNATURE: + case SwapApprovalState.REQUIRES_SIGNATURE: if (isPending) { return { message: Allow in your wallet, icon: Spinner } } @@ -77,7 +72,7 @@ export default function ApproveButton({ onClick: onApprove, children: Allow, } - case ApproveOrPermitState.PENDING_APPROVAL: + case SwapApprovalState.PENDING_APPROVAL: return { message: ( @@ -86,12 +81,12 @@ export default function ApproveButton({ ), icon: Spinner, } - case ApproveOrPermitState.PENDING_SIGNATURE: + case SwapApprovalState.PENDING_SIGNATURE: return { message: Allowance pending, icon: Spinner } default: return } - }, [approvalState, symbol, isPending, onApprove, pendingApprovalHash]) + }, [isPending, onApprove, pendingApprovalHash, state, symbol]) return } diff --git a/src/components/Swap/SwapActionButton/SwapButton.tsx b/src/components/Swap/SwapActionButton/SwapButton.tsx index d84a76c37..63122c27f 100644 --- a/src/components/Swap/SwapActionButton/SwapButton.tsx +++ b/src/components/Swap/SwapActionButton/SwapButton.tsx @@ -1,7 +1,7 @@ import { Trans } from '@lingui/macro' import { useWeb3React } from '@web3-react/core' import { useSwapInfo } from 'hooks/swap' -import { ApproveOrPermitState, useApproveOrPermit } from 'hooks/swap/useSwapApproval' +import { SwapApprovalState } from 'hooks/swap/useSwapApproval' import { useSwapCallback } from 'hooks/swap/useSwapCallback' import { useConditionalHandler } from 'hooks/useConditionalHandler' import { useSetOldestValidBlock } from 'hooks/useIsValidBlock' @@ -16,7 +16,7 @@ import invariant from 'tiny-invariant' import ActionButton from '../../ActionButton' import Dialog from '../../Dialog' import { SummaryDialog } from '../Summary' -import ApproveButton, { useIsPendingApproval } from './ApproveButton' +import ApproveButton from './ApproveButton' /** * A swapping ActionButton. @@ -33,13 +33,13 @@ export default function SwapButton({ }) { const { account, chainId } = useWeb3React() const { - [Field.INPUT]: { usdc: inputUSDC, amount: inputCurrencyAmount }, + [Field.INPUT]: { usdc: inputUSDC }, [Field.OUTPUT]: { usdc: outputUSDC }, trade: { trade, gasUseEstimateUSD }, slippage, impact, + approval, } = useSwapInfo() - const approval = useApproveOrPermit(trade, slippage.allowed, useIsPendingApproval, inputCurrencyAmount) const deadline = useTransactionDeadline() const feeOptions = useAtomValue(feeOptionsAtom) @@ -47,7 +47,7 @@ export default function SwapButton({ trade, allowedSlippage: slippage.allowed, recipientAddressOrName: account ?? null, - signatureData: approval.signatureData, + signatureData: approval?.signatureData, deadline, feeOptions, }) @@ -91,7 +91,7 @@ export default function SwapButton({ setOpen(await onReviewSwapClick()) }, [onReviewSwapClick]) - if (approval.approvalState !== ApproveOrPermitState.APPROVED && !disabled) { + if (approval.state !== SwapApprovalState.APPROVED && !disabled) { return } diff --git a/src/components/Swap/TokenInput.tsx b/src/components/Swap/TokenInput.tsx index 94a893850..f850d4053 100644 --- a/src/components/Swap/TokenInput.tsx +++ b/src/components/Swap/TokenInput.tsx @@ -33,18 +33,18 @@ export interface TokenInputHandle { } interface TokenInputProps { + field: Field amount: string currency?: Currency + approved?: boolean + loading?: boolean disabled?: boolean - field: Field - max?: string onChangeInput: (input: string) => void onChangeCurrency: (currency: Currency) => void - loading?: boolean } export const TokenInput = forwardRef>(function TokenInput( - { amount, currency, disabled, field, onChangeInput, onChangeCurrency, loading, children, ...rest }, + { field, amount, currency, approved, loading, disabled, onChangeInput, onChangeCurrency, children, ...rest }, ref ) { const input = useRef(null) @@ -78,7 +78,7 @@ export const TokenInput = forwardRef - + {children} diff --git a/src/components/TokenSelect/TokenButton.tsx b/src/components/TokenSelect/TokenButton.tsx index 8a8fb300e..a3a460165 100644 --- a/src/components/TokenSelect/TokenButton.tsx +++ b/src/components/TokenSelect/TokenButton.tsx @@ -13,13 +13,17 @@ const transitionCss = css` transition: background-color 0.125s linear, border-color 0.125s linear, filter 0.125s linear, width 0.125s ease-out; ` -const StyledTokenButton = styled(Button)` +const StyledTokenButton = styled(Button)<{ approved?: boolean }>` border-radius: ${({ theme }) => theme.borderRadius}em; padding: 0.25em; :enabled { ${({ transition }) => transition && transitionCss}; } + + ${TokenImg} { + filter: ${({ approved }) => approved === false && 'grayscale(1)'}; + } ` const TokenButtonRow = styled(Row)<{ empty: boolean }>` @@ -37,11 +41,12 @@ const TokenButtonRow = styled(Row)<{ empty: boolean }>` interface TokenButtonProps { value?: Currency + approved?: boolean disabled?: boolean onClick: () => void } -export default function TokenButton({ value, disabled, onClick }: TokenButtonProps) { +export default function TokenButton({ value, approved, disabled, onClick }: TokenButtonProps) { const buttonBackgroundColor = value ? 'interactive' : 'accent' const contentColor = buttonBackgroundColor === 'accent' ? 'onAccent' : 'currentColor' @@ -65,6 +70,7 @@ export default function TokenButton({ value, disabled, onClick }: TokenButtonPro void value?: Currency + approved?: boolean + disabled?: boolean + onSelect: (value: Currency) => void } -export default memo(function TokenSelect({ disabled, field, onSelect, value }: TokenSelectProps) { +export default memo(function TokenSelect({ field, value, approved, disabled, onSelect }: TokenSelectProps) { usePrefetchBalances() const [open, setOpen] = useState(false) @@ -144,7 +145,7 @@ export default memo(function TokenSelect({ disabled, field, onSelect, value }: T ) return ( <> - + {open && setOpen(false)} />} ) diff --git a/src/hooks/swap/useSwapApproval.ts b/src/hooks/swap/useSwapApproval.ts index d5b85eff3..41c68569e 100644 --- a/src/hooks/swap/useSwapApproval.ts +++ b/src/hooks/swap/useSwapApproval.ts @@ -1,36 +1,19 @@ -import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' +import { Percent } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { SWAP_ROUTER_ADDRESSES } from 'constants/addresses' import { ErrorCode } from 'constants/eip1193' -import { useERC20PermitFromTrade, UseERC20PermitState } from 'hooks/useERC20Permit' +import { useIsPendingApproval } from 'hooks/transactions' +import { PermitState, SignatureData, usePermit } from 'hooks/usePermit' import useTransactionDeadline from 'hooks/useTransactionDeadline' import { useAtomValue } from 'jotai/utils' -import { useCallback, useMemo } from 'react' +import { useMemo } from 'react' import { InterfaceTrade } from 'state/routing/types' import { swapEventHandlersAtom } from 'state/swap' import { ApprovalState, useApproval } from '../useApproval' export { ApprovalState } from '../useApproval' -// wraps useApproveCallback in the context of a swap -export default function useSwapApproval( - trade: InterfaceTrade | undefined, - allowedSlippage: Percent, - useIsPendingApproval: (token?: Token, spender?: string) => boolean, - amount?: CurrencyAmount // defaults to trade.maximumAmountIn(allowedSlippage) -) { - const { chainId } = useWeb3React() - const amountToApprove = useMemo( - () => amount || (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined), - [amount, trade, allowedSlippage] - ) - const spender = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined - - const approval = useApproval(amountToApprove, spender, useIsPendingApproval) - return approval -} - -export enum ApproveOrPermitState { +export enum SwapApprovalState { REQUIRES_APPROVAL, PENDING_APPROVAL, REQUIRES_SIGNATURE, @@ -38,68 +21,71 @@ export enum ApproveOrPermitState { APPROVED, } +export interface SwapApproval { + state: SwapApprovalState + signatureData?: SignatureData + approve?: () => Promise +} + /** * Returns all relevant statuses and callback functions for approvals. * Considers both standard approval and ERC20 permit. */ -export const useApproveOrPermit = ( - trade: InterfaceTrade | undefined, - allowedSlippage: Percent, - useIsPendingApproval: (token?: Token, spender?: string) => boolean, - amount?: CurrencyAmount // defaults to trade.maximumAmountIn(allowedSlippage) -) => { +export function useSwapApproval(trade: InterfaceTrade | undefined, allowedSlippage: Percent): SwapApproval { + const amount = useMemo(() => trade?.maximumAmountIn(allowedSlippage), [allowedSlippage, trade]) + const { chainId } = useWeb3React() const deadline = useTransactionDeadline() + const spender = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined - // Check approvals on ERC20 contract based on amount. - const [approval, getApproval] = useSwapApproval(trade, allowedSlippage, useIsPendingApproval, amount) + // Check EIP-20 approval. + const [approval, approve] = useApproval(amount, spender, useIsPendingApproval) - // Check status of permit and whether token supports it. - const { - state: signatureState, - signatureData, - gatherPermitSignature, - } = useERC20PermitFromTrade(trade, allowedSlippage, deadline) + // Check EIP-2162 approval. + const { state: permitState, signatureData, sign } = usePermit(amount, spender, deadline, null) - // If permit is supported, trigger a signature, if not create approval transaction. + // If permit is supported, sign a permit; if not, submit an approval. const { onSwapApprove } = useAtomValue(swapEventHandlersAtom) - const handleApproveOrPermit = useCallback(async () => { - try { - if (signatureState === UseERC20PermitState.NOT_SIGNED && gatherPermitSignature) { - try { - await gatherPermitSignature() - } catch (error) { - // Try to approve if gatherPermitSignature failed for any reason other than the user rejecting it. - if (error?.code !== ErrorCode.USER_REJECTED_REQUEST) { - await getApproval() + const approveOrSign = useMemo(() => { + if (approval !== ApprovalState.NOT_APPROVED && permitState !== PermitState.NOT_SIGNED) return + return async () => { + try { + if (permitState === PermitState.NOT_SIGNED && sign) { + try { + await sign() + } catch (error) { + // Try to approve if signing failed for any reason other than the user rejecting it. + if (error?.code !== ErrorCode.USER_REJECTED_REQUEST) { + await approve() + } } + } else { + await approve() } - } else { - await getApproval() + } catch (e) { + // Swallow approval errors - user rejections do not need to be displayed. + return } - } catch (e) { - // Swallow approval errors - user rejections do not need to be displayed. - return + onSwapApprove?.() } - onSwapApprove?.() - }, [onSwapApprove, signatureState, gatherPermitSignature, getApproval]) + }, [approval, approve, onSwapApprove, permitState, sign]) - const approvalState = useMemo(() => { + const state = useMemo(() => { if (approval === ApprovalState.PENDING) { - return ApproveOrPermitState.PENDING_APPROVAL - } else if (signatureState === UseERC20PermitState.LOADING) { - return ApproveOrPermitState.PENDING_SIGNATURE - } else if (approval !== ApprovalState.NOT_APPROVED || signatureState === UseERC20PermitState.SIGNED) { - return ApproveOrPermitState.APPROVED - } else if (gatherPermitSignature) { - return ApproveOrPermitState.REQUIRES_SIGNATURE + return SwapApprovalState.PENDING_APPROVAL + } else if (permitState === PermitState.LOADING) { + return SwapApprovalState.PENDING_SIGNATURE + } else if (approval !== ApprovalState.NOT_APPROVED || permitState === PermitState.SIGNED) { + return SwapApprovalState.APPROVED + } else if (sign) { + return SwapApprovalState.REQUIRES_SIGNATURE } else { - return ApproveOrPermitState.REQUIRES_APPROVAL + return SwapApprovalState.REQUIRES_APPROVAL } - }, [approval, gatherPermitSignature, signatureState]) + }, [approval, permitState, sign]) return { - approvalState, + state, signatureData, - handleApproveOrPermit, + approve: approveOrSign, } } diff --git a/src/hooks/swap/useSwapCallback.tsx b/src/hooks/swap/useSwapCallback.tsx index 4ebb47bfa..4dc5b4e3d 100644 --- a/src/hooks/swap/useSwapCallback.tsx +++ b/src/hooks/swap/useSwapCallback.tsx @@ -5,7 +5,7 @@ import { Percent } from '@uniswap/sdk-core' import { FeeOptions } from '@uniswap/v3-sdk' import { useWeb3React } from '@web3-react/core' import useENS from 'hooks/useENS' -import { SignatureData } from 'hooks/useERC20Permit' +import { SignatureData } from 'hooks/usePermit' import { useSwapCallArguments } from 'hooks/useSwapCallArguments' import { ReactNode, useMemo } from 'react' import { InterfaceTrade } from 'state/routing/types' diff --git a/src/hooks/swap/useSwapInfo.tsx b/src/hooks/swap/useSwapInfo.tsx index 9a0eaf9c2..719c29b65 100644 --- a/src/hooks/swap/useSwapInfo.tsx +++ b/src/hooks/swap/useSwapInfo.tsx @@ -13,6 +13,7 @@ import { Field, swapAtom, swapEventHandlersAtom } from 'state/swap' import { isExactInput } from 'utils/tradeType' import tryParseCurrencyAmount from 'utils/tryParseCurrencyAmount' +import { SwapApproval, SwapApprovalState, useSwapApproval } from './useSwapApproval' import { useIsWrap } from './useWrapCallback' export enum ChainError { @@ -40,6 +41,7 @@ interface SwapInfo { gasUseEstimateUSD?: CurrencyAmount } slippage: Slippage + approval: SwapApproval impact?: PriceImpact } @@ -89,6 +91,7 @@ function useComputeSwapInfo(routerUrl?: string): SwapInfo { // Compute slippage and impact off of the trade so that it refreshes with the trade. // Wait until the trade is valid to avoid displaying incorrect intermediate values. const slippage = useSlippage(trade) + const approval = useSwapApproval(trade.trade, slippage.allowed) const impact = usePriceImpact(trade.trade) return useMemo(() => { @@ -108,11 +111,13 @@ function useComputeSwapInfo(routerUrl?: string): SwapInfo { error, trade, slippage, + approval, impact, } }, [ amountIn, amountOut, + approval, balanceIn, balanceOut, currencyIn, @@ -132,6 +137,7 @@ const DEFAULT_SWAP_INFO: SwapInfo = { error: ChainError.UNCONNECTED_CHAIN, trade: { state: TradeState.INVALID, trade: undefined }, slippage: DEFAULT_SLIPPAGE, + approval: { state: SwapApprovalState.APPROVED }, } const SwapInfoContext = createContext(DEFAULT_SWAP_INFO) diff --git a/src/hooks/transactions/index.tsx b/src/hooks/transactions/index.tsx index efc7cfed8..60f31f411 100644 --- a/src/hooks/transactions/index.tsx +++ b/src/hooks/transactions/index.tsx @@ -63,6 +63,10 @@ export function usePendingApproval(token?: Token): string | undefined { )?.info.response.hash } +export function useIsPendingApproval(token?: Token): boolean { + return Boolean(usePendingApproval(token)) +} + export type OnTxSubmit = (hash: string, tx: Transaction) => void export type OnTxSuccess = (hash: string, receipt: TransactionReceipt) => void export type OnTxFail = (hash: string, receipt: TransactionReceipt) => void diff --git a/src/hooks/useERC20Permit.ts b/src/hooks/usePermit.ts similarity index 84% rename from src/hooks/useERC20Permit.ts rename to src/hooks/usePermit.ts index 6cb84a38d..233517935 100644 --- a/src/hooks/useERC20Permit.ts +++ b/src/hooks/usePermit.ts @@ -1,13 +1,11 @@ import { BigNumber } from '@ethersproject/bignumber' import { splitSignature } from '@ethersproject/bytes' -import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' +import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' -import { SWAP_ROUTER_ADDRESSES } from 'constants/addresses' import { DAI, UNI, USDC_MAINNET } from 'constants/tokens' import { useSingleCallResult } from 'hooks/multicall' import JSBI from 'jsbi' import { useMemo, useState } from 'react' -import { InterfaceTrade } from 'state/routing/types' import { useEIP2612Contract } from './useContract' import useIsArgentWallet from './useIsArgentWallet' @@ -54,7 +52,7 @@ const PERMITTABLE_TOKENS: { }, } -export enum UseERC20PermitState { +export enum PermitState { // returned for any reason, e.g. it is an argent wallet, or the currency does not support it NOT_APPLICABLE, LOADING, @@ -114,15 +112,15 @@ const PERMIT_ALLOWED_TYPE = [ { name: 'allowed', type: 'bool' }, ] -export function useERC20Permit( +export function usePermit( currencyAmount: CurrencyAmount | null | undefined, spender: string | null | undefined, transactionDeadline: BigNumber | undefined, overridePermitInfo: PermitInfo | undefined | null ): { - signatureData: SignatureData | null - state: UseERC20PermitState - gatherPermitSignature: null | (() => Promise) + state: PermitState + signatureData?: SignatureData + sign?: () => Promise } { const { account, chainId, provider } = useWeb3React() const tokenAddress = currencyAmount?.currency?.isToken ? currencyAmount.currency.address : undefined @@ -150,18 +148,14 @@ export function useERC20Permit( !permitInfo ) { return { - state: UseERC20PermitState.NOT_APPLICABLE, - signatureData: null, - gatherPermitSignature: null, + state: PermitState.NOT_APPLICABLE, } } const nonceNumber = tokenNonceState.result?.[0]?.toNumber() if (tokenNonceState.loading || typeof nonceNumber !== 'number') { return { - state: UseERC20PermitState.LOADING, - signatureData: null, - gatherPermitSignature: null, + state: PermitState.LOADING, } } @@ -176,9 +170,9 @@ export function useERC20Permit( JSBI.greaterThanOrEqual(JSBI.BigInt(signatureData.amount), currencyAmount.quotient)) return { - state: isSignatureDataValid ? UseERC20PermitState.SIGNED : UseERC20PermitState.NOT_SIGNED, - signatureData: isSignatureDataValid ? signatureData : null, - gatherPermitSignature: async function gatherPermitSignature() { + state: isSignatureDataValid ? PermitState.SIGNED : PermitState.NOT_SIGNED, + signatureData: isSignatureDataValid ? signatureData : undefined, + sign: async () => { const allowed = permitInfo.type === PermitType.ALLOWED const signatureDeadline = transactionDeadline.toNumber() + PERMIT_VALIDITY_BUFFER const value = currencyAmount.quotient.toString() @@ -257,18 +251,3 @@ export function useERC20Permit( signatureData, ]) } - -export function useERC20PermitFromTrade( - trade: InterfaceTrade | undefined, - allowedSlippage: Percent, - transactionDeadline: BigNumber | undefined -) { - const { chainId } = useWeb3React() - const swapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined - const amountToApprove = useMemo( - () => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined), - [trade, allowedSlippage] - ) - - return useERC20Permit(amountToApprove, swapRouterAddress, transactionDeadline, null) -} diff --git a/src/hooks/useSwapCallArguments.tsx b/src/hooks/useSwapCallArguments.tsx index f912a0b3d..3c760e6f2 100644 --- a/src/hooks/useSwapCallArguments.tsx +++ b/src/hooks/useSwapCallArguments.tsx @@ -10,7 +10,7 @@ import approveAmountCalldata from 'utils/approveAmountCalldata' import { useArgentWalletContract } from './useArgentWalletContract' import useENS from './useENS' -import { SignatureData } from './useERC20Permit' +import { SignatureData } from './usePermit' interface SwapCall { address: string