Commit eb75e0dc authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: set approval to pending on wallet request (#3570)

parent c26ecdfc
......@@ -57,7 +57,7 @@ export const Overlay = styled(Row)<{ hasAction: boolean }>`
export interface Action {
message: ReactNode
icon?: Icon
onClick: () => void
onClick?: () => void
children: ReactNode
}
......
......@@ -26,10 +26,12 @@ export default function EtherscanLink({ data, type, color = 'currentColor', chil
() => data && getExplorerLink(chainId || SupportedChainId.MAINNET, data, type),
[chainId, data, type]
)
return (
<StyledExternalLink href={url} color={color} target="_blank">
<Row gap={0.25}>
{children} <Link />
{children}
{url && <Link />}
</Row>
</StyledExternalLink>
)
......
......@@ -87,12 +87,11 @@ export default memo(function SwapButton({ disabled }: SwapButtonProps) {
)
const addTransaction = useAddTransaction()
const onApprove = useCallback(() => {
handleApproveOrPermit().then((transaction) => {
const onApprove = useCallback(async () => {
const transaction = await handleApproveOrPermit()
if (transaction) {
addTransaction({ type: TransactionType.APPROVAL, ...transaction })
}
})
}, [addTransaction, handleApproveOrPermit])
const { type: wrapType, callback: wrapCallback, error: wrapError, loading: wrapLoading } = useWrapCallback()
......@@ -104,7 +103,6 @@ export default memo(function SwapButton({ disabled }: SwapButtonProps) {
!chainId ||
wrapLoading ||
(wrapType !== WrapType.NOT_APPLICABLE && wrapError) ||
approvalState === ApproveOrPermitState.PENDING_SIGNATURE ||
!(inputTradeCurrencyAmount && inputCurrencyBalance) ||
inputCurrencyBalance.lessThan(inputTradeCurrencyAmount),
[
......@@ -114,7 +112,6 @@ export default memo(function SwapButton({ disabled }: SwapButtonProps) {
wrapLoading,
wrapType,
wrapError,
approvalState,
inputTradeCurrencyAmount,
inputCurrencyBalance,
]
......@@ -155,11 +152,20 @@ export default memo(function SwapButton({ disabled }: SwapButtonProps) {
</EtherscanLink>
),
icon: Spinner,
onClick: () => void 0, // @TODO: should not require an onclick
children: <Trans>Approve</Trans>,
},
}
}
if (approvalState === ApproveOrPermitState.PENDING_SIGNATURE) {
return {
disabled: true,
action: {
message: <Trans>Allowance pending</Trans>,
icon: Spinner,
children: <Trans>Allow</Trans>,
},
}
}
return {}
}, [approvalCurrencyAmount?.currency, approvalHash, approvalState, disableSwap, inputCurrency, onApprove, wrapType])
......
......@@ -6,7 +6,7 @@ import { SWAP_ROUTER_ADDRESSES, V2_ROUTER_ADDRESS, V3_ROUTER_ADDRESS } from 'con
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useERC20PermitFromTrade, UseERC20PermitState } from 'hooks/useERC20Permit'
import useTransactionDeadline from 'lib/hooks/useTransactionDeadline'
import { useCallback, useMemo } from 'react'
import { useCallback, useMemo, useState } from 'react'
import invariant from 'tiny-invariant'
import { getTxOptimizedSwapRouter, SwapRouterVersion } from 'utils/getTxOptimizedSwapRouter'
......@@ -171,39 +171,45 @@ export const useApproveOrPermit = (
gatherPermitSignature,
} = useERC20PermitFromTrade(trade, allowedSlippage, deadline)
const notApproved = approval === ApprovalState.NOT_APPROVED && !(signatureState === UseERC20PermitState.SIGNED)
// Track when the interaction is blocked on a wallet so a PENDING state can be returned.
const [isPendingWallet, setIsPendingWallet] = useState(false)
// If permit is supported, trigger a signature, if not create approval transaction.
const handleApproveOrPermit = useCallback(async () => {
setIsPendingWallet(true)
try {
if (signatureState === UseERC20PermitState.NOT_SIGNED && gatherPermitSignature) {
try {
return await gatherPermitSignature()
} catch (error) {
// Try to approve if gatherPermitSignature failed for any reason other than the user rejecting it.
if (error?.code !== 4001) {
return getApproval()
return await getApproval()
}
}
} else {
return getApproval()
return await getApproval()
}
} catch (e) {
// Swallow approval errors - user rejections do not need to be displayed.
} finally {
setIsPendingWallet(false)
}
}, [signatureState, gatherPermitSignature, getApproval])
const approvalState = useMemo(() => {
if (approval === ApprovalState.PENDING) {
return ApproveOrPermitState.PENDING_APPROVAL
}
if (signatureState === UseERC20PermitState.LOADING) {
} else if (signatureState === UseERC20PermitState.LOADING) {
return ApproveOrPermitState.PENDING_SIGNATURE
}
if (notApproved && Boolean(gatherPermitSignature)) {
return ApproveOrPermitState.REQUIRES_SIGNATURE
}
if (notApproved) {
return ApproveOrPermitState.REQUIRES_APPROVAL
}
} else if (approval !== ApprovalState.NOT_APPROVED || signatureState === UseERC20PermitState.SIGNED) {
return ApproveOrPermitState.APPROVED
}, [approval, gatherPermitSignature, notApproved, signatureState])
} else if (gatherPermitSignature) {
return isPendingWallet ? ApproveOrPermitState.PENDING_SIGNATURE : ApproveOrPermitState.REQUIRES_SIGNATURE
} else {
return isPendingWallet ? ApproveOrPermitState.PENDING_APPROVAL : ApproveOrPermitState.REQUIRES_APPROVAL
}
}, [approval, gatherPermitSignature, isPendingWallet, signatureState])
return {
approvalState,
......
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