Skip to content

Commit a121730

Browse files
authored
fix: retry-failed creates undefined nonce value (#766)
* fix: retry-failed creates undefined nonce value * type import
1 parent 32961ab commit a121730

File tree

3 files changed

+42
-30
lines changed

3 files changed

+42
-30
lines changed

src/server/middleware/error.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,17 @@ const isZodError = (err: unknown): boolean => {
5353

5454
export const withErrorHandler = async (server: FastifyInstance) => {
5555
server.setErrorHandler(
56-
(error: Error | CustomError | ZodError, request, reply) => {
56+
(error: string | Error | CustomError | ZodError, request, reply) => {
57+
if (typeof error === "string") {
58+
return reply.status(StatusCodes.INTERNAL_SERVER_ERROR).send({
59+
error: {
60+
statusCode: 500,
61+
code: "INTERNAL_SERVER_ERROR",
62+
message: error || ReasonPhrases.INTERNAL_SERVER_ERROR,
63+
},
64+
});
65+
}
66+
5767
// Ethers Error Codes
5868
if (parseEthersError(error)) {
5969
return reply.status(StatusCodes.BAD_REQUEST).send({
@@ -103,25 +113,24 @@ export const withErrorHandler = async (server: FastifyInstance) => {
103113
StatusCodes.INTERNAL_SERVER_ERROR;
104114

105115
const message = error.message ?? ReasonPhrases.INTERNAL_SERVER_ERROR;
106-
reply.status(statusCode).send({
116+
return reply.status(statusCode).send({
107117
error: {
108118
code,
109119
message,
110120
statusCode,
111121
stack: env.NODE_ENV !== "production" ? error.stack : undefined,
112122
},
113123
});
114-
} else {
115-
// Handle non-custom errors
116-
reply.status(StatusCodes.INTERNAL_SERVER_ERROR).send({
117-
error: {
118-
statusCode: 500,
119-
code: "INTERNAL_SERVER_ERROR",
120-
message: error.message || ReasonPhrases.INTERNAL_SERVER_ERROR,
121-
stack: env.NODE_ENV !== "production" ? error.stack : undefined,
122-
},
123-
});
124124
}
125+
126+
reply.status(StatusCodes.INTERNAL_SERVER_ERROR).send({
127+
error: {
128+
statusCode: 500,
129+
code: "INTERNAL_SERVER_ERROR",
130+
message: error.message || ReasonPhrases.INTERNAL_SERVER_ERROR,
131+
stack: env.NODE_ENV !== "production" ? error.stack : undefined,
132+
},
133+
});
125134
},
126135
);
127136
};

src/server/routes/transaction/retry-failed.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,9 @@ export async function retryFailedTransaction(fastify: FastifyInstance) {
6969
);
7070
}
7171

72-
// temp do not handle userop
7372
if (transaction.isUserOp) {
7473
throw createCustomError(
75-
`Transaction cannot be retried because it is a userop`,
74+
"Transaction cannot be retried because it is a userop",
7675
StatusCodes.BAD_REQUEST,
7776
"TRANSACTION_CANNOT_BE_RETRIED",
7877
);

src/worker/tasks/sendTransactionWorker.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,15 @@ const handler: Processor<string, void, string> = async (job: Job<string>) => {
7878
// For example, the developer retried all failed transactions during an RPC outage.
7979
// An errored queued transaction (resendCount = 0) is safe to retry: the transaction wasn't sent to RPC.
8080
if (transaction.status === "errored" && resendCount === 0) {
81+
const { errorMessage, ...omitted } = transaction;
8182
transaction = {
82-
...{
83-
...transaction,
84-
nonce: undefined,
85-
errorMessage: undefined,
86-
gas: undefined,
87-
gasPrice: undefined,
88-
maxFeePerGas: undefined,
89-
maxPriorityFeePerGas: undefined,
90-
},
83+
...omitted,
9184
status: "queued",
85+
resendCount: 0,
86+
queueId: transaction.queueId,
87+
queuedAt: transaction.queuedAt,
88+
value: transaction.value,
89+
data: transaction.data,
9290
manuallyResentAt: new Date(),
9391
} satisfies QueuedTransaction;
9492
}
@@ -246,11 +244,14 @@ const _sendUserOp = async (
246244
waitForDeployment: false,
247245
})) as UserOperation; // TODO support entrypoint v0.7 accounts
248246
} catch (error) {
249-
return {
247+
const errorMessage = wrapError(error, "Bundler").message;
248+
const erroredTransaction: ErroredTransaction = {
250249
...queuedTransaction,
251250
status: "errored",
252-
errorMessage: wrapError(error, "Bundler").message,
253-
} satisfies ErroredTransaction;
251+
errorMessage,
252+
};
253+
job.log(`Failed to populate transaction: ${errorMessage}`);
254+
return erroredTransaction;
254255
}
255256

256257
job.log(`Populated userOp: ${stringify(signedUserOp)}`);
@@ -322,12 +323,15 @@ const _sendTransaction = async (
322323
maxPriorityFeePerGas: overrides?.maxPriorityFeePerGas,
323324
},
324325
});
325-
} catch (e: unknown) {
326-
return {
326+
} catch (error: unknown) {
327+
const errorMessage = wrapError(error, "RPC").message;
328+
const erroredTransaction: ErroredTransaction = {
327329
...queuedTransaction,
328330
status: "errored",
329-
errorMessage: wrapError(e, "RPC").message,
330-
} satisfies ErroredTransaction;
331+
errorMessage,
332+
};
333+
job.log(`Failed to populate transaction: ${errorMessage}`);
334+
return erroredTransaction;
331335
}
332336

333337
// Handle if `maxFeePerGas` is overridden.

0 commit comments

Comments
 (0)