@@ -131,16 +131,43 @@ function populateSyntheticTransactions(
131131 return [ ...deduplicatedInput , ...syntheticTransactions . values ( ) ] as Transaction [ ] | string [ ] ;
132132}
133133
134+ /**
135+ * Builds Ethereum-style receipt objects.
136+ *
137+ * Groups mirror node logs and contract results by transaction hash, derives a numeric
138+ * transaction index for each transaction, orders them by that index, and then produces
139+ * `IReceiptRootHash` entries with cumulative gas, status, bloom, and logs.
140+ *
141+ * @param txHashes - Transaction hashes for the block.
142+ * @param contractResults - Contract results returned by the mirror node for the block.
143+ * @param logs - Log entries returned by the mirror node for the block.
144+ * @returns An array of receipt objects, sorted by transaction index.
145+ */
134146function buildReceiptRootHashes ( txHashes : string [ ] , contractResults : any [ ] , logs : Log [ ] ) : IReceiptRootHash [ ] {
135147 const items : {
136148 transactionIndex : number ;
137149 logsPerTx : Log [ ] ;
138150 crPerTx : any [ ] ;
139151 } [ ] = [ ] ;
140152
153+ //build lookup maps for logs and contract results by transaction hash to avoid O(n^2) complexity
154+ const logsByTxHash = new Map < string , Log [ ] > ( ) ;
155+ for ( const log of logs ) {
156+ const list = logsByTxHash . get ( log . transactionHash ) ?? [ ] ;
157+ list . push ( log ) ;
158+ logsByTxHash . set ( log . transactionHash , list ) ;
159+ }
160+
161+ const contractResultsByHash = new Map < string , any [ ] > ( ) ;
162+ for ( const cr of contractResults ) {
163+ const list = contractResultsByHash . get ( cr . hash ) ?? [ ] ;
164+ list . push ( cr ) ;
165+ contractResultsByHash . set ( cr . hash , list ) ;
166+ }
167+
141168 for ( const txHash of txHashes ) {
142- const logsPerTx : Log [ ] = logs . filter ( ( log ) => log . transactionHash === txHash ) ;
143- const crPerTx : any [ ] = contractResults . filter ( ( cr ) => cr . hash === txHash ) ;
169+ const logsPerTx : Log [ ] = logsByTxHash . get ( txHash ) ?? [ ] ;
170+ const crPerTx : any [ ] = contractResultsByHash . get ( txHash ) ?? [ ] ;
144171
145172 // Derive numeric transaction index (for ordering)
146173 let txIndexNum : number = 0 ;
@@ -172,7 +199,10 @@ function buildReceiptRootHashes(txHashes: string[], contractResults: any[], logs
172199
173200 receipts . push ( {
174201 transactionIndex : transactionIndexHex ,
175- type : crPerTx . length && crPerTx [ 0 ] . type ? intToHex ( crPerTx [ 0 ] . type ) : null ,
202+ type :
203+ crPerTx . length > 0 && crPerTx [ 0 ] . type !== undefined && crPerTx [ 0 ] . type !== null
204+ ? intToHex ( crPerTx [ 0 ] . type )
205+ : null ,
176206 root : crPerTx . length ? crPerTx [ 0 ] . root : constants . ZERO_HEX_32_BYTE ,
177207 status : crPerTx . length ? crPerTx [ 0 ] . status : constants . ONE_HEX ,
178208 cumulativeGasUsed : intToHex ( cumulativeGas ) ,
0 commit comments