From 999c9b4bd27033c2348ab5457338a16cf96d39c5 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 19 Feb 2025 13:21:48 +0100 Subject: [PATCH 1/2] push and test --- .../__tests__/DepositOrWithdrawModal.test.ts | 56 +++++++++++++ .../components/DepositOrWithdrawModal.svelte | 83 +++++++++++-------- 2 files changed, 104 insertions(+), 35 deletions(-) diff --git a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts index 171f82535..353bcb48b 100644 --- a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts +++ b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts @@ -6,6 +6,8 @@ import { signerAddress } from '$lib/stores/wagmi'; import { readContract, switchChain } from '@wagmi/core'; import type { ComponentProps } from 'svelte'; +import { getVaultApprovalCalldata } from '@rainlanguage/orderbook/js_api'; +import { getVaultDepositCalldata } from '@rainlanguage/orderbook/js_api'; export type ModalProps = ComponentProps; @@ -173,4 +175,58 @@ describe('DepositOrWithdrawModal', () => { const continueButton = screen.getByText('Deposit'); expect(continueButton).toBeDisabled(); }); + + it('shows loading state while checking calldata', async () => { + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const depositButton = screen.getByText('Deposit'); + await fireEvent.click(depositButton); + + expect(screen.getByText('Checking...')).toBeInTheDocument(); + }); + + it('handles failed calldata fetch', async () => { + const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); + vi.mocked(getVaultDepositCalldata).mockRejectedValueOnce(new Error('Failed to fetch')); + + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const depositButton = screen.getByText('Deposit'); + await fireEvent.click(depositButton); + + await waitFor(() => { + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to get calldata:', expect.any(Error)); + }); + + consoleErrorSpy.mockRestore(); + }); + + it('handles deposit without approval when approval fails', async () => { + const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); + vi.mocked(getVaultApprovalCalldata).mockRejectedValueOnce(new Error('Approval not needed')); + + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const depositButton = screen.getByText('Deposit'); + await fireEvent.click(depositButton); + + expect(handleTransactionSpy).toHaveBeenCalledWith({ + action: 'deposit', + chainId: 1, + vault: mockVault, + config: undefined, + subgraphUrl: undefined, + approvalCalldata: undefined, + transactionCalldata: { to: '0x123', data: '0x456' } + }); + }); }); diff --git a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte index 3066c256e..025e87d48 100644 --- a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte +++ b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte @@ -44,6 +44,10 @@ let amount: bigint = 0n; let userBalance: bigint = 0n; let switchChainError = ''; + let depositCalldata: DepositCalldataResult | undefined = undefined; + let approvalCalldata: ApprovalCalldata | undefined = undefined; + let withdrawCalldata: WithdrawCalldataResult | undefined = undefined; + let isCheckingCalldata = false; const messages = { success: 'Transaction successful.', @@ -70,42 +74,45 @@ }); }; + async function handleTransaction( + transactionCalldata: DepositCalldataResult | WithdrawCalldataResult, + approvalCalldata?: ApprovalCalldata | undefined + ) { + transactionStore.handleDepositOrWithdrawTransaction({ + config: $wagmiConfig, + transactionCalldata, + approvalCalldata, + action, + chainId, + vault, + subgraphUrl + }); + } + async function handleContinue() { - if (action === 'deposit') { - let approvalCalldata: ApprovalCalldata | undefined = undefined; - try { - approvalCalldata = await getVaultApprovalCalldata(rpcUrl, vault, amount.toString()); - } catch { - approvalCalldata = undefined; + isCheckingCalldata = true; + try { + if (action === 'deposit') { + try { + approvalCalldata = await getVaultApprovalCalldata(rpcUrl, vault, amount.toString()); + } catch { + approvalCalldata = undefined; + } + depositCalldata = await getVaultDepositCalldata(vault, amount.toString()); + if (depositCalldata) { + handleTransaction(depositCalldata, approvalCalldata); + } + } else if (action === 'withdraw') { + withdrawCalldata = await getVaultWithdrawCalldata(vault, amount.toString()); + if (withdrawCalldata) { + handleTransaction(withdrawCalldata); + } } - const depositCalldata: DepositCalldataResult = await getVaultDepositCalldata( - vault, - amount.toString() - ); - currentStep = 2; - transactionStore.handleDepositOrWithdrawTransaction({ - config: $wagmiConfig, - transactionCalldata: depositCalldata, - approvalCalldata, - action, - chainId, - vault, - subgraphUrl - }); - } else if (action === 'withdraw') { - const withdrawCalldata: WithdrawCalldataResult = await getVaultWithdrawCalldata( - vault, - amount.toString() - ); currentStep = 2; - transactionStore.handleDepositOrWithdrawTransaction({ - config: $wagmiConfig, - transactionCalldata: withdrawCalldata, - action, - chainId, - vault, - subgraphUrl - }); + } catch (error) { + console.error('Failed to get calldata:', error); + } finally { + isCheckingCalldata = false; } } @@ -142,9 +149,15 @@ {:else} From eeef434513762379f279a061d9a70bb72d9f1caf Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 19 Feb 2025 15:04:38 +0100 Subject: [PATCH 2/2] error --- .../src/__tests__/DepositOrWithdrawModal.test.ts | 7 ++----- .../src/lib/components/DepositOrWithdrawModal.svelte | 12 ++++++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts index 353bcb48b..9de809754 100644 --- a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts +++ b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts @@ -149,7 +149,7 @@ describe('DepositOrWithdrawModal', () => { render(DepositOrWithdrawModal, defaultProps); await waitFor(() => { - expect(screen.getByTestId('chain-error')).toHaveTextContent( + expect(screen.getByTestId('error-message')).toHaveTextContent( 'Switch to Ethereum to check your balance.' ); }); @@ -189,7 +189,6 @@ describe('DepositOrWithdrawModal', () => { }); it('handles failed calldata fetch', async () => { - const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); vi.mocked(getVaultDepositCalldata).mockRejectedValueOnce(new Error('Failed to fetch')); render(DepositOrWithdrawModal, defaultProps); @@ -201,10 +200,8 @@ describe('DepositOrWithdrawModal', () => { await fireEvent.click(depositButton); await waitFor(() => { - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to get calldata:', expect.any(Error)); + expect(screen.getByTestId('error-message')).toHaveTextContent('Failed to get calldata.'); }); - - consoleErrorSpy.mockRestore(); }); it('handles deposit without approval when approval fails', async () => { diff --git a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte index 025e87d48..e2eb19afb 100644 --- a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte +++ b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte @@ -43,7 +43,7 @@ let currentStep = 1; let amount: bigint = 0n; let userBalance: bigint = 0n; - let switchChainError = ''; + let errorMessage = ''; let depositCalldata: DepositCalldataResult | undefined = undefined; let approvalCalldata: ApprovalCalldata | undefined = undefined; let withdrawCalldata: WithdrawCalldataResult | undefined = undefined; @@ -64,7 +64,7 @@ try { await switchChain($wagmiConfig, { chainId }); } catch { - return (switchChainError = `Switch to ${targetChain.name} to check your balance.`); + return (errorMessage = `Switch to ${targetChain.name} to check your balance.`); } userBalance = await readContract($wagmiConfig, { abi: erc20Abi, @@ -109,8 +109,8 @@ } } currentStep = 2; - } catch (error) { - console.error('Failed to get calldata:', error); + } catch { + errorMessage = 'Failed to get calldata.'; } finally { isCheckingCalldata = false; } @@ -164,8 +164,8 @@ {/if} - {#if switchChainError} -

{switchChainError}

+ {#if errorMessage} +

{errorMessage}

{/if} {#if amountGreaterThanBalance[actionType]}

Amount cannot exceed available balance.