diff --git a/src/components/Swap/SwapActionButton/Permit2Button.tsx b/src/components/Swap/SwapActionButton/Permit2Button.tsx index 861cfc80d..fd4a70ae1 100644 --- a/src/components/Swap/SwapActionButton/Permit2Button.tsx +++ b/src/components/Swap/SwapActionButton/Permit2Button.tsx @@ -22,12 +22,13 @@ export default function PermitButton({ }: { color: keyof Colors trade?: InterfaceTrade - callback?: () => Promise - onSubmit: (submit?: () => Promise) => Promise + callback?: (isPendingApproval: boolean) => Promise + onSubmit: (submit: () => Promise) => Promise }) { const currency = trade?.inputAmount?.currency const [isPending, setIsPending] = useState(false) const [isFailed, setIsFailed] = useState(false) + const pendingApproval = usePendingApproval(currency?.isToken ? currency : undefined, PERMIT2_ADDRESS) useEffect(() => { // Reset pending/failed state if currency changes. setIsPending(false) @@ -37,7 +38,7 @@ export default function PermitButton({ const onClick = useCallback(async () => { setIsPending(true) try { - await onSubmit(callback) + await onSubmit(async () => await callback?.(Boolean(pendingApproval))) setIsFailed(false) } catch (e) { console.error(e) @@ -45,9 +46,7 @@ export default function PermitButton({ } finally { setIsPending(false) } - }, [callback, onSubmit]) - - const pendingApproval = usePendingApproval(currency?.isToken ? currency : undefined, PERMIT2_ADDRESS) + }, [callback, onSubmit, pendingApproval]) const action = useMemo(() => { if (isPending) { diff --git a/src/components/Swap/SwapActionButton/SwapButton.tsx b/src/components/Swap/SwapActionButton/SwapButton.tsx index a6bde6925..bbb0e1ece 100644 --- a/src/components/Swap/SwapActionButton/SwapButton.tsx +++ b/src/components/Swap/SwapActionButton/SwapButton.tsx @@ -33,7 +33,7 @@ export default function SwapButton({ }: { color: keyof Colors disabled: boolean - onSubmit: (submit?: () => Promise) => Promise + onSubmit: (submit: () => Promise) => Promise }) { const { account, chainId } = useWeb3React() const { diff --git a/src/components/Swap/SwapActionButton/useOnSubmit.ts b/src/components/Swap/SwapActionButton/useOnSubmit.ts index 0d10214c8..4286fbc7a 100644 --- a/src/components/Swap/SwapActionButton/useOnSubmit.ts +++ b/src/components/Swap/SwapActionButton/useOnSubmit.ts @@ -13,8 +13,8 @@ export default function useOnSubmit() { const [, setInputAmount] = useSwapAmount(Field.INPUT) return useCallback( - async (submit?: () => Promise): Promise => { - const info = await submit?.() + async (submit: () => Promise): Promise => { + const info = await submit() if (!info) return addTransactionInfo(info) diff --git a/src/hooks/usePermit2.ts b/src/hooks/usePermit2.ts index 2c27eed4c..25c8bc7bc 100644 --- a/src/hooks/usePermit2.ts +++ b/src/hooks/usePermit2.ts @@ -18,17 +18,25 @@ export enum PermitState { export interface Permit { state: PermitState signature?: PermitSignature - callback?: () => Promise + callback?: (isPendingApproval: boolean) => Promise } export default function usePermit(amount?: CurrencyAmount, spender?: string): Permit { const { account } = useWeb3React() const tokenAllowance = useTokenAllowance(amount?.currency, account, PERMIT2_ADDRESS) const updateTokenAllowance = useUpdateTokenAllowance(amount, PERMIT2_ADDRESS) + const isAllowed = useMemo( + () => amount && (tokenAllowance?.greaterThan(amount) || tokenAllowance?.equalTo(amount)), + [amount, tokenAllowance] + ) const permitAllowance = usePermitAllowance(amount?.currency, spender) const [permitAllowanceAmount, setPermitAllowanceAmount] = useState(permitAllowance?.amount) useEffect(() => setPermitAllowanceAmount(permitAllowance?.amount), [permitAllowance?.amount]) + const isPermitted = useMemo( + () => amount && permitAllowanceAmount?.gte(amount.quotient.toString()), + [amount, permitAllowanceAmount] + ) const [signature, setSignature] = useState() const updatePermitAllowance = useUpdatePermitAllowance( @@ -37,12 +45,10 @@ export default function usePermit(amount?: CurrencyAmount, spender?: stri permitAllowance?.nonce, setSignature ) - - const updateTokenAndPermitAllowance = useCallback(async () => { - const info = await updateTokenAllowance() - await updatePermitAllowance() - return info - }, [updatePermitAllowance, updateTokenAllowance]) + const isSigned = useMemo( + () => amount && signature?.details.token === amount?.currency.address && signature?.spender === spender, + [amount, signature?.details.token, signature?.spender, spender] + ) // Trigger a re-render if either tokenAllowance or signature expire. useInterval( @@ -60,27 +66,30 @@ export default function usePermit(amount?: CurrencyAmount, spender?: stri true ) + const callback = useCallback( + async (isPendingApproval: boolean) => { + let info: ApprovalTransactionInfo | undefined + if (!isAllowed && !isPendingApproval) { + info = await updateTokenAllowance() + } + if (!isPermitted && !isSigned) { + await updatePermitAllowance() + } + return info + }, + [isAllowed, isPermitted, isSigned, updatePermitAllowance, updateTokenAllowance] + ) + return useMemo(() => { if (!amount || !tokenAllowance) { return { state: PermitState.UNKNOWN } - } else if (tokenAllowance.greaterThan(amount) || tokenAllowance.equalTo(amount)) { - if (permitAllowanceAmount?.gte(amount.quotient.toString())) { + } else if (isAllowed) { + if (isPermitted) { return { state: PermitState.PERMITTED } - } else if (signature?.details.token === amount.currency.address && signature?.spender === spender) { + } else if (isSigned) { return { state: PermitState.PERMITTED, signature } - } else { - return { state: PermitState.PERMIT_NEEDED, callback: updatePermitAllowance } } - } else { - return { state: PermitState.PERMIT_NEEDED, callback: updateTokenAndPermitAllowance } } - }, [ - amount, - permitAllowanceAmount, - signature, - spender, - tokenAllowance, - updatePermitAllowance, - updateTokenAndPermitAllowance, - ]) + return { state: PermitState.PERMIT_NEEDED, callback } + }, [amount, callback, isAllowed, isPermitted, isSigned, signature, tokenAllowance]) }