@subql/node-ethereum 5.4.1-1 → 5.4.1-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/blockchain.service.d.ts +30 -0
  4. package/dist/blockchain.service.js +112 -0
  5. package/dist/blockchain.service.js.map +1 -0
  6. package/dist/{indexer/project.service.test.js → blockchain.service.test.js} +7 -7
  7. package/dist/blockchain.service.test.js.map +1 -0
  8. package/dist/ethereum/api.service.ethereum.d.ts +2 -2
  9. package/dist/ethereum/api.service.ethereum.js +11 -8
  10. package/dist/ethereum/api.service.ethereum.js.map +1 -1
  11. package/dist/ethereum/api.service.ethereum.test.js +10 -2
  12. package/dist/ethereum/api.service.ethereum.test.js.map +1 -1
  13. package/dist/ethereum/ethers/celo/celo-provider.d.ts +18 -18
  14. package/dist/ethereum/ethers/op/op-provider.d.ts +20 -20
  15. package/dist/indexer/dictionary/ethDictionary.service.js +1 -1
  16. package/dist/indexer/dictionary/ethDictionary.service.js.map +1 -1
  17. package/dist/indexer/fetch.module.js +30 -24
  18. package/dist/indexer/fetch.module.js.map +1 -1
  19. package/dist/indexer/indexer.manager.d.ts +3 -5
  20. package/dist/indexer/indexer.manager.js +14 -12
  21. package/dist/indexer/indexer.manager.js.map +1 -1
  22. package/dist/indexer/unfinalizedBlocks.service.d.ts +3 -6
  23. package/dist/indexer/unfinalizedBlocks.service.js +10 -41
  24. package/dist/indexer/unfinalizedBlocks.service.js.map +1 -1
  25. package/dist/indexer/unfinalizedBlocks.service.spec.js +11 -9
  26. package/dist/indexer/unfinalizedBlocks.service.spec.js.map +1 -1
  27. package/dist/indexer/worker/worker-fetch.module.js +7 -18
  28. package/dist/indexer/worker/worker-fetch.module.js.map +1 -1
  29. package/dist/indexer/worker/worker.js.map +1 -1
  30. package/dist/indexer/worker/worker.service.js +1 -0
  31. package/dist/indexer/worker/worker.service.js.map +1 -1
  32. package/dist/init.js +1 -2
  33. package/dist/init.js.map +1 -1
  34. package/dist/subcommands/reindex.module.js +10 -11
  35. package/dist/subcommands/reindex.module.js.map +1 -1
  36. package/dist/subcommands/testing.module.js +14 -31
  37. package/dist/subcommands/testing.module.js.map +1 -1
  38. package/dist/subcommands/testing.service.d.ts +1 -3
  39. package/dist/subcommands/testing.service.js +0 -3
  40. package/dist/subcommands/testing.service.js.map +1 -1
  41. package/package.json +12 -12
  42. package/dist/indexer/blockDispatcher/block-dispatcher.service.d.ts +0 -15
  43. package/dist/indexer/blockDispatcher/block-dispatcher.service.js +0 -51
  44. package/dist/indexer/blockDispatcher/block-dispatcher.service.js.map +0 -1
  45. package/dist/indexer/blockDispatcher/ethereum-block-dispatcher.d.ts +0 -5
  46. package/dist/indexer/blockDispatcher/ethereum-block-dispatcher.js +0 -5
  47. package/dist/indexer/blockDispatcher/ethereum-block-dispatcher.js.map +0 -1
  48. package/dist/indexer/blockDispatcher/index.d.ts +0 -4
  49. package/dist/indexer/blockDispatcher/index.js +0 -10
  50. package/dist/indexer/blockDispatcher/index.js.map +0 -1
  51. package/dist/indexer/blockDispatcher/worker-block-dispatcher.service.d.ts +0 -17
  52. package/dist/indexer/blockDispatcher/worker-block-dispatcher.service.js +0 -48
  53. package/dist/indexer/blockDispatcher/worker-block-dispatcher.service.js.map +0 -1
  54. package/dist/indexer/ds-processor.service.d.ts +0 -5
  55. package/dist/indexer/ds-processor.service.js +0 -22
  56. package/dist/indexer/ds-processor.service.js.map +0 -1
  57. package/dist/indexer/dynamic-ds.service.d.ts +0 -8
  58. package/dist/indexer/dynamic-ds.service.js +0 -69
  59. package/dist/indexer/dynamic-ds.service.js.map +0 -1
  60. package/dist/indexer/fetch.service.d.ts +0 -20
  61. package/dist/indexer/fetch.service.js +0 -74
  62. package/dist/indexer/fetch.service.js.map +0 -1
  63. package/dist/indexer/project.service.d.ts +0 -16
  64. package/dist/indexer/project.service.js +0 -77
  65. package/dist/indexer/project.service.js.map +0 -1
  66. package/dist/indexer/project.service.test.js.map +0 -1
  67. /package/dist/{indexer/project.service.test.d.ts → blockchain.service.test.d.ts} +0 -0
@@ -7,19 +7,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
8
8
  return c > 3 && r && Object.defineProperty(target, key, r), r;
9
9
  };
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
10
13
  Object.defineProperty(exports, "__esModule", { value: true });
11
14
  exports.FetchModule = void 0;
15
+ const node_path_1 = __importDefault(require("node:path"));
12
16
  const common_1 = require("@nestjs/common");
13
17
  const event_emitter_1 = require("@nestjs/event-emitter");
14
18
  const node_core_1 = require("@subql/node-core");
19
+ const blockchain_service_1 = require("../blockchain.service");
15
20
  const api_service_ethereum_1 = require("../ethereum/api.service.ethereum");
16
- const blockDispatcher_1 = require("./blockDispatcher");
17
21
  const ethDictionary_service_1 = require("./dictionary/ethDictionary.service");
18
- const ds_processor_service_1 = require("./ds-processor.service");
19
- const dynamic_ds_service_1 = require("./dynamic-ds.service");
20
- const fetch_service_1 = require("./fetch.service");
21
22
  const indexer_manager_1 = require("./indexer.manager");
22
- const project_service_1 = require("./project.service");
23
23
  const unfinalizedBlocks_service_1 = require("./unfinalizedBlocks.service");
24
24
  let FetchModule = class FetchModule {
25
25
  };
@@ -29,12 +29,8 @@ exports.FetchModule = FetchModule = __decorate([
29
29
  imports: [node_core_1.CoreModule],
30
30
  providers: [
31
31
  {
32
- provide: node_core_1.ApiService,
33
- useFactory: async (project, connectionPoolService, eventEmitter, nodeConfig) => {
34
- const apiService = new api_service_ethereum_1.EthereumApiService(project, connectionPoolService, eventEmitter, nodeConfig);
35
- await apiService.init();
36
- return apiService;
37
- },
32
+ provide: 'APIService',
33
+ useFactory: api_service_ethereum_1.EthereumApiService.init,
38
34
  inject: [
39
35
  'ISubqueryProject',
40
36
  node_core_1.ConnectionPoolService,
@@ -42,39 +38,49 @@ exports.FetchModule = FetchModule = __decorate([
42
38
  node_core_1.NodeConfig,
43
39
  ],
44
40
  },
41
+ {
42
+ provide: 'IBlockchainService',
43
+ useClass: blockchain_service_1.BlockchainService,
44
+ },
45
45
  indexer_manager_1.IndexerManager,
46
46
  {
47
47
  provide: 'IBlockDispatcher',
48
- useFactory: (nodeConfig, eventEmitter, projectService, projectUpgradeService, apiService, indexerManager, cacheService, storeService, storeModelProvider, poiSyncService, project, dynamicDsService, unfinalizedBlocks, connectionPoolState, monitorService) => nodeConfig.workers
49
- ? new blockDispatcher_1.WorkerBlockDispatcherService(nodeConfig, eventEmitter, projectService, projectUpgradeService, cacheService, storeService, storeModelProvider, poiSyncService, project, dynamicDsService, unfinalizedBlocks, connectionPoolState, monitorService)
50
- : new blockDispatcher_1.BlockDispatcherService(apiService, nodeConfig, indexerManager, eventEmitter, projectService, projectUpgradeService, storeService, storeModelProvider, poiSyncService, project),
48
+ useFactory: (nodeConfig, eventEmitter, projectService, projectUpgradeService, cacheService, storeService, storeModelProvider, poiSyncService, project, dynamicDsService, unfinalizedBlocks, connectionPoolState, blockchainService, indexerManager, monitorService) => nodeConfig.workers
49
+ ? new node_core_1.WorkerBlockDispatcher(nodeConfig, eventEmitter, projectService, projectUpgradeService, storeService, storeModelProvider, cacheService, poiSyncService, dynamicDsService, unfinalizedBlocks, connectionPoolState, project, blockchainService, node_path_1.default.resolve(__dirname, '../../dist/indexer/worker/worker.js'), [], monitorService)
50
+ : new node_core_1.BlockDispatcher(nodeConfig, eventEmitter, projectService, projectUpgradeService, storeService, storeModelProvider, poiSyncService, project, blockchainService, indexerManager),
51
51
  inject: [
52
52
  node_core_1.NodeConfig,
53
53
  event_emitter_1.EventEmitter2,
54
54
  'IProjectService',
55
55
  'IProjectUpgradeService',
56
- node_core_1.ApiService,
57
- indexer_manager_1.IndexerManager,
58
56
  node_core_1.InMemoryCacheService,
59
57
  node_core_1.StoreService,
60
58
  'IStoreModelProvider',
61
59
  node_core_1.PoiSyncService,
62
60
  'ISubqueryProject',
63
- dynamic_ds_service_1.DynamicDsService,
64
- unfinalizedBlocks_service_1.UnfinalizedBlocksService,
61
+ node_core_1.DynamicDsService,
62
+ 'IUnfinalizedBlocksService',
65
63
  node_core_1.ConnectionPoolStateManager,
64
+ 'IBlockchainService',
65
+ indexer_manager_1.IndexerManager,
66
66
  node_core_1.MonitorService,
67
67
  ],
68
68
  },
69
- fetch_service_1.FetchService,
70
- ethDictionary_service_1.EthDictionaryService,
71
- ds_processor_service_1.DsProcessorService,
72
- dynamic_ds_service_1.DynamicDsService,
69
+ node_core_1.FetchService,
73
70
  {
74
- useClass: project_service_1.ProjectService,
71
+ provide: node_core_1.DictionaryService,
72
+ useClass: ethDictionary_service_1.EthDictionaryService,
73
+ },
74
+ node_core_1.DsProcessorService,
75
+ node_core_1.DynamicDsService,
76
+ {
77
+ useClass: node_core_1.ProjectService,
75
78
  provide: 'IProjectService',
76
79
  },
77
- unfinalizedBlocks_service_1.UnfinalizedBlocksService,
80
+ {
81
+ provide: 'IUnfinalizedBlocksService',
82
+ useClass: unfinalizedBlocks_service_1.UnfinalizedBlocksService,
83
+ },
78
84
  ],
79
85
  })
80
86
  ], FetchModule);
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.module.js","sourceRoot":"","sources":["../../src/indexer/fetch.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAAsD;AACtD,gDAY0B;AAG1B,2EAAsE;AACtE,uDAG2B;AAC3B,8EAA0E;AAC1E,iEAA4D;AAC5D,6DAAwD;AACxD,mDAA+C;AAC/C,uDAAmD;AACnD,uDAAmD;AACnD,2EAAuE;AA0GhE,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAxGvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,sBAAU,CAAC;QACrB,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,KAAK,EACf,OAAwB,EACxB,qBAAmE,EACnE,YAA2B,EAC3B,UAAsB,EACtB,EAAE;oBACF,MAAM,UAAU,GAAG,IAAI,yCAAkB,CACvC,OAAO,EACP,qBAAqB,EACrB,YAAY,EACZ,UAAU,CACX,CAAC;oBACF,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;oBACxB,OAAO,UAAU,CAAC;gBACpB,CAAC;gBACD,MAAM,EAAE;oBACN,kBAAkB;oBAClB,iCAAqB;oBACrB,6BAAa;oBACb,sBAAU;iBACX;aACF;YACD,gCAAc;YACd;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,UAAU,EAAE,CACV,UAAsB,EACtB,YAA2B,EAC3B,cAA8B,EAC9B,qBAA6C,EAC7C,UAA8B,EAC9B,cAA8B,EAC9B,YAAkC,EAClC,YAA0B,EAC1B,kBAAuC,EACvC,cAA8B,EAC9B,OAAwB,EACxB,gBAAkC,EAClC,iBAA2C,EAC3C,mBAAsE,EACtE,cAA+B,EAC/B,EAAE,CACF,UAAU,CAAC,OAAO;oBAChB,CAAC,CAAC,IAAI,8CAA4B,CAC9B,UAAU,EACV,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,CACf;oBACH,CAAC,CAAC,IAAI,wCAAsB,CACxB,UAAU,EACV,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,OAAO,CACR;gBACP,MAAM,EAAE;oBACN,sBAAU;oBACV,6BAAa;oBACb,iBAAiB;oBACjB,wBAAwB;oBACxB,sBAAU;oBACV,gCAAc;oBACd,gCAAoB;oBACpB,wBAAY;oBACZ,qBAAqB;oBACrB,0BAAc;oBACd,kBAAkB;oBAClB,qCAAgB;oBAChB,oDAAwB;oBACxB,sCAA0B;oBAC1B,0BAAc;iBACf;aACF;YACD,4BAAY;YACZ,4CAAoB;YACpB,yCAAkB;YAClB,qCAAgB;YAChB;gBACE,QAAQ,EAAE,gCAAc;gBACxB,OAAO,EAAE,iBAAiB;aAC3B;YACD,oDAAwB;SACzB;KACF,CAAC;GACW,WAAW,CAAG","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport {\n StoreService,\n ApiService,\n NodeConfig,\n ConnectionPoolService,\n ConnectionPoolStateManager,\n IProjectUpgradeService,\n PoiSyncService,\n InMemoryCacheService,\n MonitorService,\n CoreModule,\n IStoreModelProvider,\n} from '@subql/node-core';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApiConnection } from '../ethereum/api.connection';\nimport { EthereumApiService } from '../ethereum/api.service.ethereum';\nimport {\n BlockDispatcherService,\n WorkerBlockDispatcherService,\n} from './blockDispatcher';\nimport { EthDictionaryService } from './dictionary/ethDictionary.service';\nimport { DsProcessorService } from './ds-processor.service';\nimport { DynamicDsService } from './dynamic-ds.service';\nimport { FetchService } from './fetch.service';\nimport { IndexerManager } from './indexer.manager';\nimport { ProjectService } from './project.service';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\n@Module({\n imports: [CoreModule],\n providers: [\n {\n provide: ApiService,\n useFactory: async (\n project: SubqueryProject,\n connectionPoolService: ConnectionPoolService<EthereumApiConnection>,\n eventEmitter: EventEmitter2,\n nodeConfig: NodeConfig,\n ) => {\n const apiService = new EthereumApiService(\n project,\n connectionPoolService,\n eventEmitter,\n nodeConfig,\n );\n await apiService.init();\n return apiService;\n },\n inject: [\n 'ISubqueryProject',\n ConnectionPoolService,\n EventEmitter2,\n NodeConfig,\n ],\n },\n IndexerManager,\n {\n provide: 'IBlockDispatcher',\n useFactory: (\n nodeConfig: NodeConfig,\n eventEmitter: EventEmitter2,\n projectService: ProjectService,\n projectUpgradeService: IProjectUpgradeService,\n apiService: EthereumApiService,\n indexerManager: IndexerManager,\n cacheService: InMemoryCacheService,\n storeService: StoreService,\n storeModelProvider: IStoreModelProvider,\n poiSyncService: PoiSyncService,\n project: SubqueryProject,\n dynamicDsService: DynamicDsService,\n unfinalizedBlocks: UnfinalizedBlocksService,\n connectionPoolState: ConnectionPoolStateManager<EthereumApiConnection>,\n monitorService?: MonitorService,\n ) =>\n nodeConfig.workers\n ? new WorkerBlockDispatcherService(\n nodeConfig,\n eventEmitter,\n projectService,\n projectUpgradeService,\n cacheService,\n storeService,\n storeModelProvider,\n poiSyncService,\n project,\n dynamicDsService,\n unfinalizedBlocks,\n connectionPoolState,\n monitorService,\n )\n : new BlockDispatcherService(\n apiService,\n nodeConfig,\n indexerManager,\n eventEmitter,\n projectService,\n projectUpgradeService,\n storeService,\n storeModelProvider,\n poiSyncService,\n project,\n ),\n inject: [\n NodeConfig,\n EventEmitter2,\n 'IProjectService',\n 'IProjectUpgradeService',\n ApiService,\n IndexerManager,\n InMemoryCacheService,\n StoreService,\n 'IStoreModelProvider',\n PoiSyncService,\n 'ISubqueryProject',\n DynamicDsService,\n UnfinalizedBlocksService,\n ConnectionPoolStateManager,\n MonitorService,\n ],\n },\n FetchService,\n EthDictionaryService,\n DsProcessorService,\n DynamicDsService,\n {\n useClass: ProjectService,\n provide: 'IProjectService',\n },\n UnfinalizedBlocksService,\n ],\n})\nexport class FetchModule {}\n"]}
1
+ {"version":3,"file":"fetch.module.js","sourceRoot":"","sources":["../../src/indexer/fetch.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;;;;AAEnC,0DAA6B;AAC7B,2CAAwC;AACxC,yDAAsD;AAEtD,gDAkB0B;AAC1B,8DAA0D;AAG1D,2EAAsE;AACtE,8EAA0E;AAC1E,uDAAmD;AACnD,2EAAuE;AAyGhE,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAvGvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,sBAAU,CAAC;QACrB,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,YAAY;gBACrB,UAAU,EAAE,yCAAkB,CAAC,IAAI;gBACnC,MAAM,EAAE;oBACN,kBAAkB;oBAClB,iCAAqB;oBACrB,6BAAa;oBACb,sBAAU;iBACX;aACF;YACD;gBACE,OAAO,EAAE,oBAAoB;gBAC7B,QAAQ,EAAE,sCAAiB;aAC5B;YACD,gCAAc;YACd;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,UAAU,EAAE,CACV,UAAsB,EACtB,YAA2B,EAC3B,cAAuD,EACvD,qBAA6C,EAC7C,YAAkC,EAClC,YAA0B,EAC1B,kBAAuC,EACvC,cAA8B,EAC9B,OAAwB,EACxB,gBAA2D,EAC3D,iBAA2C,EAC3C,mBAAsE,EACtE,iBAAoC,EACpC,cAA8B,EAC9B,cAA+B,EAC/B,EAAE,CACF,UAAU,CAAC,OAAO;oBAChB,CAAC,CAAC,IAAI,iCAAqB,CACvB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,OAAO,EACP,iBAAiB,EACjB,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,qCAAqC,CAAC,EAC9D,EAAE,EACF,cAAc,CACf;oBACH,CAAC,CAAC,IAAI,2BAAe,CACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,iBAAiB,EACjB,cAAc,CACf;gBACP,MAAM,EAAE;oBACN,sBAAU;oBACV,6BAAa;oBACb,iBAAiB;oBACjB,wBAAwB;oBACxB,gCAAoB;oBACpB,wBAAY;oBACZ,qBAAqB;oBACrB,0BAAc;oBACd,kBAAkB;oBAClB,4BAAgB;oBAChB,2BAA2B;oBAC3B,sCAA0B;oBAC1B,oBAAoB;oBACpB,gCAAc;oBACd,0BAAc;iBACf;aACF;YACD,wBAAY;YACZ;gBACE,OAAO,EAAE,6BAAiB;gBAC1B,QAAQ,EAAE,4CAAoB;aAC/B;YACD,8BAAkB;YAClB,4BAAgB;YAChB;gBACE,QAAQ,EAAE,0BAAc;gBACxB,OAAO,EAAE,iBAAiB;aAC3B;YACD;gBACE,OAAO,EAAE,2BAA2B;gBACpC,QAAQ,EAAE,oDAAwB;aACnC;SACF;KACF,CAAC;GACW,WAAW,CAAG","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport path from 'node:path';\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { SubqlEthereumDataSource } from '@subql/common-ethereum';\nimport {\n StoreService,\n NodeConfig,\n ConnectionPoolService,\n ConnectionPoolStateManager,\n IProjectUpgradeService,\n PoiSyncService,\n InMemoryCacheService,\n MonitorService,\n CoreModule,\n IStoreModelProvider,\n ProjectService,\n DynamicDsService,\n WorkerBlockDispatcher,\n BlockDispatcher,\n DsProcessorService,\n FetchService,\n DictionaryService,\n} from '@subql/node-core';\nimport { BlockchainService } from '../blockchain.service';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApiConnection } from '../ethereum/api.connection';\nimport { EthereumApiService } from '../ethereum/api.service.ethereum';\nimport { EthDictionaryService } from './dictionary/ethDictionary.service';\nimport { IndexerManager } from './indexer.manager';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\n@Module({\n imports: [CoreModule],\n providers: [\n {\n provide: 'APIService',\n useFactory: EthereumApiService.init,\n inject: [\n 'ISubqueryProject',\n ConnectionPoolService,\n EventEmitter2,\n NodeConfig,\n ],\n },\n {\n provide: 'IBlockchainService',\n useClass: BlockchainService,\n },\n IndexerManager,\n {\n provide: 'IBlockDispatcher',\n useFactory: (\n nodeConfig: NodeConfig,\n eventEmitter: EventEmitter2,\n projectService: ProjectService<SubqlEthereumDataSource>,\n projectUpgradeService: IProjectUpgradeService,\n cacheService: InMemoryCacheService,\n storeService: StoreService,\n storeModelProvider: IStoreModelProvider,\n poiSyncService: PoiSyncService,\n project: SubqueryProject,\n dynamicDsService: DynamicDsService<SubqlEthereumDataSource>,\n unfinalizedBlocks: UnfinalizedBlocksService,\n connectionPoolState: ConnectionPoolStateManager<EthereumApiConnection>,\n blockchainService: BlockchainService,\n indexerManager: IndexerManager,\n monitorService?: MonitorService,\n ) =>\n nodeConfig.workers\n ? new WorkerBlockDispatcher(\n nodeConfig,\n eventEmitter,\n projectService,\n projectUpgradeService,\n storeService,\n storeModelProvider,\n cacheService,\n poiSyncService,\n dynamicDsService,\n unfinalizedBlocks,\n connectionPoolState,\n project,\n blockchainService,\n path.resolve(__dirname, '../../dist/indexer/worker/worker.js'),\n [],\n monitorService,\n )\n : new BlockDispatcher(\n nodeConfig,\n eventEmitter,\n projectService,\n projectUpgradeService,\n storeService,\n storeModelProvider,\n poiSyncService,\n project,\n blockchainService,\n indexerManager,\n ),\n inject: [\n NodeConfig,\n EventEmitter2,\n 'IProjectService',\n 'IProjectUpgradeService',\n InMemoryCacheService,\n StoreService,\n 'IStoreModelProvider',\n PoiSyncService,\n 'ISubqueryProject',\n DynamicDsService,\n 'IUnfinalizedBlocksService',\n ConnectionPoolStateManager,\n 'IBlockchainService',\n IndexerManager,\n MonitorService,\n ],\n },\n FetchService,\n {\n provide: DictionaryService,\n useClass: EthDictionaryService,\n },\n DsProcessorService,\n DynamicDsService,\n {\n useClass: ProjectService,\n provide: 'IProjectService',\n },\n {\n provide: 'IUnfinalizedBlocksService',\n useClass: UnfinalizedBlocksService,\n },\n ],\n})\nexport class FetchModule {}\n"]}
@@ -1,19 +1,17 @@
1
1
  import { isBlockHandlerProcessor, isCallHandlerProcessor, isEventHandlerProcessor, isCustomDs, isRuntimeDs, SubqlEthereumCustomDataSource, EthereumHandlerKind, EthereumRuntimeHandlerInputMap, SubqlEthereumDataSource } from '@subql/common-ethereum';
2
- import { ApiService, NodeConfig, IndexerSandbox, ProcessBlockResponse, BaseIndexerManager, IBlock, SandboxService } from '@subql/node-core';
2
+ import { ApiService, NodeConfig, IndexerSandbox, ProcessBlockResponse, BaseIndexerManager, IBlock, SandboxService, DsProcessorService, DynamicDsService } from '@subql/node-core';
3
3
  import { EthereumTransaction, EthereumLog, EthereumBlock, SubqlRuntimeDatasource, EthereumBlockFilter, EthereumLogFilter, EthereumTransactionFilter, LightEthereumLog } from '@subql/types-ethereum';
4
+ import { BlockchainService } from '../blockchain.service';
4
5
  import { EthereumProjectDs } from '../configure/SubqueryProject';
5
6
  import { EthereumApi } from '../ethereum';
6
7
  import SafeEthProvider from '../ethereum/safe-api';
7
- import { DsProcessorService } from './ds-processor.service';
8
- import { DynamicDsService } from './dynamic-ds.service';
9
8
  import { BlockContent } from './types';
10
9
  import { UnfinalizedBlocksService } from './unfinalizedBlocks.service';
11
10
  export declare class IndexerManager extends BaseIndexerManager<EthereumApi, SafeEthProvider, BlockContent, ApiService, SubqlEthereumDataSource, SubqlEthereumCustomDataSource, typeof FilterTypeMap, typeof ProcessorTypeMap, EthereumRuntimeHandlerInputMap> {
12
11
  protected isRuntimeDs: typeof isRuntimeDs;
13
12
  protected isCustomDs: typeof isCustomDs;
14
- constructor(apiService: ApiService, nodeConfig: NodeConfig, sandboxService: SandboxService<SafeEthProvider, EthereumApi>, dsProcessorService: DsProcessorService, dynamicDsService: DynamicDsService, unfinalizedBlocksService: UnfinalizedBlocksService);
13
+ constructor(apiService: ApiService, nodeConfig: NodeConfig, sandboxService: SandboxService<SafeEthProvider, EthereumApi>, dsProcessorService: DsProcessorService<SubqlEthereumDataSource, SubqlEthereumCustomDataSource>, dynamicDsService: DynamicDsService<SubqlEthereumDataSource>, unfinalizedBlocksService: UnfinalizedBlocksService, blockchainService: BlockchainService);
15
14
  indexBlock(block: IBlock<BlockContent>, dataSources: SubqlEthereumDataSource[]): Promise<ProcessBlockResponse>;
16
- private getApi;
17
15
  protected getDsProcessor(ds: SubqlEthereumDataSource, safeApi: SafeEthProvider): IndexerSandbox;
18
16
  protected indexBlockData(block: BlockContent, dataSources: EthereumProjectDs[], getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>): Promise<void>;
19
17
  private indexBlockContent;
@@ -10,27 +10,25 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
10
10
  var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
12
12
  };
13
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
14
+ return function (target, key) { decorator(target, key, paramIndex); }
15
+ };
13
16
  Object.defineProperty(exports, "__esModule", { value: true });
14
17
  exports.IndexerManager = void 0;
15
18
  const common_1 = require("@nestjs/common");
16
19
  const common_ethereum_1 = require("@subql/common-ethereum");
17
20
  const node_core_1 = require("@subql/node-core");
21
+ const blockchain_service_1 = require("../blockchain.service");
18
22
  const block_ethereum_1 = require("../ethereum/block.ethereum");
19
- const ds_processor_service_1 = require("./ds-processor.service");
20
- const dynamic_ds_service_1 = require("./dynamic-ds.service");
21
23
  const unfinalizedBlocks_service_1 = require("./unfinalizedBlocks.service");
22
24
  let IndexerManager = class IndexerManager extends node_core_1.BaseIndexerManager {
23
25
  isRuntimeDs = common_ethereum_1.isRuntimeDs;
24
26
  isCustomDs = common_ethereum_1.isCustomDs;
25
- constructor(apiService, nodeConfig, sandboxService, dsProcessorService, dynamicDsService, unfinalizedBlocksService) {
26
- super(apiService, nodeConfig, sandboxService, dsProcessorService, dynamicDsService, unfinalizedBlocksService, FilterTypeMap, ProcessorTypeMap);
27
+ constructor(apiService, nodeConfig, sandboxService, dsProcessorService, dynamicDsService, unfinalizedBlocksService, blockchainService) {
28
+ super(apiService, nodeConfig, sandboxService, dsProcessorService, dynamicDsService, unfinalizedBlocksService, FilterTypeMap, ProcessorTypeMap, blockchainService);
27
29
  }
28
30
  async indexBlock(block, dataSources) {
29
- return super.internalIndexBlock(block, dataSources, () => this.getApi(block.block));
30
- }
31
- // eslint-disable-next-line @typescript-eslint/require-await
32
- async getApi(block) {
33
- return this.apiService.safeApi(block.number);
31
+ return super.internalIndexBlock(block, dataSources, () => this.blockchainService.getSafeApi(block.block));
34
32
  }
35
33
  getDsProcessor(ds, safeApi) {
36
34
  return this.sandboxService.getDsProcessor(ds, safeApi, this.apiService.unsafeApi.api);
@@ -80,12 +78,16 @@ __decorate([
80
78
  ], IndexerManager.prototype, "indexBlock", null);
81
79
  exports.IndexerManager = IndexerManager = __decorate([
82
80
  (0, common_1.Injectable)(),
81
+ __param(0, (0, common_1.Inject)('APIService')),
82
+ __param(5, (0, common_1.Inject)('IUnfinalizedBlocksService')),
83
+ __param(6, (0, common_1.Inject)('IBlockchainService')),
83
84
  __metadata("design:paramtypes", [node_core_1.ApiService,
84
85
  node_core_1.NodeConfig,
85
86
  node_core_1.SandboxService,
86
- ds_processor_service_1.DsProcessorService,
87
- dynamic_ds_service_1.DynamicDsService,
88
- unfinalizedBlocks_service_1.UnfinalizedBlocksService])
87
+ node_core_1.DsProcessorService,
88
+ node_core_1.DynamicDsService,
89
+ unfinalizedBlocks_service_1.UnfinalizedBlocksService,
90
+ blockchain_service_1.BlockchainService])
89
91
  ], IndexerManager);
90
92
  const ProcessorTypeMap = {
91
93
  [common_ethereum_1.EthereumHandlerKind.Block]: common_ethereum_1.isBlockHandlerProcessor,
@@ -1 +1 @@
1
- {"version":3,"file":"indexer.manager.js","sourceRoot":"","sources":["../../src/indexer/indexer.manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Injectable } from '@nestjs/common';\nimport {\n isBlockHandlerProcessor,\n isCallHandlerProcessor,\n isEventHandlerProcessor,\n isCustomDs,\n isRuntimeDs,\n SubqlEthereumCustomDataSource,\n EthereumHandlerKind,\n EthereumRuntimeHandlerInputMap,\n SubqlEthereumDataSource,\n} from '@subql/common-ethereum';\nimport {\n ApiService,\n NodeConfig,\n profiler,\n IndexerSandbox,\n ProcessBlockResponse,\n BaseIndexerManager,\n IBlock,\n SandboxService,\n} from '@subql/node-core';\nimport {\n EthereumTransaction,\n EthereumLog,\n EthereumBlock,\n SubqlRuntimeDatasource,\n EthereumBlockFilter,\n EthereumLogFilter,\n EthereumTransactionFilter,\n LightEthereumLog,\n} from '@subql/types-ethereum';\nimport { EthereumProjectDs } from '../configure/SubqueryProject';\nimport { EthereumApi } from '../ethereum';\nimport {\n filterBlocksProcessor,\n filterLogsProcessor,\n filterTransactionsProcessor,\n isFullBlock,\n} from '../ethereum/block.ethereum';\nimport SafeEthProvider from '../ethereum/safe-api';\nimport { DsProcessorService } from './ds-processor.service';\nimport { DynamicDsService } from './dynamic-ds.service';\nimport { BlockContent } from './types';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\n@Injectable()\nexport class IndexerManager extends BaseIndexerManager<\n EthereumApi,\n SafeEthProvider,\n BlockContent,\n ApiService,\n SubqlEthereumDataSource,\n SubqlEthereumCustomDataSource,\n typeof FilterTypeMap,\n typeof ProcessorTypeMap,\n EthereumRuntimeHandlerInputMap\n> {\n protected isRuntimeDs = isRuntimeDs;\n protected isCustomDs = isCustomDs;\n\n constructor(\n apiService: ApiService,\n nodeConfig: NodeConfig,\n sandboxService: SandboxService<SafeEthProvider, EthereumApi>,\n dsProcessorService: DsProcessorService,\n dynamicDsService: DynamicDsService,\n unfinalizedBlocksService: UnfinalizedBlocksService,\n ) {\n super(\n apiService,\n nodeConfig,\n sandboxService,\n dsProcessorService,\n dynamicDsService,\n unfinalizedBlocksService,\n FilterTypeMap,\n ProcessorTypeMap,\n );\n }\n\n @profiler()\n async indexBlock(\n block: IBlock<BlockContent>,\n dataSources: SubqlEthereumDataSource[],\n ): Promise<ProcessBlockResponse> {\n return super.internalIndexBlock(block, dataSources, () =>\n this.getApi(block.block),\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n private async getApi(block: BlockContent): Promise<SafeEthProvider> {\n return this.apiService.safeApi(block.number);\n }\n\n protected getDsProcessor(\n ds: SubqlEthereumDataSource,\n safeApi: SafeEthProvider,\n ): IndexerSandbox {\n return this.sandboxService.getDsProcessor(\n ds,\n safeApi,\n this.apiService.unsafeApi.api,\n );\n }\n\n protected async indexBlockData(\n block: BlockContent,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n if (isFullBlock(block)) {\n await this.indexBlockContent(block, dataSources, getVM);\n\n for (const tx of block.transactions) {\n await this.indexTransaction(tx, dataSources, getVM);\n\n for (const log of tx.logs ?? []) {\n await this.indexEvent(log, dataSources, getVM);\n }\n }\n } else {\n for (const log of block.logs ?? []) {\n await this.indexEvent(log, dataSources, getVM);\n }\n }\n }\n\n private async indexBlockContent(\n block: EthereumBlock,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n for (const ds of dataSources) {\n await this.indexData(EthereumHandlerKind.Block, block, ds, getVM);\n }\n }\n\n private async indexTransaction(\n tx: EthereumTransaction,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n for (const ds of dataSources) {\n await this.indexData(EthereumHandlerKind.Call, tx, ds, getVM);\n }\n }\n\n private async indexEvent(\n log: EthereumLog | LightEthereumLog,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n for (const ds of dataSources) {\n await this.indexData(EthereumHandlerKind.Event, log, ds, getVM);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n protected async prepareFilteredData(\n kind: EthereumHandlerKind,\n data: any,\n ds: SubqlRuntimeDatasource,\n ): Promise<any> {\n return DataAbiParser[kind](this.apiService.api)(data, ds);\n }\n}\n\nconst ProcessorTypeMap = {\n [EthereumHandlerKind.Block]: isBlockHandlerProcessor,\n [EthereumHandlerKind.Event]: isEventHandlerProcessor,\n [EthereumHandlerKind.Call]: isCallHandlerProcessor,\n};\n\nconst FilterTypeMap = {\n [EthereumHandlerKind.Block]: (\n data: EthereumBlock,\n filter: EthereumBlockFilter,\n ds: SubqlEthereumDataSource,\n ) => filterBlocksProcessor(data, filter, ds.options?.address),\n [EthereumHandlerKind.Event]: (\n data: EthereumLog | LightEthereumLog,\n filter: EthereumLogFilter,\n ds: SubqlEthereumDataSource,\n ) => filterLogsProcessor(data, filter, ds.options?.address),\n [EthereumHandlerKind.Call]: (\n data: EthereumTransaction,\n filter: EthereumTransactionFilter,\n ds: SubqlEthereumDataSource,\n ) => filterTransactionsProcessor(data, filter, ds.options?.address),\n};\n\nconst DataAbiParser = {\n [EthereumHandlerKind.Block]: () => (data: EthereumBlock) => data,\n [EthereumHandlerKind.Event]:\n (api: EthereumApi) =>\n (data: EthereumLog | LightEthereumLog, ds: SubqlRuntimeDatasource) =>\n api.parseLog(data, ds),\n [EthereumHandlerKind.Call]:\n (api: EthereumApi) =>\n (data: EthereumTransaction, ds: SubqlRuntimeDatasource) =>\n api.parseTransaction(data, ds),\n};\n"]}
1
+ {"version":3,"file":"indexer.manager.js","sourceRoot":"","sources":["../../src/indexer/indexer.manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport {\n isBlockHandlerProcessor,\n isCallHandlerProcessor,\n isEventHandlerProcessor,\n isCustomDs,\n isRuntimeDs,\n SubqlEthereumCustomDataSource,\n EthereumHandlerKind,\n EthereumRuntimeHandlerInputMap,\n SubqlEthereumDataSource,\n} from '@subql/common-ethereum';\nimport {\n ApiService,\n NodeConfig,\n profiler,\n IndexerSandbox,\n ProcessBlockResponse,\n BaseIndexerManager,\n IBlock,\n SandboxService,\n DsProcessorService,\n DynamicDsService,\n} from '@subql/node-core';\nimport {\n EthereumTransaction,\n EthereumLog,\n EthereumBlock,\n SubqlRuntimeDatasource,\n EthereumBlockFilter,\n EthereumLogFilter,\n EthereumTransactionFilter,\n LightEthereumLog,\n} from '@subql/types-ethereum';\nimport { BlockchainService } from '../blockchain.service';\nimport { EthereumProjectDs } from '../configure/SubqueryProject';\nimport { EthereumApi } from '../ethereum';\nimport {\n filterBlocksProcessor,\n filterLogsProcessor,\n filterTransactionsProcessor,\n isFullBlock,\n} from '../ethereum/block.ethereum';\nimport SafeEthProvider from '../ethereum/safe-api';\nimport { BlockContent } from './types';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\n@Injectable()\nexport class IndexerManager extends BaseIndexerManager<\n EthereumApi,\n SafeEthProvider,\n BlockContent,\n ApiService,\n SubqlEthereumDataSource,\n SubqlEthereumCustomDataSource,\n typeof FilterTypeMap,\n typeof ProcessorTypeMap,\n EthereumRuntimeHandlerInputMap\n> {\n protected isRuntimeDs = isRuntimeDs;\n protected isCustomDs = isCustomDs;\n\n constructor(\n @Inject('APIService') apiService: ApiService,\n nodeConfig: NodeConfig,\n sandboxService: SandboxService<SafeEthProvider, EthereumApi>,\n dsProcessorService: DsProcessorService<\n SubqlEthereumDataSource,\n SubqlEthereumCustomDataSource\n >,\n dynamicDsService: DynamicDsService<SubqlEthereumDataSource>,\n @Inject('IUnfinalizedBlocksService')\n unfinalizedBlocksService: UnfinalizedBlocksService,\n @Inject('IBlockchainService') blockchainService: BlockchainService,\n ) {\n super(\n apiService,\n nodeConfig,\n sandboxService,\n dsProcessorService,\n dynamicDsService,\n unfinalizedBlocksService,\n FilterTypeMap,\n ProcessorTypeMap,\n blockchainService,\n );\n }\n\n @profiler()\n async indexBlock(\n block: IBlock<BlockContent>,\n dataSources: SubqlEthereumDataSource[],\n ): Promise<ProcessBlockResponse> {\n return super.internalIndexBlock(block, dataSources, () =>\n this.blockchainService.getSafeApi(block.block),\n );\n }\n\n protected getDsProcessor(\n ds: SubqlEthereumDataSource,\n safeApi: SafeEthProvider,\n ): IndexerSandbox {\n return this.sandboxService.getDsProcessor(\n ds,\n safeApi,\n this.apiService.unsafeApi.api,\n );\n }\n\n protected async indexBlockData(\n block: BlockContent,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n if (isFullBlock(block)) {\n await this.indexBlockContent(block, dataSources, getVM);\n\n for (const tx of block.transactions) {\n await this.indexTransaction(tx, dataSources, getVM);\n\n for (const log of tx.logs ?? []) {\n await this.indexEvent(log, dataSources, getVM);\n }\n }\n } else {\n for (const log of block.logs ?? []) {\n await this.indexEvent(log, dataSources, getVM);\n }\n }\n }\n\n private async indexBlockContent(\n block: EthereumBlock,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n for (const ds of dataSources) {\n await this.indexData(EthereumHandlerKind.Block, block, ds, getVM);\n }\n }\n\n private async indexTransaction(\n tx: EthereumTransaction,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n for (const ds of dataSources) {\n await this.indexData(EthereumHandlerKind.Call, tx, ds, getVM);\n }\n }\n\n private async indexEvent(\n log: EthereumLog | LightEthereumLog,\n dataSources: EthereumProjectDs[],\n getVM: (d: EthereumProjectDs) => Promise<IndexerSandbox>,\n ): Promise<void> {\n for (const ds of dataSources) {\n await this.indexData(EthereumHandlerKind.Event, log, ds, getVM);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n protected async prepareFilteredData(\n kind: EthereumHandlerKind,\n data: any,\n ds: SubqlRuntimeDatasource,\n ): Promise<any> {\n return DataAbiParser[kind](this.apiService.api)(data, ds);\n }\n}\n\nconst ProcessorTypeMap = {\n [EthereumHandlerKind.Block]: isBlockHandlerProcessor,\n [EthereumHandlerKind.Event]: isEventHandlerProcessor,\n [EthereumHandlerKind.Call]: isCallHandlerProcessor,\n};\n\nconst FilterTypeMap = {\n [EthereumHandlerKind.Block]: (\n data: EthereumBlock,\n filter: EthereumBlockFilter,\n ds: SubqlEthereumDataSource,\n ) => filterBlocksProcessor(data, filter, ds.options?.address),\n [EthereumHandlerKind.Event]: (\n data: EthereumLog | LightEthereumLog,\n filter: EthereumLogFilter,\n ds: SubqlEthereumDataSource,\n ) => filterLogsProcessor(data, filter, ds.options?.address),\n [EthereumHandlerKind.Call]: (\n data: EthereumTransaction,\n filter: EthereumTransactionFilter,\n ds: SubqlEthereumDataSource,\n ) => filterTransactionsProcessor(data, filter, ds.options?.address),\n};\n\nconst DataAbiParser = {\n [EthereumHandlerKind.Block]: () => (data: EthereumBlock) => data,\n [EthereumHandlerKind.Event]:\n (api: EthereumApi) =>\n (data: EthereumLog | LightEthereumLog, ds: SubqlRuntimeDatasource) =>\n api.parseLog(data, ds),\n [EthereumHandlerKind.Call]:\n (api: EthereumApi) =>\n (data: EthereumTransaction, ds: SubqlRuntimeDatasource) =>\n api.parseTransaction(data, ds),\n};\n"]}
@@ -1,10 +1,10 @@
1
- import { ApiService, BaseUnfinalizedBlocksService, Header, NodeConfig, IStoreModelProvider } from '@subql/node-core';
1
+ import { UnfinalizedBlocksService as BaseUnfinalizedBlocksService, Header, NodeConfig, IStoreModelProvider } from '@subql/node-core';
2
+ import { BlockchainService } from '../blockchain.service';
2
3
  import { BlockContent } from './types';
3
4
  export declare class UnfinalizedBlocksService extends BaseUnfinalizedBlocksService<BlockContent> {
4
- private readonly apiService;
5
5
  private supportsFinalization?;
6
6
  private startupCheck;
7
- constructor(apiService: ApiService, nodeConfig: NodeConfig, storeModelProvider: IStoreModelProvider);
7
+ constructor(nodeConfig: NodeConfig, storeModelProvider: IStoreModelProvider, blockchainService: BlockchainService);
8
8
  /**
9
9
  * @param reindex - the function to reindex back before a fork
10
10
  * @param supportsFinalization - If the chain supports the 'finalized' block tag this should be true.
@@ -20,7 +20,4 @@ export declare class UnfinalizedBlocksService extends BaseUnfinalizedBlocksServi
20
20
  * @return (number | undefined) - The block height to rewind to to remove forked data
21
21
  **/
22
22
  protected getLastCorrectFinalizedBlock(forkedHeader: Header): Promise<Header | undefined>;
23
- protected getFinalizedHead(): Promise<Header>;
24
- protected getHeaderForHash(hash: string): Promise<Header>;
25
- getHeaderForHeight(height: number): Promise<Header>;
26
23
  }
@@ -18,16 +18,15 @@ exports.UnfinalizedBlocksService = void 0;
18
18
  const common_1 = require("@nestjs/common");
19
19
  const node_core_1 = require("@subql/node-core");
20
20
  const lodash_1 = require("lodash");
21
+ const blockchain_service_1 = require("../blockchain.service");
21
22
  const NodeConfig_1 = require("../configure/NodeConfig");
22
- const utils_ethereum_1 = require("../ethereum/utils.ethereum");
23
23
  const logger = (0, node_core_1.getLogger)('UnfinalizedBlocksService');
24
- let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_1.BaseUnfinalizedBlocksService {
25
- apiService;
24
+ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_1.UnfinalizedBlocksService {
26
25
  supportsFinalization;
27
26
  startupCheck = true;
28
- constructor(apiService, nodeConfig, storeModelProvider) {
29
- super(new NodeConfig_1.EthereumNodeConfig(nodeConfig), storeModelProvider);
30
- this.apiService = apiService;
27
+ constructor(nodeConfig, storeModelProvider, blockchainService) {
28
+ // blockchain service cast is due to unsolvable typescript generic error, it wokrs on the main sdk but not here
29
+ super(new NodeConfig_1.EthereumNodeConfig(nodeConfig), storeModelProvider, blockchainService);
31
30
  }
32
31
  /**
33
32
  * @param reindex - the function to reindex back before a fork
@@ -51,7 +50,7 @@ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_
51
50
  this.startupCheck = false;
52
51
  const lastUnfinalized = (0, lodash_1.last)(this.unfinalizedBlocks);
53
52
  if (lastUnfinalized) {
54
- const checkUnfinalized = await this.getHeaderForHeight(lastUnfinalized.blockHeight);
53
+ const checkUnfinalized = await this.blockchainService.getHeaderForHeight(lastUnfinalized.blockHeight);
55
54
  if (lastUnfinalized.blockHash !== checkUnfinalized.blockHash) {
56
55
  return checkUnfinalized;
57
56
  }
@@ -90,7 +89,7 @@ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_
90
89
  if (!checkingHeader.parentHash) {
91
90
  throw new Error('Unable to get parent hash for header');
92
91
  }
93
- checkingHeader = await this.getHeaderForHash(checkingHeader.parentHash);
92
+ checkingHeader = await this.blockchainService.getHeaderForHash(checkingHeader.parentHash);
94
93
  }
95
94
  try {
96
95
  const poiHeader = await this.findFinalizedUsingPOI(checkingHeader);
@@ -108,18 +107,6 @@ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_
108
107
  throw e;
109
108
  }
110
109
  }
111
- async getFinalizedHead() {
112
- const finalizedBlock = await this.apiService.api.getFinalizedBlock();
113
- return (0, utils_ethereum_1.ethereumBlockToHeader)(finalizedBlock);
114
- }
115
- async getHeaderForHash(hash) {
116
- const block = await this.apiService.api.getBlockByHeightOrHash(hash);
117
- return (0, utils_ethereum_1.ethereumBlockToHeader)(block);
118
- }
119
- async getHeaderForHeight(height) {
120
- const block = await this.apiService.api.getBlockByHeightOrHash(height);
121
- return (0, utils_ethereum_1.ethereumBlockToHeader)(block);
122
- }
123
110
  };
124
111
  exports.UnfinalizedBlocksService = UnfinalizedBlocksService;
125
112
  __decorate([
@@ -128,28 +115,10 @@ __decorate([
128
115
  __metadata("design:paramtypes", []),
129
116
  __metadata("design:returntype", Promise)
130
117
  ], UnfinalizedBlocksService.prototype, "hasForked", null);
131
- __decorate([
132
- (0, node_core_1.mainThreadOnly)(),
133
- __metadata("design:type", Function),
134
- __metadata("design:paramtypes", []),
135
- __metadata("design:returntype", Promise)
136
- ], UnfinalizedBlocksService.prototype, "getFinalizedHead", null);
137
- __decorate([
138
- (0, node_core_1.mainThreadOnly)(),
139
- __metadata("design:type", Function),
140
- __metadata("design:paramtypes", [String]),
141
- __metadata("design:returntype", Promise)
142
- ], UnfinalizedBlocksService.prototype, "getHeaderForHash", null);
143
- __decorate([
144
- (0, node_core_1.mainThreadOnly)(),
145
- __metadata("design:type", Function),
146
- __metadata("design:paramtypes", [Number]),
147
- __metadata("design:returntype", Promise)
148
- ], UnfinalizedBlocksService.prototype, "getHeaderForHeight", null);
149
118
  exports.UnfinalizedBlocksService = UnfinalizedBlocksService = __decorate([
150
119
  (0, common_1.Injectable)(),
151
- __param(2, (0, common_1.Inject)('IStoreModelProvider')),
152
- __metadata("design:paramtypes", [node_core_1.ApiService,
153
- node_core_1.NodeConfig, Object])
120
+ __param(1, (0, common_1.Inject)('IStoreModelProvider')),
121
+ __param(2, (0, common_1.Inject)('IBlockchainService')),
122
+ __metadata("design:paramtypes", [node_core_1.NodeConfig, Object, blockchain_service_1.BlockchainService])
154
123
  ], UnfinalizedBlocksService);
155
124
  //# sourceMappingURL=unfinalizedBlocks.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"unfinalizedBlocks.service.js","sourceRoot":"","sources":["../../src/indexer/unfinalizedBlocks.service.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport {\n ApiService,\n BaseUnfinalizedBlocksService,\n Header,\n mainThreadOnly,\n NodeConfig,\n getLogger,\n profiler,\n POI_NOT_ENABLED_ERROR_MESSAGE,\n IStoreModelProvider,\n} from '@subql/node-core';\nimport { last } from 'lodash';\nimport { EthereumNodeConfig } from '../configure/NodeConfig';\nimport { ethereumBlockToHeader } from '../ethereum/utils.ethereum';\nimport { BlockContent } from './types';\n\nconst logger = getLogger('UnfinalizedBlocksService');\n\n@Injectable()\nexport class UnfinalizedBlocksService extends BaseUnfinalizedBlocksService<BlockContent> {\n private supportsFinalization?: boolean;\n private startupCheck = true;\n\n constructor(\n private readonly apiService: ApiService,\n nodeConfig: NodeConfig,\n @Inject('IStoreModelProvider') storeModelProvider: IStoreModelProvider,\n ) {\n super(new EthereumNodeConfig(nodeConfig), storeModelProvider);\n }\n\n /**\n * @param reindex - the function to reindex back before a fork\n * @param supportsFinalization - If the chain supports the 'finalized' block tag this should be true.\n * */\n // eslint-disable-next-line @typescript-eslint/require-await\n async init(\n reindex: (targetHeight: Header) => Promise<void>,\n supportsFinalisation?: boolean,\n ): Promise<Header | undefined> {\n this.supportsFinalization = supportsFinalisation;\n return super.init(reindex);\n }\n /**\n * Checks if a fork has happened, this doesn't find the start of the fork just where it was detected\n * @returns (Header | undefined) - The header may be the forked header but will most likely be the main header. Either way it should be used just for the block height\n * */\n @profiler()\n protected async hasForked(): Promise<Header | undefined> {\n if (this.supportsFinalization) {\n return super.hasForked();\n }\n\n // Startup check helps speed up finding a fork by checking the hash of the last unfinalized block\n if (this.startupCheck) {\n this.startupCheck = false;\n const lastUnfinalized = last(this.unfinalizedBlocks);\n if (lastUnfinalized) {\n const checkUnfinalized = await this.getHeaderForHeight(\n lastUnfinalized.blockHeight,\n );\n\n if (lastUnfinalized.blockHash !== checkUnfinalized.blockHash) {\n return checkUnfinalized;\n }\n }\n }\n\n if (this.unfinalizedBlocks.length <= 2) {\n return;\n }\n\n const i = this.unfinalizedBlocks.length - 1;\n const current = this.unfinalizedBlocks[i];\n const parent = this.unfinalizedBlocks[i - 1];\n\n if (current.parentHash !== parent.blockHash) {\n // We've found a fork now we need to find where the fork happened\n logger.warn(\n `Block fork detected at ${current.blockHeight}. Parent hash ${current.parentHash} doesn't match indexed parent ${parent.blockHash}.`,\n );\n\n return current;\n }\n\n return;\n }\n\n /**\n * Finds the height before the fork occurred based on the result of hasForked\n * @return (number | undefined) - The block height to rewind to to remove forked data\n **/\n protected async getLastCorrectFinalizedBlock(\n forkedHeader: Header,\n ): Promise<Header | undefined> {\n if (this.supportsFinalization) {\n return super.getLastCorrectFinalizedBlock(forkedHeader);\n }\n\n const bestVerifiableBlocks = this.unfinalizedBlocks.filter(\n ({ blockHeight }) => blockHeight < forkedHeader.blockHeight,\n );\n\n let checkingHeader = forkedHeader;\n\n // Work backwards through the blocks until we find a matching hash\n for (const header of bestVerifiableBlocks.reverse()) {\n if (\n header.blockHash === checkingHeader.blockHash ||\n header.blockHash === checkingHeader.parentHash\n ) {\n return header;\n }\n\n // Get the new parent\n if (!checkingHeader.parentHash) {\n throw new Error('Unable to get parent hash for header');\n }\n checkingHeader = await this.getHeaderForHash(checkingHeader.parentHash);\n }\n\n try {\n const poiHeader = await this.findFinalizedUsingPOI(checkingHeader);\n return poiHeader;\n } catch (e: any) {\n if (e.message === POI_NOT_ENABLED_ERROR_MESSAGE) {\n return {\n blockHeight: Math.max(\n 0,\n forkedHeader.blockHeight -\n (this.nodeConfig as EthereumNodeConfig).blockForkReindex,\n ),\n } as Header;\n }\n // TODO rewind back 1000+ blocks\n logger.info('Failed to use POI to rewind block');\n throw e;\n }\n }\n\n @mainThreadOnly()\n protected async getFinalizedHead(): Promise<Header> {\n const finalizedBlock = await this.apiService.api.getFinalizedBlock();\n return ethereumBlockToHeader(finalizedBlock);\n }\n\n @mainThreadOnly()\n protected async getHeaderForHash(hash: string): Promise<Header> {\n const block = await this.apiService.api.getBlockByHeightOrHash(hash);\n return ethereumBlockToHeader(block);\n }\n\n @mainThreadOnly()\n async getHeaderForHeight(height: number): Promise<Header> {\n const block = await this.apiService.api.getBlockByHeightOrHash(height);\n return ethereumBlockToHeader(block);\n }\n}\n"]}
1
+ {"version":3,"file":"unfinalizedBlocks.service.js","sourceRoot":"","sources":["../../src/indexer/unfinalizedBlocks.service.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport {\n UnfinalizedBlocksService as BaseUnfinalizedBlocksService,\n Header,\n NodeConfig,\n getLogger,\n profiler,\n POI_NOT_ENABLED_ERROR_MESSAGE,\n IStoreModelProvider,\n IBlockchainService,\n} from '@subql/node-core';\nimport { last } from 'lodash';\nimport { BlockchainService } from '../blockchain.service';\nimport { EthereumNodeConfig } from '../configure/NodeConfig';\nimport { BlockContent } from './types';\n\nconst logger = getLogger('UnfinalizedBlocksService');\n\n@Injectable()\nexport class UnfinalizedBlocksService extends BaseUnfinalizedBlocksService<BlockContent> {\n private supportsFinalization?: boolean;\n private startupCheck = true;\n\n constructor(\n nodeConfig: NodeConfig,\n @Inject('IStoreModelProvider') storeModelProvider: IStoreModelProvider,\n @Inject('IBlockchainService') blockchainService: BlockchainService,\n ) {\n // blockchain service cast is due to unsolvable typescript generic error, it wokrs on the main sdk but not here\n super(\n new EthereumNodeConfig(nodeConfig),\n storeModelProvider,\n blockchainService as IBlockchainService,\n );\n }\n\n /**\n * @param reindex - the function to reindex back before a fork\n * @param supportsFinalization - If the chain supports the 'finalized' block tag this should be true.\n * */\n // eslint-disable-next-line @typescript-eslint/require-await\n async init(\n reindex: (targetHeight: Header) => Promise<void>,\n supportsFinalisation?: boolean,\n ): Promise<Header | undefined> {\n this.supportsFinalization = supportsFinalisation;\n return super.init(reindex);\n }\n /**\n * Checks if a fork has happened, this doesn't find the start of the fork just where it was detected\n * @returns (Header | undefined) - The header may be the forked header but will most likely be the main header. Either way it should be used just for the block height\n * */\n @profiler()\n protected async hasForked(): Promise<Header | undefined> {\n if (this.supportsFinalization) {\n return super.hasForked();\n }\n\n // Startup check helps speed up finding a fork by checking the hash of the last unfinalized block\n if (this.startupCheck) {\n this.startupCheck = false;\n const lastUnfinalized = last(this.unfinalizedBlocks);\n if (lastUnfinalized) {\n const checkUnfinalized =\n await this.blockchainService.getHeaderForHeight(\n lastUnfinalized.blockHeight,\n );\n\n if (lastUnfinalized.blockHash !== checkUnfinalized.blockHash) {\n return checkUnfinalized;\n }\n }\n }\n\n if (this.unfinalizedBlocks.length <= 2) {\n return;\n }\n\n const i = this.unfinalizedBlocks.length - 1;\n const current = this.unfinalizedBlocks[i];\n const parent = this.unfinalizedBlocks[i - 1];\n\n if (current.parentHash !== parent.blockHash) {\n // We've found a fork now we need to find where the fork happened\n logger.warn(\n `Block fork detected at ${current.blockHeight}. Parent hash ${current.parentHash} doesn't match indexed parent ${parent.blockHash}.`,\n );\n\n return current;\n }\n\n return;\n }\n\n /**\n * Finds the height before the fork occurred based on the result of hasForked\n * @return (number | undefined) - The block height to rewind to to remove forked data\n **/\n protected async getLastCorrectFinalizedBlock(\n forkedHeader: Header,\n ): Promise<Header | undefined> {\n if (this.supportsFinalization) {\n return super.getLastCorrectFinalizedBlock(forkedHeader);\n }\n\n const bestVerifiableBlocks = this.unfinalizedBlocks.filter(\n ({ blockHeight }) => blockHeight < forkedHeader.blockHeight,\n );\n\n let checkingHeader = forkedHeader;\n\n // Work backwards through the blocks until we find a matching hash\n for (const header of bestVerifiableBlocks.reverse()) {\n if (\n header.blockHash === checkingHeader.blockHash ||\n header.blockHash === checkingHeader.parentHash\n ) {\n return header;\n }\n\n // Get the new parent\n if (!checkingHeader.parentHash) {\n throw new Error('Unable to get parent hash for header');\n }\n checkingHeader = await this.blockchainService.getHeaderForHash(\n checkingHeader.parentHash,\n );\n }\n\n try {\n const poiHeader = await this.findFinalizedUsingPOI(checkingHeader);\n return poiHeader;\n } catch (e: any) {\n if (e.message === POI_NOT_ENABLED_ERROR_MESSAGE) {\n return {\n blockHeight: Math.max(\n 0,\n forkedHeader.blockHeight -\n (this.nodeConfig as EthereumNodeConfig).blockForkReindex,\n ),\n } as Header;\n }\n // TODO rewind back 1000+ blocks\n logger.info('Failed to use POI to rewind block');\n throw e;\n }\n }\n}\n"]}
@@ -4,6 +4,7 @@
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  const bytes_1 = require("@ethersproject/bytes");
6
6
  const node_core_1 = require("@subql/node-core");
7
+ const blockchain_service_1 = require("../blockchain.service");
7
8
  const unfinalizedBlocks_service_1 = require("./unfinalizedBlocks.service");
8
9
  // Adds 0 padding so we can convert to POI block
9
10
  const hexify = (input) => (0, bytes_1.hexZeroPad)(input, 4);
@@ -67,10 +68,11 @@ describe('UnfinalizedBlockService', () => {
67
68
  let storeCache;
68
69
  beforeEach(() => {
69
70
  storeCache = mockStoreCache();
70
- unfinalizedBlocks = new unfinalizedBlocks_service_1.UnfinalizedBlocksService(getMockApi(), new node_core_1.NodeConfig({
71
+ const blockchainService = new blockchain_service_1.BlockchainService(getMockApi());
72
+ unfinalizedBlocks = new unfinalizedBlocks_service_1.UnfinalizedBlocksService(new node_core_1.NodeConfig({
71
73
  unfinalizedBlocks: true,
72
74
  blockForkReindex: 1000,
73
- }), storeCache);
75
+ }), storeCache, blockchainService);
74
76
  });
75
77
  it('handles a block fork', async () => {
76
78
  await unfinalizedBlocks.init(jest.fn());
@@ -112,12 +114,12 @@ describe('UnfinalizedBlockService', () => {
112
114
  });
113
115
  // The finalized block is after the cached unfinalized blocks, they should be rechecked
114
116
  it('startup, correctly checks for forks after cached unfinalized blocks', async () => {
115
- storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
117
+ await storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
116
118
  makeHeader(99, true),
117
119
  makeHeader(100),
118
120
  makeHeader(101),
119
121
  ]));
120
- storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 99);
122
+ await storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 99);
121
123
  const rewind = jest.fn();
122
124
  await unfinalizedBlocks.init(rewind);
123
125
  // It should fall back to poi in this case
@@ -129,12 +131,12 @@ describe('UnfinalizedBlockService', () => {
129
131
  });
130
132
  });
131
133
  it('startup, correctly checks for forks within cached unfinalized blocks', async () => {
132
- storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
134
+ await storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
133
135
  makeHeader(110),
134
136
  makeHeader(111),
135
137
  makeHeader(112),
136
138
  ]));
137
- storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
139
+ await storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
138
140
  const rewind = jest.fn();
139
141
  await unfinalizedBlocks.init(rewind);
140
142
  // It should fall back to poi in this case
@@ -146,18 +148,18 @@ describe('UnfinalizedBlockService', () => {
146
148
  });
147
149
  });
148
150
  it('doesnt throw if there are no unfinalized blocks on startup', async () => {
149
- storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
151
+ await storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
150
152
  await expect(unfinalizedBlocks.init(jest.fn())).resolves.not.toThrow();
151
153
  });
152
154
  it('rewinds using blockForkReindex value if poi is not enabled', async () => {
153
155
  // Do this to "disable" poi
154
156
  storeCache.poi = null;
155
- storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
157
+ await storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
156
158
  makeHeader(110),
157
159
  makeHeader(111),
158
160
  makeHeader(112),
159
161
  ]));
160
- storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
162
+ await storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
161
163
  const rewind = jest.fn();
162
164
  await unfinalizedBlocks.init(rewind);
163
165
  // It should fall back to poi in this case
@@ -1 +1 @@
1
- {"version":3,"file":"unfinalizedBlocks.service.spec.js","sourceRoot":"","sources":["../../src/indexer/unfinalizedBlocks.service.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { hexZeroPad } from '@ethersproject/bytes';\nimport {\n ApiService,\n CacheMetadataModel,\n Header,\n NodeConfig,\n PoiBlock,\n StoreCacheService,\n METADATA_UNFINALIZED_BLOCKS_KEY,\n METADATA_LAST_FINALIZED_PROCESSED_KEY,\n} from '@subql/node-core';\nimport { EthereumNodeConfig } from '../configure/NodeConfig';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\n// Adds 0 padding so we can convert to POI block\nconst hexify = (input: string) => hexZeroPad(input, 4);\n\n// Mock 1740100000 is the timestamp of the genesis block\nconst genBlockTimestamp = (height: number) => (1740100000 + height) * 1000;\nconst genBlockDate = (height: number) => new Date(genBlockTimestamp(height));\n\nconst makeHeader = (height: number, finalized?: boolean): Header => ({\n blockHeight: height,\n blockHash: hexify(`0xABC${height}${finalized ? 'f' : ''}`),\n parentHash: hexify(`0xABC${height - 1}${finalized ? 'f' : ''}`),\n timestamp: genBlockDate(height),\n});\n\nconst getMockApi = (): ApiService => {\n return {\n api: {\n getBlockByHeightOrHash: (hash: string | number) => {\n const num =\n typeof hash === 'number'\n ? hash\n : Number(\n hash\n .toString()\n .replace('0x', '')\n .replace('ABC', '')\n .replace('f', ''),\n );\n return Promise.resolve({\n number: num,\n hash: typeof hash === 'number' ? hexify(`0xABC${hash}f`) : hash,\n parentHash: hexify(`0xABC${num - 1}f`),\n timestamp: genBlockTimestamp(num) / 1000,\n });\n },\n getFinalizedBlock: jest.fn(() => ({\n number: 110,\n hash: '0xABC110f',\n parentHash: '0xABC109f',\n timestamp: genBlockTimestamp(110) / 1000,\n })),\n },\n } as any;\n};\n\nfunction getMockMetadata(): any {\n const data: Record<string, any> = {};\n return {\n upsert: ({ key, value }: any) => (data[key] = value),\n findOne: ({ where: { key } }: any) => ({ value: data[key] }),\n findByPk: (key: string) => data[key],\n find: (key: string) => data[key],\n } as any;\n}\n\nfunction mockStoreCache(): StoreCacheService {\n return {\n metadata: new CacheMetadataModel(getMockMetadata()),\n poi: {\n getPoiBlocksBefore: jest.fn(() => [\n PoiBlock.create(99, hexify('0xABC99f'), new Uint8Array(), ''),\n ]),\n },\n } as any as StoreCacheService;\n}\n\ndescribe('UnfinalizedBlockService', () => {\n let unfinalizedBlocks: UnfinalizedBlocksService;\n let storeCache: StoreCacheService;\n\n beforeEach(() => {\n storeCache = mockStoreCache();\n\n unfinalizedBlocks = new UnfinalizedBlocksService(\n getMockApi(),\n new NodeConfig({\n unfinalizedBlocks: true,\n blockForkReindex: 1000,\n } as any) as EthereumNodeConfig,\n storeCache,\n );\n });\n\n it('handles a block fork', async () => {\n await unfinalizedBlocks.init(jest.fn());\n\n (unfinalizedBlocks as any)._unfinalizedBlocks = [\n makeHeader(100),\n makeHeader(101),\n makeHeader(102),\n makeHeader(103, true), // Where the fork started\n makeHeader(104),\n makeHeader(105),\n makeHeader(106),\n makeHeader(107),\n makeHeader(108),\n makeHeader(109),\n makeHeader(110),\n ];\n\n const rewind = await unfinalizedBlocks.processUnfinalizedBlockHeader(\n makeHeader(111, true),\n );\n\n expect(rewind?.blockHeight).toEqual(103);\n });\n\n it('uses POI blocks if there are not enough cached unfinalized blocks', async () => {\n await unfinalizedBlocks.init(jest.fn());\n\n (unfinalizedBlocks as any)._unfinalizedBlocks = [\n makeHeader(100),\n makeHeader(101),\n makeHeader(102),\n makeHeader(103),\n makeHeader(104),\n makeHeader(105),\n makeHeader(106),\n makeHeader(107),\n makeHeader(108),\n makeHeader(109),\n makeHeader(110),\n ];\n\n const spy = jest.spyOn(storeCache.poi as any, 'getPoiBlocksBefore');\n\n const rewind = await unfinalizedBlocks.processUnfinalizedBlockHeader(\n makeHeader(111, true),\n );\n\n expect(rewind?.blockHeight).toEqual(99);\n expect(spy).toHaveBeenCalled();\n });\n\n // The finalized block is after the cached unfinalized blocks, they should be rechecked\n it('startup, correctly checks for forks after cached unfinalized blocks', async () => {\n storeCache.metadata.set(\n METADATA_UNFINALIZED_BLOCKS_KEY,\n JSON.stringify(<Header[]>[\n makeHeader(99, true),\n makeHeader(100),\n makeHeader(101),\n ]),\n );\n\n storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 99);\n\n const rewind = jest.fn();\n\n await unfinalizedBlocks.init(rewind);\n\n // It should fall back to poi in this case\n expect(rewind).toHaveBeenCalledWith({\n blockHash: '0x00ABC99f',\n blockHeight: 99,\n parentHash: '0x00ABC98f',\n timestamp: genBlockDate(99),\n });\n });\n\n it('startup, correctly checks for forks within cached unfinalized blocks', async () => {\n storeCache.metadata.set(\n METADATA_UNFINALIZED_BLOCKS_KEY,\n JSON.stringify(<Header[]>[\n makeHeader(110),\n makeHeader(111),\n makeHeader(112),\n ]),\n );\n\n storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);\n\n const rewind = jest.fn();\n\n await unfinalizedBlocks.init(rewind);\n\n // It should fall back to poi in this case\n expect(rewind).toHaveBeenCalledWith({\n blockHash: '0x00ABC99f',\n blockHeight: 99,\n parentHash: '0x00ABC98f',\n timestamp: genBlockDate(99),\n });\n });\n\n it('doesnt throw if there are no unfinalized blocks on startup', async () => {\n storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);\n\n await expect(unfinalizedBlocks.init(jest.fn())).resolves.not.toThrow();\n });\n\n it('rewinds using blockForkReindex value if poi is not enabled', async () => {\n // Do this to \"disable\" poi\n (storeCache as any).poi = null;\n\n storeCache.metadata.set(\n METADATA_UNFINALIZED_BLOCKS_KEY,\n JSON.stringify(<Header[]>[\n makeHeader(110),\n makeHeader(111),\n makeHeader(112),\n ]),\n );\n\n storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);\n\n const rewind = jest.fn();\n\n await unfinalizedBlocks.init(rewind);\n\n // It should fall back to poi in this case\n expect(rewind).toHaveBeenCalledWith({ blockHeight: 0 });\n });\n});\n"]}
1
+ {"version":3,"file":"unfinalizedBlocks.service.spec.js","sourceRoot":"","sources":["../../src/indexer/unfinalizedBlocks.service.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAEnC,gDAAkD;AAClD,gDAQ0B;AAC1B,8DAA0D;AAG1D,2EAAuE;AAEvE,gDAAgD;AAChD,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAA,kBAAU,EAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAEvD,wDAAwD;AACxD,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC;AAC3E,MAAM,YAAY,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAE7E,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,SAAmB,EAAU,EAAE,CAAC,CAAC;IACnE,WAAW,EAAE,MAAM;IACnB,SAAS,EAAE,MAAM,CAAC,QAAQ,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1D,UAAU,EAAE,MAAM,CAAC,QAAQ,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC/D,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC;CAChC,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,GAAuB,EAAE;IAC1C,OAAO;QACL,GAAG,EAAE;YACH,sBAAsB,EAAE,CAAC,IAAqB,EAAE,EAAE;gBAChD,MAAM,GAAG,GACP,OAAO,IAAI,KAAK,QAAQ;oBACtB,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,MAAM,CACJ,IAAI;yBACD,QAAQ,EAAE;yBACV,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;yBACjB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;yBAClB,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,CAAC;gBACR,OAAO,OAAO,CAAC,OAAO,CAAC;oBACrB,MAAM,EAAE,GAAG;oBACX,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;oBAC/D,UAAU,EAAE,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC;oBACtC,SAAS,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,IAAI;iBACzC,CAAC,CAAC;YACL,CAAC;YACD,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;gBAChC,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,WAAW;gBACjB,UAAU,EAAE,WAAW;gBACvB,SAAS,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,IAAI;aACzC,CAAC,CAAC;SACJ;KACK,CAAC;AACX,CAAC,CAAC;AAEF,SAAS,eAAe;IACtB,MAAM,IAAI,GAAwB,EAAE,CAAC;IACrC,OAAO;QACL,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACpD,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAO,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;QACpC,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;KAC1B,CAAC;AACX,CAAC;AAED,SAAS,cAAc;IACrB,OAAO;QACL,QAAQ,EAAE,IAAI,8BAAkB,CAAC,eAAe,EAAE,CAAC;QACnD,GAAG,EAAE;YACH,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;gBAChC,oBAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,IAAI,UAAU,EAAE,EAAE,EAAE,CAAC;aAC9D,CAAC;SACH;KAC0B,CAAC;AAChC,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,IAAI,iBAA2C,CAAC;IAChD,IAAI,UAA6B,CAAC;IAElC,UAAU,CAAC,GAAG,EAAE;QACd,UAAU,GAAG,cAAc,EAAE,CAAC;QAE9B,MAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,UAAU,EAAE,CAAC,CAAC;QAE9D,iBAAiB,GAAG,IAAI,oDAAwB,CAC9C,IAAI,sBAAU,CAAC;YACb,iBAAiB,EAAE,IAAI;YACvB,gBAAgB,EAAE,IAAI;SAChB,CAAuB,EAC/B,UAAU,EACV,iBAAiB,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAEvC,iBAAyB,CAAC,kBAAkB,GAAG;YAC9C,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,yBAAyB;YAChD,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;SAChB,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,6BAA6B,CAClE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CACtB,CAAC;QAEF,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAEvC,iBAAyB,CAAC,kBAAkB,GAAG;YAC9C,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;SAChB,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAU,EAAE,oBAAoB,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,6BAA6B,CAClE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CACtB,CAAC;QAEF,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,uFAAuF;IACvF,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAC3B,2CAA+B,EAC/B,IAAI,CAAC,SAAS,CAAW;YACvB,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC;YACpB,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;SAChB,CAAC,CACH,CAAC;QAEF,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,iDAAqC,EAAE,EAAE,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAEzB,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErC,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC;YAClC,SAAS,EAAE,YAAY;YACvB,WAAW,EAAE,EAAE;YACf,UAAU,EAAE,YAAY;YACxB,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAC3B,2CAA+B,EAC/B,IAAI,CAAC,SAAS,CAAW;YACvB,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;SAChB,CAAC,CACH,CAAC;QAEF,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,iDAAqC,EAAE,GAAG,CAAC,CAAC;QAE1E,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAEzB,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErC,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC;YAClC,SAAS,EAAE,YAAY;YACvB,WAAW,EAAE,EAAE;YACf,UAAU,EAAE,YAAY;YACxB,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,iDAAqC,EAAE,GAAG,CAAC,CAAC;QAE1E,MAAM,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,2BAA2B;QAC1B,UAAkB,CAAC,GAAG,GAAG,IAAI,CAAC;QAE/B,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAC3B,2CAA+B,EAC/B,IAAI,CAAC,SAAS,CAAW;YACvB,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;YACf,UAAU,CAAC,GAAG,CAAC;SAChB,CAAC,CACH,CAAC;QAEF,MAAM,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,iDAAqC,EAAE,GAAG,CAAC,CAAC;QAE1E,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAEzB,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErC,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { hexZeroPad } from '@ethersproject/bytes';\nimport {\n CacheMetadataModel,\n Header,\n NodeConfig,\n PoiBlock,\n StoreCacheService,\n METADATA_UNFINALIZED_BLOCKS_KEY,\n METADATA_LAST_FINALIZED_PROCESSED_KEY,\n} from '@subql/node-core';\nimport { BlockchainService } from '../blockchain.service';\nimport { EthereumNodeConfig } from '../configure/NodeConfig';\nimport { EthereumApiService } from '../ethereum';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\n// Adds 0 padding so we can convert to POI block\nconst hexify = (input: string) => hexZeroPad(input, 4);\n\n// Mock 1740100000 is the timestamp of the genesis block\nconst genBlockTimestamp = (height: number) => (1740100000 + height) * 1000;\nconst genBlockDate = (height: number) => new Date(genBlockTimestamp(height));\n\nconst makeHeader = (height: number, finalized?: boolean): Header => ({\n blockHeight: height,\n blockHash: hexify(`0xABC${height}${finalized ? 'f' : ''}`),\n parentHash: hexify(`0xABC${height - 1}${finalized ? 'f' : ''}`),\n timestamp: genBlockDate(height),\n});\n\nconst getMockApi = (): EthereumApiService => {\n return {\n api: {\n getBlockByHeightOrHash: (hash: string | number) => {\n const num =\n typeof hash === 'number'\n ? hash\n : Number(\n hash\n .toString()\n .replace('0x', '')\n .replace('ABC', '')\n .replace('f', ''),\n );\n return Promise.resolve({\n number: num,\n hash: typeof hash === 'number' ? hexify(`0xABC${hash}f`) : hash,\n parentHash: hexify(`0xABC${num - 1}f`),\n timestamp: genBlockTimestamp(num) / 1000,\n });\n },\n getFinalizedBlock: jest.fn(() => ({\n number: 110,\n hash: '0xABC110f',\n parentHash: '0xABC109f',\n timestamp: genBlockTimestamp(110) / 1000,\n })),\n },\n } as any;\n};\n\nfunction getMockMetadata(): any {\n const data: Record<string, any> = {};\n return {\n upsert: ({ key, value }: any) => (data[key] = value),\n findOne: ({ where: { key } }: any) => ({ value: data[key] }),\n findByPk: (key: string) => data[key],\n find: (key: string) => data[key],\n } as any;\n}\n\nfunction mockStoreCache(): StoreCacheService {\n return {\n metadata: new CacheMetadataModel(getMockMetadata()),\n poi: {\n getPoiBlocksBefore: jest.fn(() => [\n PoiBlock.create(99, hexify('0xABC99f'), new Uint8Array(), ''),\n ]),\n },\n } as any as StoreCacheService;\n}\n\ndescribe('UnfinalizedBlockService', () => {\n let unfinalizedBlocks: UnfinalizedBlocksService;\n let storeCache: StoreCacheService;\n\n beforeEach(() => {\n storeCache = mockStoreCache();\n\n const blockchainService = new BlockchainService(getMockApi());\n\n unfinalizedBlocks = new UnfinalizedBlocksService(\n new NodeConfig({\n unfinalizedBlocks: true,\n blockForkReindex: 1000,\n } as any) as EthereumNodeConfig,\n storeCache,\n blockchainService,\n );\n });\n\n it('handles a block fork', async () => {\n await unfinalizedBlocks.init(jest.fn());\n\n (unfinalizedBlocks as any)._unfinalizedBlocks = [\n makeHeader(100),\n makeHeader(101),\n makeHeader(102),\n makeHeader(103, true), // Where the fork started\n makeHeader(104),\n makeHeader(105),\n makeHeader(106),\n makeHeader(107),\n makeHeader(108),\n makeHeader(109),\n makeHeader(110),\n ];\n\n const rewind = await unfinalizedBlocks.processUnfinalizedBlockHeader(\n makeHeader(111, true),\n );\n\n expect(rewind?.blockHeight).toEqual(103);\n });\n\n it('uses POI blocks if there are not enough cached unfinalized blocks', async () => {\n await unfinalizedBlocks.init(jest.fn());\n\n (unfinalizedBlocks as any)._unfinalizedBlocks = [\n makeHeader(100),\n makeHeader(101),\n makeHeader(102),\n makeHeader(103),\n makeHeader(104),\n makeHeader(105),\n makeHeader(106),\n makeHeader(107),\n makeHeader(108),\n makeHeader(109),\n makeHeader(110),\n ];\n\n const spy = jest.spyOn(storeCache.poi as any, 'getPoiBlocksBefore');\n\n const rewind = await unfinalizedBlocks.processUnfinalizedBlockHeader(\n makeHeader(111, true),\n );\n\n expect(rewind?.blockHeight).toEqual(99);\n expect(spy).toHaveBeenCalled();\n });\n\n // The finalized block is after the cached unfinalized blocks, they should be rechecked\n it('startup, correctly checks for forks after cached unfinalized blocks', async () => {\n await storeCache.metadata.set(\n METADATA_UNFINALIZED_BLOCKS_KEY,\n JSON.stringify(<Header[]>[\n makeHeader(99, true),\n makeHeader(100),\n makeHeader(101),\n ]),\n );\n\n await storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 99);\n\n const rewind = jest.fn();\n\n await unfinalizedBlocks.init(rewind);\n\n // It should fall back to poi in this case\n expect(rewind).toHaveBeenCalledWith({\n blockHash: '0x00ABC99f',\n blockHeight: 99,\n parentHash: '0x00ABC98f',\n timestamp: genBlockDate(99),\n });\n });\n\n it('startup, correctly checks for forks within cached unfinalized blocks', async () => {\n await storeCache.metadata.set(\n METADATA_UNFINALIZED_BLOCKS_KEY,\n JSON.stringify(<Header[]>[\n makeHeader(110),\n makeHeader(111),\n makeHeader(112),\n ]),\n );\n\n await storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);\n\n const rewind = jest.fn();\n\n await unfinalizedBlocks.init(rewind);\n\n // It should fall back to poi in this case\n expect(rewind).toHaveBeenCalledWith({\n blockHash: '0x00ABC99f',\n blockHeight: 99,\n parentHash: '0x00ABC98f',\n timestamp: genBlockDate(99),\n });\n });\n\n it('doesnt throw if there are no unfinalized blocks on startup', async () => {\n await storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);\n\n await expect(unfinalizedBlocks.init(jest.fn())).resolves.not.toThrow();\n });\n\n it('rewinds using blockForkReindex value if poi is not enabled', async () => {\n // Do this to \"disable\" poi\n (storeCache as any).poi = null;\n\n await storeCache.metadata.set(\n METADATA_UNFINALIZED_BLOCKS_KEY,\n JSON.stringify(<Header[]>[\n makeHeader(110),\n makeHeader(111),\n makeHeader(112),\n ]),\n );\n\n await storeCache.metadata.set(METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);\n\n const rewind = jest.fn();\n\n await unfinalizedBlocks.init(rewind);\n\n // It should fall back to poi in this case\n expect(rewind).toHaveBeenCalledWith({ blockHeight: 0 });\n });\n});\n"]}