Skip to content

Commit 0e1d8d9

Browse files
fix(test): handle transaction already imported error in ensureSufficientStake
- Add error handling for parallel test execution in CI - Handle 'transaction already imported' error (-32003) gracefully - Wait and re-check balance after transaction submission - Make deposit operation idempotent for parallel test execution - Prevents nonce conflicts when multiple tests run simultaneously
1 parent a5c7194 commit 0e1d8d9

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

tests/test-utils.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,58 @@ export const ensureSufficientStake = async (
243243

244244
if (BigInt(account.stake.toString()) < BigInt(requiredStake.toString())) {
245245
await setNRlcBalance(walletAddress, requiredStake);
246-
await iexec.account.deposit(requiredStake);
246+
try {
247+
await iexec.account.deposit(requiredStake);
248+
} catch (error: any) {
249+
// Handle "transaction already imported" error - this can happen when
250+
// multiple tests run in parallel and try to deposit simultaneously.
251+
// If the transaction is already submitted, we can check if the balance
252+
// will be sufficient after it's mined, or just wait a bit and retry.
253+
if (
254+
error?.message?.includes('transaction already imported') ||
255+
error?.code === -32003 ||
256+
(error?.cause?.code === -32003 &&
257+
error?.cause?.message?.includes('transaction already imported'))
258+
) {
259+
// Wait a bit for the transaction to be mined
260+
await new Promise((resolve) => setTimeout(resolve, 2000));
261+
// Re-check balance - if it's now sufficient, we're good
262+
const updatedAccount = await iexec.account.checkBalance(walletAddress);
263+
if (
264+
BigInt(updatedAccount.stake.toString()) >=
265+
BigInt(requiredStake.toString())
266+
) {
267+
// Balance is sufficient, transaction was already processed
268+
return;
269+
}
270+
// If still insufficient, the transaction might be pending or failed
271+
// Try one more time after waiting
272+
try {
273+
await iexec.account.deposit(requiredStake);
274+
} catch (retryError: any) {
275+
// If it still fails with the same error, check balance one more time
276+
if (
277+
retryError?.message?.includes('transaction already imported') ||
278+
retryError?.code === -32003
279+
) {
280+
const finalAccount = await iexec.account.checkBalance(
281+
walletAddress
282+
);
283+
if (
284+
BigInt(finalAccount.stake.toString()) >=
285+
BigInt(requiredStake.toString())
286+
) {
287+
return;
288+
}
289+
}
290+
// If balance is still insufficient, throw the original error
291+
throw retryError;
292+
}
293+
} else {
294+
// For other errors, re-throw
295+
throw error;
296+
}
297+
}
247298
}
248299
};
249300

0 commit comments

Comments
 (0)