Commit 0e2344ba authored by eddie's avatar eddie Committed by GitHub

feat: refactor ConfirmSwapModal for clarity (#6729)

* feat: refactor ConfirmSwapModal for clarity

* fix: remove reset effect for now

* fix: catchUserReject update

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