@@ -12,10 +12,13 @@ import { IdentitiesService } from "../identities/identities.service";
1212import { ApiConfigService } from "../../common/api-config/api.config.service" ;
1313import { ConcurrencyUtils } from "src/utils/concurrency.utils" ;
1414import { ApiUtils } from "@multiversx/sdk-nestjs-http" ;
15+ import { OriginLogger } from "@multiversx/sdk-nestjs-common" ;
1516import { GatewayService } from "../../common/gateway/gateway.service" ;
1617
1718@Injectable ( )
1819export class BlockService {
20+ private readonly logger = new OriginLogger ( BlockService . name ) ;
21+
1922 constructor (
2023 private readonly indexerService : IndexerService ,
2124 private readonly cachingService : CacheService ,
@@ -39,6 +42,17 @@ export class BlockService {
3942 async getBlocks ( filter : BlockFilter , queryPagination : QueryPagination , withProposerIdentity ?: boolean ) : Promise < Block [ ] > {
4043 const result = await this . indexerService . getBlocks ( filter , queryPagination ) ;
4144
45+ // If Supernova is enabled for any of these blocks, bulk fetch execution results and merge them
46+ const execMap = await this . fetchExecutionResultsForBlocks ( result as any [ ] ) ;
47+ if ( execMap . size > 0 ) {
48+ for ( const item of result as any [ ] ) {
49+ const er = execMap . get ( item . hash ) ;
50+ if ( er ) {
51+ ApiUtils . mergeObjects ( item , er ) ;
52+ }
53+ }
54+ }
55+
4256 const blocks = await Promise . all ( result . map ( async ( item ) => {
4357 const blockRaw = await this . computeProposerAndValidators ( item ) ;
4458
@@ -58,6 +72,43 @@ export class BlockService {
5872 return blocks ;
5973 }
6074
75+ private async fetchExecutionResultsForBlocks ( items : any [ ] ) : Promise < Map < string , any > > {
76+ const map = new Map < string , any > ( ) ;
77+ if ( ! items || items . length === 0 ) {
78+ return map ;
79+ }
80+
81+ const supernovaEnableEpoch = await this . getSupernovaEnableEpoch ( ) ;
82+ if ( supernovaEnableEpoch === - 1 ) {
83+ return map ;
84+ }
85+
86+ const eligible = items . filter ( ( r : any ) => ( r ?. epoch ?? - 1 ) >= supernovaEnableEpoch ) ;
87+ if ( eligible . length === 0 ) {
88+ return map ;
89+ }
90+
91+ const hashes = eligible . map ( ( r : any ) => r . hash ) . filter ( Boolean ) ;
92+ if ( hashes . length === 0 ) {
93+ return map ;
94+ }
95+
96+ try {
97+ const executionResults = await this . indexerService . getExecutionResultsForHashes ( hashes ) ;
98+ for ( const er of executionResults as any [ ] ) {
99+ if ( er ?. hash ) {
100+ map . set ( er . hash , er ) ;
101+ }
102+ }
103+ this . logger . log ( `Applied executionresults for ${ map . size } blocks out of ${ eligible . length } .` ) ;
104+ } catch {
105+ // Keep endpoint resilient if executionresults index is unavailable
106+ return map ;
107+ }
108+
109+ return map ;
110+ }
111+
61112 private async applyProposerIdentity ( blocks : Block [ ] ) : Promise < void > {
62113 const proposerBlses = blocks . map ( x => x . proposer ) ;
63114
@@ -176,7 +227,7 @@ export class BlockService {
176227
177228 async getSupernovaEnableEpoch ( ) : Promise < number > {
178229 const enableEpochs = await this . getNetworkEnableEpochs ( ) ;
179- return enableEpochs [ "erd_supernova_enable_epoch" ] ?? - 1 ;
230+ return enableEpochs ?. [ "erd_supernova_enable_epoch" ] ?? - 1 ;
180231 }
181232
182233 async getNetworkEnableEpochs ( ) : Promise < Record < string , number > > {
0 commit comments