@@ -47,6 +47,61 @@ async function fetchBlockFromRpc(
4747 }
4848}
4949
50+ function isBlockNumber ( identifier : string ) : boolean {
51+ return / ^ \d + $ / . test ( identifier ) ;
52+ }
53+
54+ async function fetchBlockFromRpcByNumber (
55+ blockNumber : string ,
56+ ) : Promise < Block < bigint , true > | null > {
57+ try {
58+ const block = await client . getBlock ( {
59+ blockNumber : BigInt ( blockNumber ) ,
60+ includeTransactions : true ,
61+ } ) ;
62+ return block ;
63+ } catch ( error ) {
64+ console . error ( "Failed to fetch block from RPC by number:" , error ) ;
65+ return null ;
66+ }
67+ }
68+
69+ async function buildAndCacheBlockData (
70+ rpcBlock : Block < bigint , true > ,
71+ hash : Hash ,
72+ number : bigint ,
73+ ) : Promise < BlockData > {
74+ const transactions : BlockTransaction [ ] = await Promise . all (
75+ rpcBlock . transactions . map ( async ( tx , index ) => {
76+ const { bundleId, executionTimeUs } =
77+ await enrichTransactionWithBundleData ( tx . hash ) ;
78+ return {
79+ hash : tx . hash ,
80+ from : tx . from ,
81+ to : tx . to ,
82+ gasUsed : tx . gas ,
83+ executionTimeUs,
84+ bundleId,
85+ index,
86+ } ;
87+ } ) ,
88+ ) ;
89+
90+ const blockData : BlockData = {
91+ hash,
92+ number,
93+ timestamp : rpcBlock . timestamp ,
94+ transactions,
95+ gasUsed : rpcBlock . gasUsed ,
96+ gasLimit : rpcBlock . gasLimit ,
97+ cachedAt : Date . now ( ) ,
98+ } ;
99+
100+ await cacheBlockData ( blockData ) ;
101+
102+ return blockData ;
103+ }
104+
50105// On OP Stack, the first transaction (index 0) is the L1 attributes deposit transaction.
51106// This is not a perfect check (ideally we'd check tx.type === 'deposit' or type 0x7e),
52107// but sufficient for filtering out system transactions that don't need simulation data.
@@ -133,9 +188,35 @@ export async function GET(
133188 { params } : { params : Promise < { hash : string } > } ,
134189) {
135190 try {
136- const { hash } = await params ;
191+ const { hash : identifier } = await params ;
137192
138- const cachedBlock = await getBlockFromCache ( hash ) ;
193+ // If the identifier is a block number, resolve it to a hash first
194+ if ( isBlockNumber ( identifier ) ) {
195+ const rpcBlock = await fetchBlockFromRpcByNumber ( identifier ) ;
196+ if ( ! rpcBlock || ! rpcBlock . hash || ! rpcBlock . number ) {
197+ return NextResponse . json ( { error : "Block not found" } , { status : 404 } ) ;
198+ }
199+
200+ // Check cache by resolved hash
201+ const cachedBlock = await getBlockFromCache ( rpcBlock . hash ) ;
202+ if ( cachedBlock ) {
203+ const { updatedBlock, hasUpdates } =
204+ await refetchMissingTransactionSimulations ( cachedBlock ) ;
205+ if ( hasUpdates ) {
206+ await cacheBlockData ( updatedBlock ) ;
207+ }
208+ return NextResponse . json ( serializeBlockData ( updatedBlock ) ) ;
209+ }
210+
211+ const blockData = await buildAndCacheBlockData (
212+ rpcBlock ,
213+ rpcBlock . hash ,
214+ rpcBlock . number ,
215+ ) ;
216+ return NextResponse . json ( serializeBlockData ( blockData ) ) ;
217+ }
218+
219+ const cachedBlock = await getBlockFromCache ( identifier ) ;
139220 if ( cachedBlock ) {
140221 const { updatedBlock, hasUpdates } =
141222 await refetchMissingTransactionSimulations ( cachedBlock ) ;
@@ -147,39 +228,16 @@ export async function GET(
147228 return NextResponse . json ( serializeBlockData ( updatedBlock ) ) ;
148229 }
149230
150- const rpcBlock = await fetchBlockFromRpc ( hash ) ;
231+ const rpcBlock = await fetchBlockFromRpc ( identifier ) ;
151232 if ( ! rpcBlock || ! rpcBlock . hash || ! rpcBlock . number ) {
152233 return NextResponse . json ( { error : "Block not found" } , { status : 404 } ) ;
153234 }
154235
155- const transactions : BlockTransaction [ ] = await Promise . all (
156- rpcBlock . transactions . map ( async ( tx , index ) => {
157- const { bundleId, executionTimeUs } =
158- await enrichTransactionWithBundleData ( tx . hash ) ;
159- return {
160- hash : tx . hash ,
161- from : tx . from ,
162- to : tx . to ,
163- gasUsed : tx . gas ,
164- executionTimeUs,
165- bundleId,
166- index,
167- } ;
168- } ) ,
236+ const blockData = await buildAndCacheBlockData (
237+ rpcBlock ,
238+ rpcBlock . hash ,
239+ rpcBlock . number ,
169240 ) ;
170-
171- const blockData : BlockData = {
172- hash : rpcBlock . hash ,
173- number : rpcBlock . number ,
174- timestamp : rpcBlock . timestamp ,
175- transactions,
176- gasUsed : rpcBlock . gasUsed ,
177- gasLimit : rpcBlock . gasLimit ,
178- cachedAt : Date . now ( ) ,
179- } ;
180-
181- await cacheBlockData ( blockData ) ;
182-
183241 return NextResponse . json ( serializeBlockData ( blockData ) ) ;
184242 } catch ( error ) {
185243 console . error ( "Error fetching block data:" , error ) ;
0 commit comments