diff --git a/src/transaction/components/TransactionProvider.test.tsx b/src/transaction/components/TransactionProvider.test.tsx
index 7e0fc9e370..3c7cb18d60 100644
--- a/src/transaction/components/TransactionProvider.test.tsx
+++ b/src/transaction/components/TransactionProvider.test.tsx
@@ -5,6 +5,7 @@ import {
useSwitchChain,
useWaitForTransactionReceipt,
} from 'wagmi';
+import { METHOD_NOT_SUPPORTED_ERROR_SUBSTRING } from '../constants';
import { useCallsStatus } from '../hooks/useCallsStatus';
import { useWriteContract } from '../hooks/useWriteContract';
import { useWriteContracts } from '../hooks/useWriteContracts';
@@ -235,16 +236,13 @@ describe('TransactionProvider', () => {
statusWriteContracts: 'IDLE',
writeContractsAsync: writeContractsAsyncMock,
});
-
render(
,
);
-
const button = screen.getByText('Submit');
fireEvent.click(button);
-
await waitFor(() => {
const errorMessage = screen.getByTestId('context-value-errorMessage');
expect(errorMessage.textContent).toBe('Request denied.');
@@ -259,7 +257,6 @@ describe('TransactionProvider', () => {
(useCallsStatus as ReturnType).mockReturnValue({
transactionHash: 'hash',
});
-
render(
{
,
);
-
await waitFor(() => {
expect(onSuccessMock).toHaveBeenCalledWith({
transactionReceipts: [{ status: 'success' }],
@@ -283,21 +279,43 @@ describe('TransactionProvider', () => {
switchChainAsync: switchChainAsyncMock,
});
(useAccount as ReturnType).mockReturnValue({ chainId: 1 });
-
render(
,
);
-
const button = screen.getByText('Submit');
fireEvent.click(button);
-
await waitFor(() => {
expect(switchChainAsyncMock).toHaveBeenCalledWith({ chainId: 2 });
});
});
+ it('should call fallbackToWriteContract when executeContracts fails', async () => {
+ const writeContractsAsyncMock = vi
+ .fn()
+ .mockRejectedValue(new Error(METHOD_NOT_SUPPORTED_ERROR_SUBSTRING));
+ const writeContractAsyncMock = vi.fn();
+ (useWriteContracts as ReturnType).mockReturnValue({
+ statusWriteContracts: 'IDLE',
+ writeContractsAsync: writeContractsAsyncMock,
+ });
+ (useWriteContract as ReturnType).mockReturnValue({
+ status: 'IDLE',
+ writeContractAsync: writeContractAsyncMock,
+ });
+ render(
+
+
+ ,
+ );
+ const button = screen.getByText('Submit');
+ fireEvent.click(button);
+ await waitFor(() => {
+ expect(writeContractAsyncMock).toHaveBeenCalled();
+ });
+ });
+
it('should handle generic error during fallback', async () => {
const writeContractsAsyncMock = vi
.fn()
@@ -313,16 +331,13 @@ describe('TransactionProvider', () => {
status: 'IDLE',
writeContractAsync: writeContractAsyncMock,
});
-
render(
,
);
-
const button = screen.getByText('Submit');
fireEvent.click(button);
-
await waitFor(() => {
expect(screen.getByTestId('context-value-errorMessage').textContent).toBe(
'Something went wrong. Please try again.',
diff --git a/src/transaction/components/TransactionProvider.tsx b/src/transaction/components/TransactionProvider.tsx
index 086b1fd6e0..b487ae0eb7 100644
--- a/src/transaction/components/TransactionProvider.tsx
+++ b/src/transaction/components/TransactionProvider.tsx
@@ -118,8 +118,14 @@ export function TransactionProvider({
});
receipts.push(txnReceipt);
} catch (err) {
- console.error('getTransactionReceiptsError', err);
- setErrorMessage(GENERIC_ERROR_MESSAGE);
+ setLifeCycleStatus({
+ statusName: 'error',
+ statusData: {
+ code: 'TmTPc01', // Transaction module TransactionProvider component 01 error
+ error: JSON.stringify(err),
+ message: GENERIC_ERROR_MESSAGE,
+ },
+ });
}
}
setReceiptArray(receipts);
@@ -144,7 +150,14 @@ export function TransactionProvider({
const errorMessage = isUserRejectedRequestError(err)
? 'Request denied.'
: GENERIC_ERROR_MESSAGE;
- setErrorMessage(errorMessage);
+ setLifeCycleStatus({
+ statusName: 'error',
+ statusData: {
+ code: 'TmTPc02', // Transaction module TransactionProvider component 02 error
+ error: JSON.stringify(err),
+ message: errorMessage,
+ },
+ });
}
}
}, [contracts, writeContractAsync]);
@@ -165,30 +178,6 @@ export function TransactionProvider({
});
}, [writeContractsAsync, contracts, capabilities]);
- const handleSubmitErrors = useCallback(
- async (err: unknown) => {
- // handles EOA writeContracts error
- // (fallback to writeContract)
- if (
- err instanceof Error &&
- err.message.includes(METHOD_NOT_SUPPORTED_ERROR_SUBSTRING)
- ) {
- try {
- await fallbackToWriteContract();
- } catch (_err) {
- setErrorMessage(GENERIC_ERROR_MESSAGE);
- }
- // handles user rejected request error
- } else if (isUserRejectedRequestError(err)) {
- setErrorMessage('Request denied.');
- // handles generic error
- } else {
- setErrorMessage(GENERIC_ERROR_MESSAGE);
- }
- },
- [fallbackToWriteContract],
- );
-
const handleSubmit = useCallback(async () => {
setErrorMessage('');
setIsToastVisible(true);
@@ -196,9 +185,27 @@ export function TransactionProvider({
await switchChain(chainId);
await executeContracts();
} catch (err) {
- await handleSubmitErrors(err);
+ // handles EOA writeContracts error (fallback to writeContract)
+ if (
+ err instanceof Error &&
+ err.message.includes(METHOD_NOT_SUPPORTED_ERROR_SUBSTRING)
+ ) {
+ await fallbackToWriteContract();
+ return;
+ }
+ const errorMessage = isUserRejectedRequestError(err)
+ ? 'Request denied.'
+ : GENERIC_ERROR_MESSAGE;
+ setLifeCycleStatus({
+ statusName: 'error',
+ statusData: {
+ code: 'TmTPc03', // Transaction module TransactionProvider component 03 error
+ error: JSON.stringify(err),
+ message: errorMessage,
+ },
+ });
}
- }, [chainId, executeContracts, handleSubmitErrors, switchChain]);
+ }, [chainId, executeContracts, fallbackToWriteContract, switchChain]);
useEffect(() => {
if (receiptArray?.length) {
diff --git a/src/transaction/hooks/useTransactionReceipts.ts b/src/transaction/hooks/useTransactionReceipts.ts
new file mode 100644
index 0000000000..e69de29bb2