feat: refactor ConfirmSwapModal for clarity (#6729)
* feat: refactor ConfirmSwapModal for clarity * fix: remove reset effect for now * fix: catchUserReject update * fix: remove unnecessary awaits
This commit is contained in:
parent
309d03b5e7
commit
0e2344ba85
@ -20,6 +20,7 @@ import { useCallback, useEffect, useState } from 'react'
|
||||
import { InterfaceTrade } from 'state/routing/types'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ThemedText } from 'theme'
|
||||
import invariant from 'tiny-invariant'
|
||||
import { isL2ChainId } from 'utils/chains'
|
||||
import { formatSwapPriceUpdatedEventProperties } from 'utils/loggingFormatters'
|
||||
import { didUserReject } from 'utils/swapErrorToUserReadableMessage'
|
||||
@ -71,7 +72,7 @@ function useConfirmModalState({
|
||||
// This is a function instead of a memoized value because we do _not_ want it to update as the allowance changes.
|
||||
// For example, if the user needs to complete 3 steps initially, we should always show 3 step indicators
|
||||
// at the bottom of the modal, even after they complete steps 1 and 2.
|
||||
const prepareSwapFlow = useCallback(() => {
|
||||
const generateRequiredSteps = useCallback(() => {
|
||||
const steps: PendingConfirmModalState[] = []
|
||||
if (allowance.state === AllowanceState.REQUIRED && allowance.needsSetupApproval) {
|
||||
steps.push(ConfirmModalState.APPROVING_TOKEN)
|
||||
@ -80,48 +81,66 @@ function useConfirmModalState({
|
||||
steps.push(ConfirmModalState.PERMITTING)
|
||||
}
|
||||
steps.push(ConfirmModalState.PENDING_CONFIRMATION)
|
||||
setPendingModalSteps(steps)
|
||||
return steps
|
||||
}, [allowance])
|
||||
|
||||
const { chainId } = useWeb3React()
|
||||
const trace = useTrace()
|
||||
const maximumAmountIn = useMaxAmountIn(trade, allowedSlippage)
|
||||
|
||||
const startSwapFlow = useCallback(async () => {
|
||||
setApprovalError(undefined)
|
||||
if (allowance.state === AllowanceState.REQUIRED) {
|
||||
// Starts the approval process, by triggering either the Token Approval or the Permit signature.
|
||||
try {
|
||||
if (allowance.needsSetupApproval) {
|
||||
setConfirmModalState(ConfirmModalState.APPROVING_TOKEN)
|
||||
await allowance.approve()
|
||||
sendAnalyticsEvent(InterfaceEventName.APPROVE_TOKEN_TXN_SUBMITTED, {
|
||||
chain_id: chainId,
|
||||
token_symbol: maximumAmountIn?.currency.symbol,
|
||||
token_address: maximumAmountIn?.currency.address,
|
||||
...trace,
|
||||
})
|
||||
} else {
|
||||
setConfirmModalState(ConfirmModalState.PERMITTING)
|
||||
await allowance.permit()
|
||||
}
|
||||
} catch (e) {
|
||||
setConfirmModalState(ConfirmModalState.REVIEWING)
|
||||
if (didUserReject(e)) {
|
||||
return
|
||||
}
|
||||
console.error(e)
|
||||
setApprovalError(
|
||||
allowance.needsSetupApproval ? PendingModalError.TOKEN_APPROVAL_ERROR : PendingModalError.PERMIT_ERROR
|
||||
)
|
||||
}
|
||||
} else {
|
||||
setConfirmModalState(ConfirmModalState.PENDING_CONFIRMATION)
|
||||
onSwap()
|
||||
}
|
||||
}, [allowance, chainId, maximumAmountIn?.currency.address, maximumAmountIn?.currency.symbol, onSwap, trace])
|
||||
const catchUserReject = async (e: any, errorType: PendingModalError) => {
|
||||
setConfirmModalState(ConfirmModalState.REVIEWING)
|
||||
if (didUserReject(e)) return
|
||||
console.error(e)
|
||||
setApprovalError(errorType)
|
||||
}
|
||||
|
||||
const previousPermitNeeded = usePrevious(
|
||||
const performStep = useCallback(
|
||||
async (step: ConfirmModalState) => {
|
||||
switch (step) {
|
||||
case ConfirmModalState.APPROVING_TOKEN:
|
||||
setConfirmModalState(ConfirmModalState.APPROVING_TOKEN)
|
||||
invariant(allowance.state === AllowanceState.REQUIRED, 'Allowance should be required')
|
||||
allowance
|
||||
.approve()
|
||||
.then(() => {
|
||||
sendAnalyticsEvent(InterfaceEventName.APPROVE_TOKEN_TXN_SUBMITTED, {
|
||||
chain_id: chainId,
|
||||
token_symbol: maximumAmountIn?.currency.symbol,
|
||||
token_address: maximumAmountIn?.currency.address,
|
||||
...trace,
|
||||
})
|
||||
})
|
||||
.catch((e) => catchUserReject(e, PendingModalError.TOKEN_APPROVAL_ERROR))
|
||||
break
|
||||
case ConfirmModalState.PERMITTING:
|
||||
setConfirmModalState(ConfirmModalState.PERMITTING)
|
||||
invariant(allowance.state === AllowanceState.REQUIRED, 'Allowance should be required')
|
||||
allowance.permit().catch((e) => catchUserReject(e, PendingModalError.TOKEN_APPROVAL_ERROR))
|
||||
break
|
||||
case ConfirmModalState.PENDING_CONFIRMATION:
|
||||
setConfirmModalState(ConfirmModalState.PENDING_CONFIRMATION)
|
||||
try {
|
||||
onSwap()
|
||||
} catch (e) {
|
||||
catchUserReject(e, PendingModalError.CONFIRMATION_ERROR)
|
||||
}
|
||||
break
|
||||
default:
|
||||
setConfirmModalState(ConfirmModalState.REVIEWING)
|
||||
break
|
||||
}
|
||||
},
|
||||
[allowance, chainId, maximumAmountIn?.currency.address, maximumAmountIn?.currency.symbol, onSwap, trace]
|
||||
)
|
||||
|
||||
const startSwapFlow = useCallback(() => {
|
||||
const steps = generateRequiredSteps()
|
||||
setPendingModalSteps(steps)
|
||||
performStep(steps[0])
|
||||
}, [generateRequiredSteps, performStep])
|
||||
|
||||
const previousSetupApprovalNeeded = usePrevious(
|
||||
allowance.state === AllowanceState.REQUIRED ? allowance.needsSetupApproval : undefined
|
||||
)
|
||||
useEffect(() => {
|
||||
@ -130,11 +149,11 @@ function useConfirmModalState({
|
||||
allowance.needsPermitSignature &&
|
||||
// If the token approval switched from missing to fulfilled, trigger the next step (permit2 signature).
|
||||
!allowance.needsSetupApproval &&
|
||||
previousPermitNeeded
|
||||
previousSetupApprovalNeeded
|
||||
) {
|
||||
startSwapFlow()
|
||||
performStep(ConfirmModalState.PERMITTING)
|
||||
}
|
||||
}, [allowance, previousPermitNeeded, startSwapFlow])
|
||||
}, [allowance, performStep, previousSetupApprovalNeeded])
|
||||
|
||||
useEffect(() => {
|
||||
// Automatically triggers the next phase if the local modal state still thinks we're in the approval phase,
|
||||
@ -145,16 +164,16 @@ function useConfirmModalState({
|
||||
setConfirmModalState(ConfirmModalState.REVIEWING)
|
||||
return
|
||||
}
|
||||
startSwapFlow()
|
||||
performStep(ConfirmModalState.PENDING_CONFIRMATION)
|
||||
}
|
||||
}, [allowance, confirmModalState, doesTradeDiffer, startSwapFlow])
|
||||
}, [allowance, confirmModalState, doesTradeDiffer, performStep])
|
||||
|
||||
const onCancel = () => {
|
||||
setConfirmModalState(ConfirmModalState.REVIEWING)
|
||||
setApprovalError(undefined)
|
||||
}
|
||||
|
||||
return { startSwapFlow, prepareSwapFlow, onCancel, confirmModalState, approvalError, pendingModalSteps }
|
||||
return { startSwapFlow, onCancel, confirmModalState, approvalError, pendingModalSteps }
|
||||
}
|
||||
|
||||
export default function ConfirmSwapModal({
|
||||
@ -186,14 +205,13 @@ export default function ConfirmSwapModal({
|
||||
}) {
|
||||
const { chainId } = useWeb3React()
|
||||
const doesTradeDiffer = originalTrade && tradeMeaningfullyDiffers(trade, originalTrade, allowedSlippage)
|
||||
const { startSwapFlow, onCancel, confirmModalState, approvalError, pendingModalSteps, prepareSwapFlow } =
|
||||
useConfirmModalState({
|
||||
trade,
|
||||
allowedSlippage,
|
||||
onSwap: onConfirm,
|
||||
allowance,
|
||||
doesTradeDiffer: Boolean(doesTradeDiffer),
|
||||
})
|
||||
const { startSwapFlow, onCancel, confirmModalState, approvalError, pendingModalSteps } = useConfirmModalState({
|
||||
trade,
|
||||
allowedSlippage,
|
||||
onSwap: onConfirm,
|
||||
allowance,
|
||||
doesTradeDiffer: Boolean(doesTradeDiffer),
|
||||
})
|
||||
|
||||
const swapFailed = Boolean(swapError) && !didUserReject(swapError)
|
||||
useEffect(() => {
|
||||
@ -242,11 +260,7 @@ export default function ConfirmSwapModal({
|
||||
if (confirmModalState === ConfirmModalState.REVIEWING || showAcceptChanges) {
|
||||
return (
|
||||
<SwapModalFooter
|
||||
onConfirm={() => {
|
||||
// Calculate the necessary steps once, before starting the flow.
|
||||
prepareSwapFlow()
|
||||
startSwapFlow()
|
||||
}}
|
||||
onConfirm={startSwapFlow}
|
||||
trade={trade}
|
||||
hash={txHash}
|
||||
allowedSlippage={allowedSlippage}
|
||||
@ -284,7 +298,6 @@ export default function ConfirmSwapModal({
|
||||
onAcceptChanges,
|
||||
swapFailed,
|
||||
swapError?.message,
|
||||
prepareSwapFlow,
|
||||
startSwapFlow,
|
||||
])
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user