From 58c67298ddddf668f50c039c40a30e821a49b9ae Mon Sep 17 00:00:00 2001 From: Martin Grabina Date: Wed, 4 Mar 2026 12:56:22 -0300 Subject: [PATCH] fix: handle unparseable tx responses from delegation wallets MetaMask Delegation Framework (and similar SC wallets) can return transaction responses where ethers v5 cannot parse fields like nonce, causing an INVALID_ARGUMENT error even though the tx succeeded on-chain. Recover by catching the specific error pattern (INVALID_ARGUMENT with a transactionHash present) and falling back to waitForTransaction. The shim checks receipt.status to properly surface reverted transactions. Co-Authored-By: Claude Opus 4.6 --- src/libs/web3-data-provider/Web3Provider.tsx | 32 +++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/libs/web3-data-provider/Web3Provider.tsx b/src/libs/web3-data-provider/Web3Provider.tsx index 26fe83287c..92d8bb179b 100644 --- a/src/libs/web3-data-provider/Web3Provider.tsx +++ b/src/libs/web3-data-provider/Web3Provider.tsx @@ -96,10 +96,34 @@ export const Web3ContextProvider: React.FC<{ children: ReactElement }> = ({ chil if (provider) { const { from, ...data } = txData; const signer = provider.getSigner(from); - const txResponse: TransactionResponse = await signer.sendTransaction({ - ...data, - value: data.value ? BigNumber.from(data.value) : undefined, - }); + const txResponse: TransactionResponse = await signer + .sendTransaction({ + ...data, + value: data.value ? BigNumber.from(data.value) : undefined, + }) + .catch(async (error) => { + // Some wallets (MetaMask Delegation Framework, Safe) return tx responses + // that ethers v5 can't parse (e.g. undefined nonce). The tx was already + // sent successfully — recover by waiting for the receipt by hash. + if (error.code === 'INVALID_ARGUMENT' && error.transactionHash) { + const receipt = await provider.waitForTransaction(error.transactionHash); + if (receipt.status === 0) { + throw new Error('transaction failed'); + } + return { + hash: error.transactionHash, + wait: async (confirmations?: number) => { + if (confirmations && confirmations > 1) { + const r = await provider.waitForTransaction(error.transactionHash, confirmations); + if (r.status === 0) throw new Error('transaction failed'); + return r; + } + return receipt; + }, + } as TransactionResponse; + } + throw error; + }); return txResponse; } throw new Error('Error sending transaction. Provider not found');