From f53a6444979523cbbcc4ae4233656d58a5b872cf Mon Sep 17 00:00:00 2001 From: Mimi Tran <80493680+mimi-imtbl@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:48:32 +1000 Subject: [PATCH] [NO CHANGELOG][Add Funds Widget] Feat/add funds skip approval (#2263) --- .../src/widgets/add-funds/hooks/useExecute.ts | 24 ++++++++++++--- .../src/widgets/add-funds/views/Review.tsx | 29 +++++++++++-------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useExecute.ts b/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useExecute.ts index 841c46b5ba..e5ac8ebb23 100644 --- a/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useExecute.ts +++ b/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useExecute.ts @@ -19,6 +19,7 @@ export const useExecute = () => { if (!provider.provider.request) { throw Error('provider does not have request method'); } + try { const fromChainHex = `0x${parseInt(chainId, 10).toString(16)}`; const providerChainId = await provider.provider.request({ @@ -45,17 +46,31 @@ export const useExecute = () => { ): Promise => { try { if (!isSquidNativeToken(routeResponse?.route?.params.fromToken)) { - const fromToken = routeResponse?.route.params.fromToken; const erc20Abi = [ 'function approve(address spender, uint256 amount) public returns (bool)', + 'function allowance(address owner, address spender) public view returns (uint256)', ]; + const fromToken = routeResponse?.route.params.fromToken; const signer = provider.getSigner(); const tokenContract = new ethers.Contract(fromToken, erc20Abi, signer); - const transactionRequestTarget = routeResponse?.route?.transactionRequest?.target; const fromAmount = routeResponse?.route.params.fromAmount; - const tx = await tokenContract.approve(transactionRequestTarget, fromAmount); - await tx.wait(); + if (!fromAmount) { + throw new Error('fromAmount is undefined'); + } + + const transactionRequestTarget = routeResponse?.route?.transactionRequest?.target; + if (!transactionRequestTarget) { + throw new Error('transactionRequest target is undefined'); + } + + const ownerAddress = await signer.getAddress(); + const allowance = await tokenContract.allowance(ownerAddress, transactionRequestTarget); + + if (allowance.lt(fromAmount)) { + const tx = await tokenContract.approve(transactionRequestTarget, fromAmount); + await tx.wait(); + } } } catch (e) { throw Error('Error approving tokens'); @@ -70,6 +85,7 @@ export const useExecute = () => { if (!provider.provider.request) { throw Error('provider does not have request method'); } + try { const tx = (await squid.executeRoute({ signer: provider.getSigner(), diff --git a/packages/checkout/widgets-lib/src/widgets/add-funds/views/Review.tsx b/packages/checkout/widgets-lib/src/widgets/add-funds/views/Review.tsx index 67a0832330..982722648b 100644 --- a/packages/checkout/widgets-lib/src/widgets/add-funds/views/Review.tsx +++ b/packages/checkout/widgets-lib/src/widgets/add-funds/views/Review.tsx @@ -37,7 +37,7 @@ export function Review({ onBackButtonClick, onCloseButtonClick, }: ReviewProps) { const { viewDispatch } = useContext(ViewContext); - const { addFundsState } = useContext(AddFundsContext); + const { addFundsState: { squid, provider, chains } } = useContext(AddFundsContext); const [route, setRoute] = useState(); const [fromAddress, setFromAddress] = useState(); @@ -51,18 +51,18 @@ export function Review({ } = useExecute(); const getFromAmountAndRoute = async () => { - if (!addFundsState.squid) { + if (!squid) { return; } - const address = await addFundsState.provider?.getSigner().getAddress(); + const address = await provider?.getSigner().getAddress(); if (!address) { return; } setFromAddress(address); const amountData = await getFromAmount( - addFundsState.squid, + squid, data.balance, data.toAmount, data.toChainId, @@ -74,7 +74,7 @@ export function Review({ } const routeResponse = await getRoute( - addFundsState.squid, + squid, amountData?.fromToken, amountData?.toToken, data.toAmount, @@ -100,7 +100,7 @@ export function Review({ }, []); const getChain = (chainId: string | undefined) - : Chain | undefined => addFundsState.chains?.find((chain) => chain.id === chainId); + : Chain | undefined => chains?.find((chain) => chain.id === chainId); const getFeeCosts = (): number => route?.route.estimate.feeCosts.reduce((acc, fee) => acc + Number(fee.amountUsd), 0) ?? 0; @@ -130,17 +130,22 @@ export function Review({ }; const onProceedClick = async () => { - if (!addFundsState.squid || !addFundsState.provider || !route) { + if (!squid || !provider || !route) { return; } + try { clearInterval(getRouteIntervalId); setProceedDisabled(true); - const provider = await convertToNetworkChangeableProvider(addFundsState.provider); - await checkProviderChain(provider, route.route.params.fromChain); - await approve(provider, route); - const txReceipt = await execute(addFundsState.squid, provider, route); + const changeableProvider = await convertToNetworkChangeableProvider(provider); + + await checkProviderChain(changeableProvider, route.route.params.fromChain); + + await approve(changeableProvider, route); + + const txReceipt = await execute(squid, changeableProvider, route); + viewDispatch({ payload: { type: ViewActions.UPDATE_VIEW, @@ -152,7 +157,7 @@ export function Review({ }, }, }); - } catch (e: unknown) { + } catch (e) { viewDispatch({ payload: { type: ViewActions.UPDATE_VIEW,