Retry Transactions

Replace stuck transactions by preparing and sending calls again.

Key use cases:

  • Replace transactions stuck due to low gas prices
  • Speed up pending transactions by increasing gas fees
  • Override transactions that have been pending for too long
  • Cancel stuck transactions by replacing with a no-op

The Retry flow

  1. Send the initial transaction
  2. Monitor the transaction status
  3. If the transaction is stuck/pending too long, re-prepare the same call
  4. Send the transaction with higher gas to replace the stuck transaction
  5. The original transaction gets dropped from mempool

Prerequisites

If the original transaction is already being mined, the replacement transaction may be dropped. In this case, you won’t be able to retrieve data using the replacement’s call ID, and the original transaction will be included!

Required SDK version: ^v4.61.0

See the sendCalls SDK reference for full descriptions of the parameters used in the following example.

When re-sending calls without a nonceOverride, the client automatically uses the same nonce as the pending transaction, replacing it.

You’ll need the following env variables:

1import { client, config } from "./client.ts";
2
3// Send initial transaction
4const { preparedCallIds } = await client.sendCalls({
5 capabilities: {
6 paymasterService: {
7 policyId: config.policyId,
8 },
9 },
10 calls: [
11 {
12 to: "0x0000000000000000000000000000000000000000",
13 value: "0x00",
14 data: "0x",
15 },
16 ],
17});
18
19console.log("Initial transaction:", preparedCallIds[0]);
20
21// Check status
22const status = await client.getCallsStatus({
23 id: preparedCallIds[0]!,
24});
25
26console.log("Transaction status:", status.status);
27
28// If still pending (status 100), send replacement
29if (status.status === 100) {
30 console.log("Transaction pending, sending replacement...");
31
32 // Re-send without nonceOverride to replace stuck transaction
33 const { preparedCallIds: replacementIds } = await client.sendCalls({
34 capabilities: {
35 paymasterService: {
36 policyId: config.policyId,
37 },
38 },
39 calls: [
40 {
41 to: "0x0000000000000000000000000000000000000000",
42 value: "0x00",
43 data: "0x",
44 },
45 ],
46 });
47
48 console.log("Replacement transaction:", replacementIds[0]);
49
50 // Wait for replacement to confirm
51 const result = await client.waitForCallsStatus(replacementIds[0]!);
52
53 console.log("Replacement confirmed:", result);
54}