@subql/node-ethereum 5.1.7 → 5.2.0

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 (31) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/ethereum/api.ethereum.test.js +9 -14
  4. package/dist/ethereum/api.ethereum.test.js.map +1 -1
  5. package/dist/ethereum/ethers/celo/celo-provider.d.ts +3 -3
  6. package/dist/indexer/blockDispatcher/block-dispatcher.service.d.ts +2 -2
  7. package/dist/indexer/blockDispatcher/block-dispatcher.service.js +4 -5
  8. package/dist/indexer/blockDispatcher/block-dispatcher.service.js.map +1 -1
  9. package/dist/indexer/blockDispatcher/worker-block-dispatcher.service.d.ts +3 -3
  10. package/dist/indexer/blockDispatcher/worker-block-dispatcher.service.js +5 -6
  11. package/dist/indexer/blockDispatcher/worker-block-dispatcher.service.js.map +1 -1
  12. package/dist/indexer/fetch.module.js +4 -4
  13. package/dist/indexer/fetch.module.js.map +1 -1
  14. package/dist/indexer/fetch.service.d.ts +2 -2
  15. package/dist/indexer/fetch.service.js +4 -4
  16. package/dist/indexer/fetch.service.js.map +1 -1
  17. package/dist/indexer/project.service.d.ts +2 -2
  18. package/dist/indexer/project.service.js.map +1 -1
  19. package/dist/indexer/unfinalizedBlocks.service.d.ts +5 -5
  20. package/dist/indexer/unfinalizedBlocks.service.js +16 -11
  21. package/dist/indexer/unfinalizedBlocks.service.js.map +1 -1
  22. package/dist/indexer/unfinalizedBlocks.service.spec.js +13 -5
  23. package/dist/indexer/unfinalizedBlocks.service.spec.js.map +1 -1
  24. package/dist/indexer/worker/worker.service.d.ts +3 -7
  25. package/dist/indexer/worker/worker.service.js +2 -0
  26. package/dist/indexer/worker/worker.service.js.map +1 -1
  27. package/dist/subcommands/reindex.module.js +6 -1
  28. package/dist/subcommands/reindex.module.js.map +1 -1
  29. package/dist/subcommands/testing.module.js +6 -1
  30. package/dist/subcommands/testing.module.js.map +1 -1
  31. package/package.json +4 -4
@@ -10,6 +10,9 @@ 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.UnfinalizedBlocksService = void 0;
15
18
  const common_1 = require("@nestjs/common");
@@ -22,8 +25,8 @@ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_
22
25
  apiService;
23
26
  supportsFinalization;
24
27
  startupCheck = true;
25
- constructor(apiService, nodeConfig, storeCache) {
26
- super(new NodeConfig_1.EthereumNodeConfig(nodeConfig), storeCache);
28
+ constructor(apiService, nodeConfig, storeModelProvider) {
29
+ super(new NodeConfig_1.EthereumNodeConfig(nodeConfig), storeModelProvider);
27
30
  this.apiService = apiService;
28
31
  }
29
32
  /**
@@ -77,10 +80,10 @@ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_
77
80
  const bestVerifiableBlocks = this.unfinalizedBlocks.filter(({ blockHeight }) => blockHeight < forkedHeader.blockHeight);
78
81
  let checkingHeader = forkedHeader;
79
82
  // Work backwards through the blocks until we find a matching hash
80
- for (const { blockHash, blockHeight } of bestVerifiableBlocks.reverse()) {
81
- if (blockHash === checkingHeader.blockHash ||
82
- blockHash === checkingHeader.parentHash) {
83
- return blockHeight;
83
+ for (const header of bestVerifiableBlocks.reverse()) {
84
+ if (header.blockHash === checkingHeader.blockHash ||
85
+ header.blockHash === checkingHeader.parentHash) {
86
+ return header;
84
87
  }
85
88
  // Get the new parent
86
89
  if (!checkingHeader.parentHash) {
@@ -90,12 +93,14 @@ let UnfinalizedBlocksService = class UnfinalizedBlocksService extends node_core_
90
93
  }
91
94
  try {
92
95
  const poiHeader = await this.findFinalizedUsingPOI(checkingHeader);
93
- return poiHeader.blockHeight;
96
+ return poiHeader;
94
97
  }
95
98
  catch (e) {
96
99
  if (e.message === node_core_1.POI_NOT_ENABLED_ERROR_MESSAGE) {
97
- return Math.max(0, forkedHeader.blockHeight -
98
- this.nodeConfig.blockForkReindex);
100
+ return {
101
+ blockHeight: Math.max(0, forkedHeader.blockHeight -
102
+ this.nodeConfig.blockForkReindex),
103
+ };
99
104
  }
100
105
  // TODO rewind back 1000+ blocks
101
106
  logger.info('Failed to use POI to rewind block');
@@ -142,8 +147,8 @@ __decorate([
142
147
  ], UnfinalizedBlocksService.prototype, "getHeaderForHeight", null);
143
148
  exports.UnfinalizedBlocksService = UnfinalizedBlocksService = __decorate([
144
149
  (0, common_1.Injectable)(),
150
+ __param(2, (0, common_1.Inject)('IStoreModelProvider')),
145
151
  __metadata("design:paramtypes", [node_core_1.ApiService,
146
- node_core_1.NodeConfig,
147
- node_core_1.StoreCacheService])
152
+ node_core_1.NodeConfig, Object])
148
153
  ], UnfinalizedBlocksService);
149
154
  //# 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-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Injectable } from '@nestjs/common';\nimport {\n ApiService,\n BaseUnfinalizedBlocksService,\n Header,\n mainThreadOnly,\n NodeConfig,\n StoreCacheService,\n getLogger,\n profiler,\n POI_NOT_ENABLED_ERROR_MESSAGE,\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 storeCache: StoreCacheService,\n ) {\n super(new EthereumNodeConfig(nodeConfig), storeCache);\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 async init(\n reindex: (targetHeight: number) => Promise<void>,\n supportsFinalisation?: boolean,\n ): Promise<number | 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<number | 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 { blockHash, blockHeight } of bestVerifiableBlocks.reverse()) {\n if (\n blockHash === checkingHeader.blockHash ||\n blockHash === checkingHeader.parentHash\n ) {\n return blockHeight;\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.blockHeight;\n } catch (e: any) {\n if (e.message === POI_NOT_ENABLED_ERROR_MESSAGE) {\n return Math.max(\n 0,\n forkedHeader.blockHeight -\n (this.nodeConfig as EthereumNodeConfig).blockForkReindex,\n );\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 protected 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-2024 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 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"]}
@@ -82,7 +82,7 @@ describe('UnfinalizedBlockService', () => {
82
82
  makeHeader(110),
83
83
  ];
84
84
  const rewind = await unfinalizedBlocks.processUnfinalizedBlockHeader(makeHeader(111, true));
85
- expect(rewind).toEqual(103);
85
+ expect(rewind?.blockHeight).toEqual(103);
86
86
  });
87
87
  it('uses POI blocks if there are not enough cached unfinalized blocks', async () => {
88
88
  await unfinalizedBlocks.init(jest.fn());
@@ -101,7 +101,7 @@ describe('UnfinalizedBlockService', () => {
101
101
  ];
102
102
  const spy = jest.spyOn(storeCache.poi, 'getPoiBlocksBefore');
103
103
  const rewind = await unfinalizedBlocks.processUnfinalizedBlockHeader(makeHeader(111, true));
104
- expect(rewind).toEqual(99);
104
+ expect(rewind?.blockHeight).toEqual(99);
105
105
  expect(spy).toHaveBeenCalled();
106
106
  });
107
107
  // The finalized block is after the cached unfinalized blocks, they should be rechecked
@@ -115,7 +115,11 @@ describe('UnfinalizedBlockService', () => {
115
115
  const rewind = jest.fn();
116
116
  await unfinalizedBlocks.init(rewind);
117
117
  // It should fall back to poi in this case
118
- expect(rewind).toHaveBeenCalledWith(99);
118
+ expect(rewind).toHaveBeenCalledWith({
119
+ blockHash: '0x00ABC99f',
120
+ blockHeight: 99,
121
+ parentHash: '0x00ABC98f',
122
+ });
119
123
  });
120
124
  it('startup, correctly checks for forks within cached unfinalized blocks', async () => {
121
125
  storeCache.metadata.set(node_core_1.METADATA_UNFINALIZED_BLOCKS_KEY, JSON.stringify([
@@ -127,7 +131,11 @@ describe('UnfinalizedBlockService', () => {
127
131
  const rewind = jest.fn();
128
132
  await unfinalizedBlocks.init(rewind);
129
133
  // It should fall back to poi in this case
130
- expect(rewind).toHaveBeenCalledWith(99);
134
+ expect(rewind).toHaveBeenCalledWith({
135
+ blockHash: '0x00ABC99f',
136
+ blockHeight: 99,
137
+ parentHash: '0x00ABC98f',
138
+ });
131
139
  });
132
140
  it('doesnt throw if there are no unfinalized blocks on startup', async () => {
133
141
  storeCache.metadata.set(node_core_1.METADATA_LAST_FINALIZED_PROCESSED_KEY, 109);
@@ -145,7 +153,7 @@ describe('UnfinalizedBlockService', () => {
145
153
  const rewind = jest.fn();
146
154
  await unfinalizedBlocks.init(rewind);
147
155
  // It should fall back to poi in this case
148
- expect(rewind).toHaveBeenCalledWith(0);
156
+ expect(rewind).toHaveBeenCalledWith({ blockHeight: 0 });
149
157
  });
150
158
  });
151
159
  //# sourceMappingURL=unfinalizedBlocks.service.spec.js.map
@@ -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-2024 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\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});\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 });\n },\n getFinalizedBlock: jest.fn(() => ({\n number: 110,\n hash: '0xABC110f',\n parentHash: '0xABC109f',\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).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).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(99);\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(99);\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(0);\n });\n});\n"]}
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-2024 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\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});\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 });\n },\n getFinalizedBlock: jest.fn(() => ({\n number: 110,\n hash: '0xABC110f',\n parentHash: '0xABC109f',\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 });\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 });\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,13 +1,11 @@
1
1
  import { SubqlEthereumDataSource } from '@subql/common-ethereum';
2
- import { NodeConfig, IProjectService, ProcessBlockResponse, ApiService, BaseWorkerService, IProjectUpgradeService, IBlock } from '@subql/node-core';
2
+ import { NodeConfig, IProjectService, ProcessBlockResponse, ApiService, BaseWorkerService, IProjectUpgradeService, IBlock, Header } from '@subql/node-core';
3
3
  import { EthereumProjectDs } from '../../configure/SubqueryProject';
4
4
  import { EthereumApi } from '../../ethereum';
5
5
  import SafeEthProvider from '../../ethereum/safe-api';
6
6
  import { IndexerManager } from '../indexer.manager';
7
7
  import { BlockContent } from '../types';
8
- export type FetchBlockResponse = {
9
- parentHash: string;
10
- } | undefined;
8
+ export type FetchBlockResponse = Header;
11
9
  export type WorkerStatusResponse = {
12
10
  threadId: number;
13
11
  isIndexing: boolean;
@@ -19,8 +17,6 @@ export declare class WorkerService extends BaseWorkerService<BlockContent, Fetch
19
17
  private indexerManager;
20
18
  constructor(apiService: ApiService<EthereumApi, SafeEthProvider, IBlock<BlockContent>[]>, indexerManager: IndexerManager, projectService: IProjectService<EthereumProjectDs>, projectUpgradeService: IProjectUpgradeService, nodeConfig: NodeConfig);
21
19
  protected fetchChainBlock(heights: number, extra: {}): Promise<IBlock<BlockContent>>;
22
- protected toBlockResponse(block: BlockContent): {
23
- parentHash: string;
24
- };
20
+ protected toBlockResponse(block: BlockContent): Header;
25
21
  protected processFetchedBlock(block: IBlock<BlockContent>, dataSources: SubqlEthereumDataSource[]): Promise<ProcessBlockResponse>;
26
22
  }
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.WorkerService = void 0;
18
18
  const common_1 = require("@nestjs/common");
19
19
  const node_core_1 = require("@subql/node-core");
20
+ const utils_ethereum_1 = require("../../ethereum/utils.ethereum");
20
21
  const indexer_manager_1 = require("../indexer.manager");
21
22
  let WorkerService = class WorkerService extends node_core_1.BaseWorkerService {
22
23
  apiService;
@@ -32,6 +33,7 @@ let WorkerService = class WorkerService extends node_core_1.BaseWorkerService {
32
33
  }
33
34
  toBlockResponse(block) {
34
35
  return {
36
+ ...(0, utils_ethereum_1.ethereumBlockToHeader)(block),
35
37
  parentHash: block.parentHash,
36
38
  };
37
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"worker.service.js","sourceRoot":"","sources":["../../../src/indexer/worker/worker.service.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;;;;;;;AAEnC,2CAAoD;AAEpD,gDAQ0B;AAI1B,wDAAoD;AAa7C,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,6BAKlC;IAEW;IAKA;IANV,YACU,UAIP,EACO,cAA8B,EAEtC,cAAkD,EAElD,qBAA6C,EAC7C,UAAsB;QAEtB,KAAK,CAAC,cAAc,EAAE,qBAAqB,EAAE,UAAU,CAAC,CAAC;QAZjD,eAAU,GAAV,UAAU,CAIjB;QACO,mBAAc,GAAd,cAAc,CAAgB;IAQxC,CAAC;IAES,KAAK,CAAC,eAAe,CAC7B,OAAe,EACf,KAAS;QAET,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAES,eAAe,CAAC,KAAmB;QAC3C,OAAO;YACL,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,mBAAmB,CACjC,KAA2B,EAC3B,WAAsC;QAEtC,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC;CACF,CAAA;AA1CY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAcR,WAAA,IAAA,eAAM,EAAC,iBAAiB,CAAC,CAAA;IAEzB,WAAA,IAAA,eAAM,EAAC,wBAAwB,CAAC,CAAA;qCARb,sBAAU;QAKN,gCAAc,kBAK1B,sBAAU;GAjBb,aAAa,CA0CzB","sourcesContent":["// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport { SubqlEthereumDataSource } from '@subql/common-ethereum';\nimport {\n NodeConfig,\n IProjectService,\n ProcessBlockResponse,\n ApiService,\n BaseWorkerService,\n IProjectUpgradeService,\n IBlock,\n} from '@subql/node-core';\nimport { EthereumProjectDs } from '../../configure/SubqueryProject';\nimport { EthereumApi } from '../../ethereum';\nimport SafeEthProvider from '../../ethereum/safe-api';\nimport { IndexerManager } from '../indexer.manager';\nimport { BlockContent } from '../types';\n\nexport type FetchBlockResponse = { parentHash: string } | undefined;\n\nexport type WorkerStatusResponse = {\n threadId: number;\n isIndexing: boolean;\n fetchedBlocks: number;\n toFetchBlocks: number;\n};\n\n@Injectable()\nexport class WorkerService extends BaseWorkerService<\n BlockContent,\n FetchBlockResponse,\n SubqlEthereumDataSource,\n {}\n> {\n constructor(\n private apiService: ApiService<\n EthereumApi,\n SafeEthProvider,\n IBlock<BlockContent>[]\n >,\n private indexerManager: IndexerManager,\n @Inject('IProjectService')\n projectService: IProjectService<EthereumProjectDs>,\n @Inject('IProjectUpgradeService')\n projectUpgradeService: IProjectUpgradeService,\n nodeConfig: NodeConfig,\n ) {\n super(projectService, projectUpgradeService, nodeConfig);\n }\n\n protected async fetchChainBlock(\n heights: number,\n extra: {},\n ): Promise<IBlock<BlockContent>> {\n const [block] = await this.apiService.fetchBlocks([heights]);\n return block;\n }\n\n protected toBlockResponse(block: BlockContent): { parentHash: string } {\n return {\n parentHash: block.parentHash,\n };\n }\n\n protected async processFetchedBlock(\n block: IBlock<BlockContent>,\n dataSources: SubqlEthereumDataSource[],\n ): Promise<ProcessBlockResponse> {\n return this.indexerManager.indexBlock(block, dataSources);\n }\n}\n"]}
1
+ {"version":3,"file":"worker.service.js","sourceRoot":"","sources":["../../../src/indexer/worker/worker.service.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;;;;;;;AAEnC,2CAAoD;AAEpD,gDAS0B;AAI1B,kEAAsE;AACtE,wDAAoD;AAa7C,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,6BAKlC;IAEW;IAKA;IANV,YACU,UAIP,EACO,cAA8B,EAEtC,cAAkD,EAElD,qBAA6C,EAC7C,UAAsB;QAEtB,KAAK,CAAC,cAAc,EAAE,qBAAqB,EAAE,UAAU,CAAC,CAAC;QAZjD,eAAU,GAAV,UAAU,CAIjB;QACO,mBAAc,GAAd,cAAc,CAAgB;IAQxC,CAAC;IAES,KAAK,CAAC,eAAe,CAC7B,OAAe,EACf,KAAS;QAET,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAES,eAAe,CAAC,KAAmB;QAC3C,OAAO;YACL,GAAG,IAAA,sCAAqB,EAAC,KAAK,CAAC;YAC/B,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,mBAAmB,CACjC,KAA2B,EAC3B,WAAsC;QAEtC,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC;CACF,CAAA;AA3CY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAcR,WAAA,IAAA,eAAM,EAAC,iBAAiB,CAAC,CAAA;IAEzB,WAAA,IAAA,eAAM,EAAC,wBAAwB,CAAC,CAAA;qCARb,sBAAU;QAKN,gCAAc,kBAK1B,sBAAU;GAjBb,aAAa,CA2CzB","sourcesContent":["// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport { SubqlEthereumDataSource } from '@subql/common-ethereum';\nimport {\n NodeConfig,\n IProjectService,\n ProcessBlockResponse,\n ApiService,\n BaseWorkerService,\n IProjectUpgradeService,\n IBlock,\n Header,\n} from '@subql/node-core';\nimport { EthereumProjectDs } from '../../configure/SubqueryProject';\nimport { EthereumApi } from '../../ethereum';\nimport SafeEthProvider from '../../ethereum/safe-api';\nimport { ethereumBlockToHeader } from '../../ethereum/utils.ethereum';\nimport { IndexerManager } from '../indexer.manager';\nimport { BlockContent } from '../types';\n\nexport type FetchBlockResponse = Header;\n\nexport type WorkerStatusResponse = {\n threadId: number;\n isIndexing: boolean;\n fetchedBlocks: number;\n toFetchBlocks: number;\n};\n\n@Injectable()\nexport class WorkerService extends BaseWorkerService<\n BlockContent,\n FetchBlockResponse,\n SubqlEthereumDataSource,\n {}\n> {\n constructor(\n private apiService: ApiService<\n EthereumApi,\n SafeEthProvider,\n IBlock<BlockContent>[]\n >,\n private indexerManager: IndexerManager,\n @Inject('IProjectService')\n projectService: IProjectService<EthereumProjectDs>,\n @Inject('IProjectUpgradeService')\n projectUpgradeService: IProjectUpgradeService,\n nodeConfig: NodeConfig,\n ) {\n super(projectService, projectUpgradeService, nodeConfig);\n }\n\n protected async fetchChainBlock(\n heights: number,\n extra: {},\n ): Promise<IBlock<BlockContent>> {\n const [block] = await this.apiService.fetchBlocks([heights]);\n return block;\n }\n\n protected toBlockResponse(block: BlockContent): Header {\n return {\n ...ethereumBlockToHeader(block),\n parentHash: block.parentHash,\n };\n }\n\n protected async processFetchedBlock(\n block: IBlock<BlockContent>,\n dataSources: SubqlEthereumDataSource[],\n ): Promise<ProcessBlockResponse> {\n return this.indexerManager.indexBlock(block, dataSources);\n }\n}\n"]}
@@ -13,6 +13,7 @@ const common_1 = require("@nestjs/common");
13
13
  const event_emitter_1 = require("@nestjs/event-emitter");
14
14
  const schedule_1 = require("@nestjs/schedule");
15
15
  const node_core_1 = require("@subql/node-core");
16
+ const x_sequelize_1 = require("@subql/x-sequelize");
16
17
  const configure_module_1 = require("../configure/configure.module");
17
18
  const ds_processor_service_1 = require("../indexer/ds-processor.service");
18
19
  const dynamic_ds_service_1 = require("../indexer/dynamic-ds.service");
@@ -23,7 +24,11 @@ exports.ReindexFeatureModule = ReindexFeatureModule;
23
24
  exports.ReindexFeatureModule = ReindexFeatureModule = __decorate([
24
25
  (0, common_1.Module)({
25
26
  providers: [
26
- node_core_1.StoreCacheService,
27
+ {
28
+ provide: 'IStoreModelProvider',
29
+ useFactory: node_core_1.storeModelFactory,
30
+ inject: [node_core_1.NodeConfig, event_emitter_1.EventEmitter2, schedule_1.SchedulerRegistry, x_sequelize_1.Sequelize],
31
+ },
27
32
  node_core_1.StoreService,
28
33
  node_core_1.ReindexService,
29
34
  node_core_1.PoiService,
@@ -1 +1 @@
1
- {"version":3,"file":"reindex.module.js","sourceRoot":"","sources":["../../src/subcommands/reindex.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA2D;AAC3D,+CAAqD;AACrD,gDAQ0B;AAC1B,oEAAgE;AAChE,0EAAqE;AACrE,sEAAiE;AACjE,oFAAgF;AA2BzE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IAzBhC,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT,6BAAiB;YACjB,wBAAY;YACZ,0BAAc;YACd,sBAAU;YACV,6BAAiB;YACjB;gBACE,OAAO,EAAE,0BAA0B;gBACnC,QAAQ,EAAE,oDAAwB;aACnC;YACD;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,QAAQ,EAAE,qCAAgB;aAC3B;YACD,yCAAkB;YAClB;gBACE,8EAA8E;gBAC9E,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,GAAG,EAAE,CAAC,SAAS;aAC5B;YACD,4BAAiB;SAClB;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,oBAAoB,CAAG;AAW7B,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IATzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,oBAAQ,CAAC,OAAO,EAAE;YAClB,kCAAe,CAAC,QAAQ,EAAE;YAC1B,oBAAoB;YACpB,kCAAkB,CAAC,OAAO,EAAE;SAC7B;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,aAAa,CAAG","sourcesContent":["// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitterModule } from '@nestjs/event-emitter';\nimport { SchedulerRegistry } from '@nestjs/schedule';\nimport {\n ApiService,\n DbModule,\n ForceCleanService,\n StoreCacheService,\n StoreService,\n ReindexService,\n PoiService,\n} from '@subql/node-core';\nimport { ConfigureModule } from '../configure/configure.module';\nimport { DsProcessorService } from '../indexer/ds-processor.service';\nimport { DynamicDsService } from '../indexer/dynamic-ds.service';\nimport { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service';\n\n@Module({\n providers: [\n StoreCacheService,\n StoreService,\n ReindexService,\n PoiService,\n ForceCleanService,\n {\n provide: 'UnfinalizedBlocksService',\n useClass: UnfinalizedBlocksService,\n },\n {\n provide: 'DynamicDsService',\n useClass: DynamicDsService,\n },\n DsProcessorService,\n {\n // Used to work with DI for unfinalizedBlocksService but not used with reindex\n provide: ApiService,\n useFactory: () => undefined,\n },\n SchedulerRegistry,\n ],\n controllers: [],\n})\nexport class ReindexFeatureModule {}\n\n@Module({\n imports: [\n DbModule.forRoot(),\n ConfigureModule.register(),\n ReindexFeatureModule,\n EventEmitterModule.forRoot(),\n ],\n controllers: [],\n})\nexport class ReindexModule {}\n"]}
1
+ {"version":3,"file":"reindex.module.js","sourceRoot":"","sources":["../../src/subcommands/reindex.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAqD;AACrD,gDAS0B;AAC1B,oDAA+C;AAC/C,oEAAgE;AAChE,0EAAqE;AACrE,sEAAiE;AACjE,oFAAgF;AA+BzE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IA7BhC,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,qBAAqB;gBAC9B,UAAU,EAAE,6BAAiB;gBAC7B,MAAM,EAAE,CAAC,sBAAU,EAAE,6BAAa,EAAE,4BAAiB,EAAE,uBAAS,CAAC;aAClE;YACD,wBAAY;YACZ,0BAAc;YACd,sBAAU;YACV,6BAAiB;YACjB;gBACE,OAAO,EAAE,0BAA0B;gBACnC,QAAQ,EAAE,oDAAwB;aACnC;YACD;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,QAAQ,EAAE,qCAAgB;aAC3B;YACD,yCAAkB;YAClB;gBACE,8EAA8E;gBAC9E,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,GAAG,EAAE,CAAC,SAAS;aAC5B;YACD,4BAAiB;SAClB;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,oBAAoB,CAAG;AAW7B,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IATzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,oBAAQ,CAAC,OAAO,EAAE;YAClB,kCAAe,CAAC,QAAQ,EAAE;YAC1B,oBAAoB;YACpB,kCAAkB,CAAC,OAAO,EAAE;SAC7B;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,aAAa,CAAG","sourcesContent":["// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';\nimport { SchedulerRegistry } from '@nestjs/schedule';\nimport {\n ApiService,\n DbModule,\n ForceCleanService,\n StoreService,\n ReindexService,\n PoiService,\n NodeConfig,\n storeModelFactory,\n} from '@subql/node-core';\nimport { Sequelize } from '@subql/x-sequelize';\nimport { ConfigureModule } from '../configure/configure.module';\nimport { DsProcessorService } from '../indexer/ds-processor.service';\nimport { DynamicDsService } from '../indexer/dynamic-ds.service';\nimport { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service';\n\n@Module({\n providers: [\n {\n provide: 'IStoreModelProvider',\n useFactory: storeModelFactory,\n inject: [NodeConfig, EventEmitter2, SchedulerRegistry, Sequelize],\n },\n StoreService,\n ReindexService,\n PoiService,\n ForceCleanService,\n {\n provide: 'UnfinalizedBlocksService',\n useClass: UnfinalizedBlocksService,\n },\n {\n provide: 'DynamicDsService',\n useClass: DynamicDsService,\n },\n DsProcessorService,\n {\n // Used to work with DI for unfinalizedBlocksService but not used with reindex\n provide: ApiService,\n useFactory: () => undefined,\n },\n SchedulerRegistry,\n ],\n controllers: [],\n})\nexport class ReindexFeatureModule {}\n\n@Module({\n imports: [\n DbModule.forRoot(),\n ConfigureModule.register(),\n ReindexFeatureModule,\n EventEmitterModule.forRoot(),\n ],\n controllers: [],\n})\nexport class ReindexModule {}\n"]}
@@ -13,6 +13,7 @@ const common_1 = require("@nestjs/common");
13
13
  const event_emitter_1 = require("@nestjs/event-emitter");
14
14
  const schedule_1 = require("@nestjs/schedule");
15
15
  const node_core_1 = require("@subql/node-core");
16
+ const x_sequelize_1 = require("@subql/x-sequelize");
16
17
  const configure_module_1 = require("../configure/configure.module");
17
18
  const ethereum_1 = require("../ethereum");
18
19
  const ds_processor_service_1 = require("../indexer/ds-processor.service");
@@ -28,7 +29,11 @@ exports.TestingFeatureModule = TestingFeatureModule = __decorate([
28
29
  providers: [
29
30
  node_core_1.InMemoryCacheService,
30
31
  node_core_1.StoreService,
31
- node_core_1.StoreCacheService,
32
+ {
33
+ provide: 'IStoreModelProvider',
34
+ useFactory: node_core_1.storeModelFactory,
35
+ inject: [node_core_1.NodeConfig, event_emitter_1.EventEmitter2, schedule_1.SchedulerRegistry, x_sequelize_1.Sequelize],
36
+ },
32
37
  event_emitter_1.EventEmitter2,
33
38
  node_core_1.PoiService,
34
39
  node_core_1.PoiSyncService,
@@ -1 +1 @@
1
- {"version":3,"file":"testing.module.js","sourceRoot":"","sources":["../../src/subcommands/testing.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAqE;AACrE,gDAa0B;AAC1B,oEAAgE;AAEhE,0CAAiD;AAEjD,0EAAqE;AACrE,sEAAiE;AACjE,gEAA4D;AAC5D,gEAA4D;AAC5D,oFAAgF;AA0DzE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IAxDhC,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT,gCAAoB;YACpB,wBAAY;YACZ,6BAAiB;YACjB,6BAAa;YACb,sBAAU;YACV,0BAAc;YACd,0BAAc;YACd,yCAAkB;YAClB,qCAAgB;YAChB,oDAAwB;YACxB,sCAA0B;YAC1B,iCAAqB;YACrB;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,gCAAc;aACzB;YACD;gBACE,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,KAAK,EACf,OAAwB,EACxB,qBAAmE,EACnE,YAA2B,EAC3B,UAAsB,EACtB,EAAE;oBACF,MAAM,UAAU,GAAG,IAAI,6BAAkB,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,4BAAiB;YACjB,sBAAU;YACV;gBACE,OAAO,EAAE,MAAM;gBACf,WAAW,EAAE,sBAAU;aACxB;YACD;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,gCAAc;aACzB;SACF;QACD,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,CAAC,sBAAU,CAAC;KACtB,CAAC;GACW,oBAAoB,CAAG;AAY7B,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IAVzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,oBAAQ,CAAC,OAAO,EAAE;YAClB,kCAAe,CAAC,QAAQ,EAAE;YAC1B,kCAAkB,CAAC,OAAO,EAAE;YAC5B,yBAAc,CAAC,OAAO,EAAE;YACxB,oBAAoB;SACrB;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,aAAa,CAAG","sourcesContent":["// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';\nimport { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule';\nimport {\n ApiService,\n ConnectionPoolService,\n ConnectionPoolStateManager,\n DbModule,\n InMemoryCacheService,\n NodeConfig,\n PoiService,\n PoiSyncService,\n StoreCacheService,\n StoreService,\n TestRunner,\n SandboxService,\n} from '@subql/node-core';\nimport { ConfigureModule } from '../configure/configure.module';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApiService } from '../ethereum';\nimport { EthereumApiConnection } from '../ethereum/api.connection';\nimport { DsProcessorService } from '../indexer/ds-processor.service';\nimport { DynamicDsService } from '../indexer/dynamic-ds.service';\nimport { IndexerManager } from '../indexer/indexer.manager';\nimport { ProjectService } from '../indexer/project.service';\nimport { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service';\n\n@Module({\n providers: [\n InMemoryCacheService,\n StoreService,\n StoreCacheService,\n EventEmitter2,\n PoiService,\n PoiSyncService,\n SandboxService,\n DsProcessorService,\n DynamicDsService,\n UnfinalizedBlocksService,\n ConnectionPoolStateManager,\n ConnectionPoolService,\n {\n provide: 'IProjectService',\n useClass: ProjectService,\n },\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 SchedulerRegistry,\n TestRunner,\n {\n provide: 'IApi',\n useExisting: ApiService,\n },\n {\n provide: 'IIndexerManager',\n useClass: IndexerManager,\n },\n ],\n controllers: [],\n exports: [TestRunner],\n})\nexport class TestingFeatureModule {}\n\n@Module({\n imports: [\n DbModule.forRoot(),\n ConfigureModule.register(),\n EventEmitterModule.forRoot(),\n ScheduleModule.forRoot(),\n TestingFeatureModule,\n ],\n controllers: [],\n})\nexport class TestingModule {}\n"]}
1
+ {"version":3,"file":"testing.module.js","sourceRoot":"","sources":["../../src/subcommands/testing.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAqE;AACrE,gDAa0B;AAC1B,oDAA+C;AAC/C,oEAAgE;AAEhE,0CAAiD;AAEjD,0EAAqE;AACrE,sEAAiE;AACjE,gEAA4D;AAC5D,gEAA4D;AAC5D,oFAAgF;AA8DzE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IA5DhC,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT,gCAAoB;YACpB,wBAAY;YACZ;gBACE,OAAO,EAAE,qBAAqB;gBAC9B,UAAU,EAAE,6BAAiB;gBAC7B,MAAM,EAAE,CAAC,sBAAU,EAAE,6BAAa,EAAE,4BAAiB,EAAE,uBAAS,CAAC;aAClE;YACD,6BAAa;YACb,sBAAU;YACV,0BAAc;YACd,0BAAc;YACd,yCAAkB;YAClB,qCAAgB;YAChB,oDAAwB;YACxB,sCAA0B;YAC1B,iCAAqB;YACrB;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,gCAAc;aACzB;YACD;gBACE,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,KAAK,EACf,OAAwB,EACxB,qBAAmE,EACnE,YAA2B,EAC3B,UAAsB,EACtB,EAAE;oBACF,MAAM,UAAU,GAAG,IAAI,6BAAkB,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,4BAAiB;YACjB,sBAAU;YACV;gBACE,OAAO,EAAE,MAAM;gBACf,WAAW,EAAE,sBAAU;aACxB;YACD;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,gCAAc;aACzB;SACF;QACD,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,CAAC,sBAAU,CAAC;KACtB,CAAC;GACW,oBAAoB,CAAG;AAY7B,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IAVzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,oBAAQ,CAAC,OAAO,EAAE;YAClB,kCAAe,CAAC,QAAQ,EAAE;YAC1B,kCAAkB,CAAC,OAAO,EAAE;YAC5B,yBAAc,CAAC,OAAO,EAAE;YACxB,oBAAoB;SACrB;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,aAAa,CAAG","sourcesContent":["// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';\nimport { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule';\nimport {\n ApiService,\n ConnectionPoolService,\n ConnectionPoolStateManager,\n DbModule,\n InMemoryCacheService,\n NodeConfig,\n PoiService,\n PoiSyncService,\n StoreService,\n TestRunner,\n SandboxService,\n storeModelFactory,\n} from '@subql/node-core';\nimport { Sequelize } from '@subql/x-sequelize';\nimport { ConfigureModule } from '../configure/configure.module';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApiService } from '../ethereum';\nimport { EthereumApiConnection } from '../ethereum/api.connection';\nimport { DsProcessorService } from '../indexer/ds-processor.service';\nimport { DynamicDsService } from '../indexer/dynamic-ds.service';\nimport { IndexerManager } from '../indexer/indexer.manager';\nimport { ProjectService } from '../indexer/project.service';\nimport { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service';\n\n@Module({\n providers: [\n InMemoryCacheService,\n StoreService,\n {\n provide: 'IStoreModelProvider',\n useFactory: storeModelFactory,\n inject: [NodeConfig, EventEmitter2, SchedulerRegistry, Sequelize],\n },\n EventEmitter2,\n PoiService,\n PoiSyncService,\n SandboxService,\n DsProcessorService,\n DynamicDsService,\n UnfinalizedBlocksService,\n ConnectionPoolStateManager,\n ConnectionPoolService,\n {\n provide: 'IProjectService',\n useClass: ProjectService,\n },\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 SchedulerRegistry,\n TestRunner,\n {\n provide: 'IApi',\n useExisting: ApiService,\n },\n {\n provide: 'IIndexerManager',\n useClass: IndexerManager,\n },\n ],\n controllers: [],\n exports: [TestRunner],\n})\nexport class TestingFeatureModule {}\n\n@Module({\n imports: [\n DbModule.forRoot(),\n ConfigureModule.register(),\n EventEmitterModule.forRoot(),\n ScheduleModule.forRoot(),\n TestingFeatureModule,\n ],\n controllers: [],\n})\nexport class TestingModule {}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subql/node-ethereum",
3
- "version": "5.1.7",
3
+ "version": "5.2.0",
4
4
  "description": "",
5
5
  "author": "Ian He",
6
6
  "license": "GPL-3.0",
@@ -24,9 +24,9 @@
24
24
  "@nestjs/event-emitter": "^2.0.0",
25
25
  "@nestjs/platform-express": "^9.4.0",
26
26
  "@nestjs/schedule": "^3.0.1",
27
- "@subql/common": "^5.1.4",
28
- "@subql/common-ethereum": "4.5.4",
29
- "@subql/node-core": "^14.1.6",
27
+ "@subql/common": "^5.2.1",
28
+ "@subql/common-ethereum": "4.5.5",
29
+ "@subql/node-core": "^15.0.3",
30
30
  "@subql/testing": "^2.2.1",
31
31
  "@subql/types-ethereum": "4.0.0",
32
32
  "cacheable-lookup": "6",