@@ -2,13 +2,85 @@ import { type Static, Type } from "@sinclair/typebox";
22import type { FastifyInstance } from "fastify" ;
33import { StatusCodes } from "http-status-codes" ;
44import { TransactionDB } from "../../../shared/db/transactions/db" ;
5+ import { env } from "../../../shared/utils/env" ;
56import { createCustomError } from "../../middleware/error" ;
67import { standardResponseSchema } from "../../schemas/shared-api-schemas" ;
78import {
89 TransactionSchema ,
910 toTransactionSchema ,
1011} from "../../schemas/transaction" ;
1112
13+ /**
14+ * Creates a minimal transaction response from backfill data.
15+ * Used when the transaction is not found in Redis but exists in the backfill table.
16+ */
17+ const createBackfillResponse = (
18+ queueId : string ,
19+ backfill : { status : "mined" | "errored" ; transactionHash ?: string } ,
20+ ) : Static < typeof TransactionSchema > => {
21+ const baseResponse : Static < typeof TransactionSchema > = {
22+ queueId,
23+ status : backfill . status ,
24+ chainId : null ,
25+ fromAddress : null ,
26+ toAddress : null ,
27+ data : null ,
28+ extension : null ,
29+ value : null ,
30+ nonce : null ,
31+ gasLimit : null ,
32+ gasPrice : null ,
33+ maxFeePerGas : null ,
34+ maxPriorityFeePerGas : null ,
35+ transactionType : null ,
36+ transactionHash : null ,
37+ queuedAt : null ,
38+ sentAt : null ,
39+ minedAt : null ,
40+ cancelledAt : null ,
41+ deployedContractAddress : null ,
42+ deployedContractType : null ,
43+ errorMessage : null ,
44+ sentAtBlockNumber : null ,
45+ blockNumber : null ,
46+ retryCount : 0 ,
47+ retryGasValues : null ,
48+ retryMaxFeePerGas : null ,
49+ retryMaxPriorityFeePerGas : null ,
50+ signerAddress : null ,
51+ accountAddress : null ,
52+ accountSalt : null ,
53+ accountFactoryAddress : null ,
54+ target : null ,
55+ sender : null ,
56+ initCode : null ,
57+ callData : null ,
58+ callGasLimit : null ,
59+ verificationGasLimit : null ,
60+ preVerificationGas : null ,
61+ paymasterAndData : null ,
62+ userOpHash : null ,
63+ functionName : null ,
64+ functionArgs : null ,
65+ onChainTxStatus : null ,
66+ onchainStatus : null ,
67+ effectiveGasPrice : null ,
68+ cumulativeGasUsed : null ,
69+ batchOperations : null ,
70+ } ;
71+
72+ if ( backfill . status === "mined" && backfill . transactionHash ) {
73+ return {
74+ ...baseResponse ,
75+ transactionHash : backfill . transactionHash ,
76+ onchainStatus : "success" ,
77+ onChainTxStatus : 1 ,
78+ } ;
79+ }
80+
81+ return baseResponse ;
82+ } ;
83+
1284// INPUT
1385const requestSchema = Type . Object ( {
1486 queueId : Type . String ( {
@@ -75,6 +147,16 @@ export async function getTransactionStatusRoute(fastify: FastifyInstance) {
75147
76148 const transaction = await TransactionDB . get ( queueId ) ;
77149 if ( ! transaction ) {
150+ // Fallback to backfill table if enabled
151+ if ( env . ENABLE_TX_BACKFILL_FALLBACK ) {
152+ const backfill = await TransactionDB . getBackfill ( queueId ) ;
153+ if ( backfill ) {
154+ return reply . status ( StatusCodes . OK ) . send ( {
155+ result : createBackfillResponse ( queueId , backfill ) ,
156+ } ) ;
157+ }
158+ }
159+
78160 throw createCustomError (
79161 "Transaction not found." ,
80162 StatusCodes . BAD_REQUEST ,
@@ -122,6 +204,16 @@ export async function getTransactionStatusQueryParamRoute(
122204
123205 const transaction = await TransactionDB . get ( queueId ) ;
124206 if ( ! transaction ) {
207+ // Fallback to backfill table if enabled
208+ if ( env . ENABLE_TX_BACKFILL_FALLBACK ) {
209+ const backfill = await TransactionDB . getBackfill ( queueId ) ;
210+ if ( backfill ) {
211+ return reply . status ( StatusCodes . OK ) . send ( {
212+ result : createBackfillResponse ( queueId , backfill ) ,
213+ } ) ;
214+ }
215+ }
216+
125217 throw createCustomError (
126218 "Transaction not found." ,
127219 StatusCodes . BAD_REQUEST ,
0 commit comments