Skip to content

Commit 230544c

Browse files
authored
fix(ui): refetch missing transactions in cached blocks (#119)
1 parent 0ef607c commit 230544c

File tree

1 file changed

+58
-1
lines changed

1 file changed

+58
-1
lines changed

ui/src/app/api/block/[hash]/route.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ async function fetchBlockFromRpc(
4747
}
4848
}
4949

50+
// On OP Stack, the first transaction (index 0) is the L1 attributes deposit transaction.
51+
// This is not a perfect check (ideally we'd check tx.type === 'deposit' or type 0x7e),
52+
// but sufficient for filtering out system transactions that don't need simulation data.
53+
function isSystemTransaction(tx: BlockTransaction): boolean {
54+
return tx.index === 0;
55+
}
56+
5057
async function enrichTransactionWithBundleData(
5158
txHash: string,
5259
): Promise<{ bundleId: string | null; executionTimeUs: number | null }> {
@@ -78,6 +85,49 @@ async function enrichTransactionWithBundleData(
7885
};
7986
}
8087

88+
async function refetchMissingTransactionSimulations(
89+
block: BlockData,
90+
): Promise<{ updatedBlock: BlockData; hasUpdates: boolean }> {
91+
const transactionsToRefetch = block.transactions.filter(
92+
(tx) => tx.bundleId === null && !isSystemTransaction(tx),
93+
);
94+
95+
if (transactionsToRefetch.length === 0) {
96+
return { updatedBlock: block, hasUpdates: false };
97+
}
98+
99+
const refetchResults = await Promise.all(
100+
transactionsToRefetch.map(async (tx) => {
101+
const { bundleId, executionTimeUs } =
102+
await enrichTransactionWithBundleData(tx.hash);
103+
return { hash: tx.hash, bundleId, executionTimeUs };
104+
}),
105+
);
106+
107+
let hasUpdates = false;
108+
const updatedTransactions = block.transactions.map((tx) => {
109+
const refetchResult = refetchResults.find((r) => r.hash === tx.hash);
110+
if (refetchResult && refetchResult.bundleId !== null) {
111+
hasUpdates = true;
112+
return {
113+
...tx,
114+
bundleId: refetchResult.bundleId,
115+
executionTimeUs: refetchResult.executionTimeUs,
116+
};
117+
}
118+
return tx;
119+
});
120+
121+
return {
122+
updatedBlock: {
123+
...block,
124+
transactions: updatedTransactions,
125+
cachedAt: hasUpdates ? Date.now() : block.cachedAt,
126+
},
127+
hasUpdates,
128+
};
129+
}
130+
81131
export async function GET(
82132
_request: NextRequest,
83133
{ params }: { params: Promise<{ hash: string }> },
@@ -87,7 +137,14 @@ export async function GET(
87137

88138
const cachedBlock = await getBlockFromCache(hash);
89139
if (cachedBlock) {
90-
return NextResponse.json(serializeBlockData(cachedBlock));
140+
const { updatedBlock, hasUpdates } =
141+
await refetchMissingTransactionSimulations(cachedBlock);
142+
143+
if (hasUpdates) {
144+
await cacheBlockData(updatedBlock);
145+
}
146+
147+
return NextResponse.json(serializeBlockData(updatedBlock));
91148
}
92149

93150
const rpcBlock = await fetchBlockFromRpc(hash);

0 commit comments

Comments
 (0)