@subql/node-ethereum 2.9.3-1 → 2.9.3-3

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.
@@ -75,6 +75,39 @@ describe('Api.ethereum', () => {
75
75
  expect(result[0].hash).toBe('0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05');
76
76
  expect(result.length).toBe(1);
77
77
  });
78
+ it('!null filter support for logs, expect to filter out', async () => {
79
+ const beamEndpoint = 'https://rpc.api.moonbeam.network';
80
+ ethApi = new api_ethereum_1.EthereumApi(beamEndpoint, eventEmitter);
81
+ await ethApi.init();
82
+ const filter_1 = {
83
+ topics: [
84
+ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
85
+ undefined,
86
+ undefined,
87
+ '!null',
88
+ ],
89
+ };
90
+ const filter_2 = {
91
+ topics: [
92
+ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
93
+ ],
94
+ };
95
+ blockData = await ethApi.fetchBlock(4015990, true);
96
+ const transaction = blockData.transactions.find((tx) => tx.hash ===
97
+ '0xeb2e443f2d4e784193fa13bbbae2b85e6ee459e7b7b53f8ca098ffae9b25b059');
98
+ const erc20Transfers = transaction.logs.filter((log) => {
99
+ if (block_ethereum_1.EthereumBlockWrapped.filterLogsProcessor(log, filter_2)) {
100
+ return log;
101
+ }
102
+ });
103
+ const erc721Transfers = transaction.logs.filter((log) => {
104
+ if (block_ethereum_1.EthereumBlockWrapped.filterLogsProcessor(log, filter_1)) {
105
+ return log;
106
+ }
107
+ });
108
+ expect(erc20Transfers.length).toBe(7);
109
+ expect(erc721Transfers.length).toBe(2);
110
+ });
78
111
  it('Null filter support, for undefined transaction.to', async () => {
79
112
  const beamEndpoint = 'https://rpc.api.moonbeam.network';
80
113
  ethApi = new api_ethereum_1.EthereumApi(beamEndpoint, eventEmitter);
@@ -1 +1 @@
1
- {"version":3,"file":"api.ethereum.test.js","sourceRoot":"","sources":["../../src/ethereum/api.ethereum.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2022 OnFinality Limited authors & contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport path from 'path';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport {\n EthereumDatasourceKind,\n EthereumHandlerKind,\n SubqlRuntimeDatasource,\n} from '@subql/types-ethereum';\nimport { EthereumApi } from './api.ethereum';\nimport { EthereumBlockWrapped } from './block.ethereum';\n\n// Add api key to work\nconst HTTP_ENDPOINT = 'https://eth.api.onfinality.io/public';\n\nconst ds: SubqlRuntimeDatasource = {\n mapping: {\n file: '',\n handlers: [\n {\n handler: 'test',\n kind: EthereumHandlerKind.Call,\n filter: { function: '0x23b872dd' },\n },\n ],\n },\n kind: EthereumDatasourceKind.Runtime,\n startBlock: 16258633,\n options: { abi: 'erc721' },\n assets: {\n erc721: { file: path.join(__dirname, '../../test/erc721.json') },\n } as unknown as Map<string, { file: string }>,\n};\n\njest.setTimeout(90000);\ndescribe('Api.ethereum', () => {\n let ethApi: EthereumApi;\n const eventEmitter = new EventEmitter2();\n let blockData: EthereumBlockWrapped;\n beforeEach(async () => {\n ethApi = new EthereumApi(HTTP_ENDPOINT, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(16258633, true);\n });\n\n it('Should format transaction in logs, and the transaction gas should be bigInt type', () => {\n expect(typeof blockData.logs[0].transaction.gas).toBe('bigint');\n expect(typeof blockData.logs[0].transaction.blockNumber).toBe('number');\n expect(typeof blockData.logs[0].transaction.gasPrice).toBe('bigint');\n expect(typeof blockData.logs[0].transaction.maxPriorityFeePerGas).toBe(\n 'bigint',\n );\n expect(typeof blockData.logs[0].transaction.transactionIndex).toBe(\n 'bigint',\n );\n });\n\n it('Decode nested logs in transactions', async () => {\n // Erc721\n const tx = blockData.transactions.find(\n (e) =>\n e.hash ===\n '0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc',\n );\n const parsedTx = await ethApi.parseTransaction(tx, ds);\n expect(parsedTx.logs[0].args).toBeTruthy();\n });\n\n it('Should return raw logs, if decode fails', async () => {\n // not Erc721\n const tx = blockData.transactions.find(\n (e) =>\n e.hash ===\n '0xed62f7a7720fe6ae05dec45ad9dd4f53034a0aae2c140d229b1151504ee9a6c9',\n );\n const parsedLog = await ethApi.parseLog(tx.logs[0], ds);\n expect(parsedLog).not.toHaveProperty('args');\n expect(parsedLog).toBeTruthy();\n });\n it('Null filter support', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: null },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result[0].hash).toBe(\n '0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05',\n );\n expect(result.length).toBe(1);\n });\n it('Null filter support, for undefined transaction.to', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n blockData.transactions[1].to = undefined;\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: null },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result[0].hash).toBe(\n '0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05',\n );\n expect(result.length).toBe(1);\n });\n\n it('Should return all tx if filter.to is not defined', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n undefined,\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(2);\n });\n\n it('filter.to Should support only null not undefined', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: undefined },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(0);\n });\n it('If transaction is undefined, with null filter, should be supported', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n tx.to = undefined;\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: null },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(2);\n });\n\n it('Resolves the correct tags for finalization', async () => {\n // Ethereum\n expect((ethApi as any).supportsFinalization).toBeTruthy();\n\n // Moonbeam\n ethApi = new EthereumApi('https://rpc.api.moonbeam.network', eventEmitter);\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalization).toBeTruthy();\n\n // BSC\n ethApi = new EthereumApi('https://bsc-dataseed.binance.org', eventEmitter);\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalized).toBeFalsy();\n\n // Polygon\n ethApi = new EthereumApi(\n 'https://polygon.api.onfinality.io/public',\n eventEmitter,\n );\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalized).toBeFalsy();\n });\n});\n"]}
1
+ {"version":3,"file":"api.ethereum.test.js","sourceRoot":"","sources":["../../src/ethereum/api.ethereum.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2022 OnFinality Limited authors & contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport path from 'path';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport {\n EthereumDatasourceKind,\n EthereumHandlerKind,\n EthereumLogFilter,\n SubqlRuntimeDatasource,\n} from '@subql/types-ethereum';\nimport { EthereumApi } from './api.ethereum';\nimport { EthereumBlockWrapped } from './block.ethereum';\n\n// Add api key to work\nconst HTTP_ENDPOINT = 'https://eth.api.onfinality.io/public';\n\nconst ds: SubqlRuntimeDatasource = {\n mapping: {\n file: '',\n handlers: [\n {\n handler: 'test',\n kind: EthereumHandlerKind.Call,\n filter: { function: '0x23b872dd' },\n },\n ],\n },\n kind: EthereumDatasourceKind.Runtime,\n startBlock: 16258633,\n options: { abi: 'erc721' },\n assets: {\n erc721: { file: path.join(__dirname, '../../test/erc721.json') },\n } as unknown as Map<string, { file: string }>,\n};\n\njest.setTimeout(90000);\ndescribe('Api.ethereum', () => {\n let ethApi: EthereumApi;\n const eventEmitter = new EventEmitter2();\n let blockData: EthereumBlockWrapped;\n beforeEach(async () => {\n ethApi = new EthereumApi(HTTP_ENDPOINT, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(16258633, true);\n });\n\n it('Should format transaction in logs, and the transaction gas should be bigInt type', () => {\n expect(typeof blockData.logs[0].transaction.gas).toBe('bigint');\n expect(typeof blockData.logs[0].transaction.blockNumber).toBe('number');\n expect(typeof blockData.logs[0].transaction.gasPrice).toBe('bigint');\n expect(typeof blockData.logs[0].transaction.maxPriorityFeePerGas).toBe(\n 'bigint',\n );\n expect(typeof blockData.logs[0].transaction.transactionIndex).toBe(\n 'bigint',\n );\n });\n\n it('Decode nested logs in transactions', async () => {\n // Erc721\n const tx = blockData.transactions.find(\n (e) =>\n e.hash ===\n '0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc',\n );\n const parsedTx = await ethApi.parseTransaction(tx, ds);\n expect(parsedTx.logs[0].args).toBeTruthy();\n });\n\n it('Should return raw logs, if decode fails', async () => {\n // not Erc721\n const tx = blockData.transactions.find(\n (e) =>\n e.hash ===\n '0xed62f7a7720fe6ae05dec45ad9dd4f53034a0aae2c140d229b1151504ee9a6c9',\n );\n const parsedLog = await ethApi.parseLog(tx.logs[0], ds);\n expect(parsedLog).not.toHaveProperty('args');\n expect(parsedLog).toBeTruthy();\n });\n it('Null filter support', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: null },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result[0].hash).toBe(\n '0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05',\n );\n expect(result.length).toBe(1);\n });\n\n it('!null filter support for logs, expect to filter out', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n const filter_1: EthereumLogFilter = {\n topics: [\n '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',\n undefined,\n undefined,\n '!null',\n ],\n };\n\n const filter_2: EthereumLogFilter = {\n topics: [\n '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',\n ],\n };\n\n blockData = await ethApi.fetchBlock(4015990, true);\n const transaction = blockData.transactions.find(\n (tx) =>\n tx.hash ===\n '0xeb2e443f2d4e784193fa13bbbae2b85e6ee459e7b7b53f8ca098ffae9b25b059',\n );\n const erc20Transfers = transaction.logs.filter((log) => {\n if (EthereumBlockWrapped.filterLogsProcessor(log, filter_2)) {\n return log;\n }\n });\n const erc721Transfers = transaction.logs.filter((log) => {\n if (EthereumBlockWrapped.filterLogsProcessor(log, filter_1)) {\n return log;\n }\n });\n\n expect(erc20Transfers.length).toBe(7);\n expect(erc721Transfers.length).toBe(2);\n });\n\n it('Null filter support, for undefined transaction.to', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n blockData.transactions[1].to = undefined;\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: null },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result[0].hash).toBe(\n '0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05',\n );\n expect(result.length).toBe(1);\n });\n\n it('Should return all tx if filter.to is not defined', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n undefined,\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(2);\n });\n\n it('filter.to Should support only null not undefined', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: undefined },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(0);\n });\n it('If transaction is undefined, with null filter, should be supported', async () => {\n const beamEndpoint = 'https://rpc.api.moonbeam.network';\n ethApi = new EthereumApi(beamEndpoint, eventEmitter);\n await ethApi.init();\n blockData = await ethApi.fetchBlock(2847447, true);\n const result = blockData.transactions.filter((tx) => {\n tx.to = undefined;\n if (\n EthereumBlockWrapped.filterTransactionsProcessor(\n tx,\n { to: null },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(2);\n });\n\n it('Resolves the correct tags for finalization', async () => {\n // Ethereum\n expect((ethApi as any).supportsFinalization).toBeTruthy();\n\n // Moonbeam\n ethApi = new EthereumApi('https://rpc.api.moonbeam.network', eventEmitter);\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalization).toBeTruthy();\n\n // BSC\n ethApi = new EthereumApi('https://bsc-dataseed.binance.org', eventEmitter);\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalized).toBeFalsy();\n\n // Polygon\n ethApi = new EthereumApi(\n 'https://polygon.api.onfinality.io/public',\n eventEmitter,\n );\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalized).toBeFalsy();\n });\n});\n"]}
@@ -79,6 +79,9 @@ class EthereumBlockWrapped {
79
79
  if (!log.topics[i]) {
80
80
  return false;
81
81
  }
82
+ if (topic === '!null') {
83
+ return true;
84
+ }
82
85
  if (!(0, string_1.hexStringEq)((0, string_1.eventToTopic)(topic), log.topics[i])) {
83
86
  return false;
84
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"block.ethereum.js","sourceRoot":"","sources":["../../src/ethereum/block.ethereum.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2022 OnFinality Limited authors & contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EthereumBlock,\n EthereumTransactionFilter,\n EthereumLog,\n EthereumLogFilter,\n EthereumBlockFilter,\n EthereumBlockWrapper,\n EthereumTransaction,\n} from '@subql/types-ethereum';\nimport {\n eventToTopic,\n functionToSighash,\n hexStringEq,\n stringNormalizedEq,\n} from '../utils/string';\n\nexport class EthereumBlockWrapped implements EthereumBlockWrapper {\n constructor(\n private _block: EthereumBlock,\n private _txs: EthereumTransaction[],\n private _logs: EthereumLog[],\n ) {\n this._block.transactions = this._txs;\n this._block.logs = this._logs;\n\n // Set logs on tx\n this._logs.forEach((l) => {\n const tx = this._txs.find((tx) => tx.hash === l.transactionHash);\n\n if (!tx) return;\n tx.logs = tx.logs ? [...tx.logs, l] : [l];\n });\n }\n\n get block(): EthereumBlock {\n return this._block;\n }\n\n get blockHeight(): number {\n return this.block.number;\n }\n\n get hash(): string {\n return this.block.hash;\n }\n\n get transactions(): EthereumTransaction[] {\n return this._txs;\n }\n\n get logs(): EthereumLog[] {\n return this._logs;\n }\n\n static filterBlocksProcessor(\n block: EthereumBlock,\n filter: EthereumBlockFilter,\n address?: string,\n ): boolean {\n if (filter?.modulo && block.number % filter.modulo !== 0) {\n return false;\n }\n return true;\n }\n\n static filterTransactionsProcessor(\n transaction: EthereumTransaction,\n filter: EthereumTransactionFilter,\n address?: string,\n ): boolean {\n if (!filter) return true;\n\n if (\n filter.to === null &&\n !(transaction.to === null || transaction.to === undefined)\n ) {\n return false;\n }\n\n if (filter.to && !stringNormalizedEq(filter.to, transaction.to)) {\n return false;\n }\n if (filter.from && !stringNormalizedEq(filter.from, transaction.from)) {\n return false;\n }\n if (\n address &&\n filter.to === undefined &&\n !stringNormalizedEq(address, transaction.to)\n ) {\n return false;\n }\n if (\n filter.function &&\n transaction.input.indexOf(functionToSighash(filter.function)) !== 0\n ) {\n return false;\n }\n return true;\n }\n\n static filterLogsProcessor(\n log: EthereumLog,\n filter: EthereumLogFilter,\n address?: string,\n ): boolean {\n if (address && !stringNormalizedEq(address, log.address)) {\n return false;\n }\n\n if (!filter) return true;\n\n if (filter.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n\n if (!log.topics[i]) {\n return false;\n }\n if (!hexStringEq(eventToTopic(topic), log.topics[i])) {\n return false;\n }\n }\n }\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"block.ethereum.js","sourceRoot":"","sources":["../../src/ethereum/block.ethereum.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2022 OnFinality Limited authors & contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EthereumBlock,\n EthereumTransactionFilter,\n EthereumLog,\n EthereumLogFilter,\n EthereumBlockFilter,\n EthereumBlockWrapper,\n EthereumTransaction,\n} from '@subql/types-ethereum';\nimport {\n eventToTopic,\n functionToSighash,\n hexStringEq,\n stringNormalizedEq,\n} from '../utils/string';\n\nexport class EthereumBlockWrapped implements EthereumBlockWrapper {\n constructor(\n private _block: EthereumBlock,\n private _txs: EthereumTransaction[],\n private _logs: EthereumLog[],\n ) {\n this._block.transactions = this._txs;\n this._block.logs = this._logs;\n\n // Set logs on tx\n this._logs.forEach((l) => {\n const tx = this._txs.find((tx) => tx.hash === l.transactionHash);\n\n if (!tx) return;\n tx.logs = tx.logs ? [...tx.logs, l] : [l];\n });\n }\n\n get block(): EthereumBlock {\n return this._block;\n }\n\n get blockHeight(): number {\n return this.block.number;\n }\n\n get hash(): string {\n return this.block.hash;\n }\n\n get transactions(): EthereumTransaction[] {\n return this._txs;\n }\n\n get logs(): EthereumLog[] {\n return this._logs;\n }\n\n static filterBlocksProcessor(\n block: EthereumBlock,\n filter: EthereumBlockFilter,\n address?: string,\n ): boolean {\n if (filter?.modulo && block.number % filter.modulo !== 0) {\n return false;\n }\n return true;\n }\n\n static filterTransactionsProcessor(\n transaction: EthereumTransaction,\n filter: EthereumTransactionFilter,\n address?: string,\n ): boolean {\n if (!filter) return true;\n\n if (\n filter.to === null &&\n !(transaction.to === null || transaction.to === undefined)\n ) {\n return false;\n }\n\n if (filter.to && !stringNormalizedEq(filter.to, transaction.to)) {\n return false;\n }\n if (filter.from && !stringNormalizedEq(filter.from, transaction.from)) {\n return false;\n }\n if (\n address &&\n filter.to === undefined &&\n !stringNormalizedEq(address, transaction.to)\n ) {\n return false;\n }\n if (\n filter.function &&\n transaction.input.indexOf(functionToSighash(filter.function)) !== 0\n ) {\n return false;\n }\n return true;\n }\n\n static filterLogsProcessor(\n log: EthereumLog,\n filter: EthereumLogFilter,\n address?: string,\n ): boolean {\n if (address && !stringNormalizedEq(address, log.address)) {\n return false;\n }\n\n if (!filter) return true;\n\n if (filter.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n\n if (!log.topics[i]) {\n return false;\n }\n\n if (topic === '!null') {\n return true;\n }\n\n if (!hexStringEq(eventToTopic(topic), log.topics[i])) {\n return false;\n }\n }\n }\n return true;\n }\n}\n"]}
@@ -3,6 +3,10 @@ import { JsonRpcProvider } from '@ethersproject/providers';
3
3
  import { Networkish } from '@ethersproject/networks';
4
4
  import { ConnectionInfo } from './web';
5
5
  export declare class JsonRpcBatchProvider extends JsonRpcProvider {
6
+ private batchSize;
7
+ private successfulBatchCount;
8
+ private failedBatchCount;
9
+ private batchSizeAdjustmentInterval;
6
10
  _pendingBatchAggregator: NodeJS.Timer;
7
11
  _pendingBatch: Array<{
8
12
  request: {
@@ -16,7 +20,9 @@ export declare class JsonRpcBatchProvider extends JsonRpcProvider {
16
20
  }>;
17
21
  _chainIdCache: string | null;
18
22
  constructor(url: string | ConnectionInfo, network?: Networkish);
23
+ setBatchSize(batchSize: number): void;
19
24
  send(method: string, params: Array<any>): Promise<any>;
20
25
  flush(): void;
21
26
  private runRequests;
27
+ private adjustBatchSize;
22
28
  }
@@ -11,8 +11,15 @@ const logger = (0, node_core_1.getLogger)('JsonRpcBatchProvider');
11
11
  class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
12
12
  constructor(url, network) {
13
13
  super(url, network);
14
+ this.batchSize = 1;
15
+ this.successfulBatchCount = 0;
16
+ this.failedBatchCount = 0;
17
+ this.batchSizeAdjustmentInterval = 10; // Adjust batch size after every 10 batches
14
18
  this._chainIdCache = null;
15
19
  }
20
+ setBatchSize(batchSize) {
21
+ this.batchSize = batchSize;
22
+ }
16
23
  send(method, params) {
17
24
  if (method === 'eth_chainId' && this._chainIdCache !== null) {
18
25
  return Promise.resolve(this._chainIdCache);
@@ -38,7 +45,7 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
38
45
  this.runRequests();
39
46
  }, 1);
40
47
  }
41
- if (this._pendingBatch.length > 10) {
48
+ if (this._pendingBatch.length > this.batchSize) {
42
49
  this.flush();
43
50
  }
44
51
  return promise;
@@ -64,6 +71,7 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
64
71
  });
65
72
  return (0, web_1.fetchJson)(this.connection, JSON.stringify(request))
66
73
  .then((result) => {
74
+ var _a;
67
75
  this.emit('debug', {
68
76
  action: 'response',
69
77
  request: request,
@@ -79,6 +87,9 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
79
87
  batch.forEach((inflightRequest) => {
80
88
  inflightRequest.reject(error);
81
89
  });
90
+ if (((_a = result.error) === null || _a === void 0 ? void 0 : _a.message) === 'Batch size is too large') {
91
+ this.adjustBatchSize(false);
92
+ }
82
93
  return;
83
94
  }
84
95
  // BSC returns a 200 response with this when being rate limited, we need a special case for it
@@ -99,6 +110,7 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
99
110
  var _a;
100
111
  inflightRequest.reject(new Error((_a = result[0].error) === null || _a === void 0 ? void 0 : _a.message));
101
112
  });
113
+ this.adjustBatchSize(false);
102
114
  return;
103
115
  }
104
116
  const resultMap = result.reduce((resultMap, payload) => {
@@ -116,6 +128,13 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
116
128
  const error = new Error(payload.error.message);
117
129
  error.code = payload.error.code;
118
130
  error.data = payload.error.data;
131
+ if (payload.error.message === 'Batch size limit exceeded' || // onfinality
132
+ payload.error.message === 'exceeded project rate limit' || // infura
133
+ payload.error.message.includes('Failed to buffer the request body') ||
134
+ payload.error.message.includes('Too Many Requests') ||
135
+ payload.error.message.includes('Request Entity Too Large')) {
136
+ this.adjustBatchSize(false);
137
+ }
119
138
  inflightRequest.reject(error);
120
139
  }
121
140
  else {
@@ -125,6 +144,7 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
125
144
  inflightRequest.resolve(payload.result);
126
145
  }
127
146
  });
147
+ this.adjustBatchSize(true);
128
148
  })
129
149
  .catch((error) => {
130
150
  this.emit('debug', {
@@ -137,8 +157,26 @@ class JsonRpcBatchProvider extends providers_1.JsonRpcProvider {
137
157
  batch.forEach((inflightRequest) => {
138
158
  inflightRequest.reject(error);
139
159
  });
160
+ //this.adjustBatchSize(false);
140
161
  });
141
162
  }
163
+ adjustBatchSize(success) {
164
+ success ? this.successfulBatchCount++ : this.failedBatchCount++;
165
+ const totalBatches = this.successfulBatchCount + this.failedBatchCount;
166
+ if (totalBatches % this.batchSizeAdjustmentInterval === 0) {
167
+ const successRate = this.successfulBatchCount / totalBatches;
168
+ // Adjust the batch size based on the success rate.
169
+ if (successRate < 0.9 && this.batchSize > 1) {
170
+ this.batchSize--;
171
+ }
172
+ else if (successRate > 0.95 && this.batchSize < 10) {
173
+ this.batchSize++;
174
+ }
175
+ // Reset the counters
176
+ this.successfulBatchCount = 0;
177
+ this.failedBatchCount = 0;
178
+ }
179
+ }
142
180
  }
143
181
  exports.JsonRpcBatchProvider = JsonRpcBatchProvider;
144
182
  //# sourceMappingURL=json-rpc-batch-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-rpc-batch-provider.js","sourceRoot":"","sources":["../../../src/ethereum/ethers/json-rpc-batch-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable */\nimport { deepCopy } from '@ethersproject/properties';\n\nimport { JsonRpcProvider } from '@ethersproject/providers';\nimport { Networkish } from '@ethersproject/networks';\nimport { ConnectionInfo, fetchJson } from './web';\nimport { getLogger } from '@subql/node-core';\n\nconst logger = getLogger('JsonRpcBatchProvider');\n\ninterface RpcResult {\n jsonrpc: '2.0';\n id: number;\n result?: string;\n error?: {\n code: number;\n message: string;\n data?: any;\n };\n}\n\n// Experimental\n\nexport class JsonRpcBatchProvider extends JsonRpcProvider {\n _pendingBatchAggregator: NodeJS.Timer;\n _pendingBatch: Array<{\n request: { method: string; params: Array<any>; id: number; jsonrpc: '2.0' };\n resolve: (result: any) => void;\n reject: (error: Error) => void;\n }>;\n\n _chainIdCache: string | null = null;\n\n constructor(url: string | ConnectionInfo, network?: Networkish) {\n super(url, network);\n }\n\n send(method: string, params: Array<any>): Promise<any> {\n if (method === 'eth_chainId' && this._chainIdCache !== null) {\n return Promise.resolve(this._chainIdCache);\n }\n\n const request = {\n method: method,\n params: params,\n id: this._nextId++,\n jsonrpc: '2.0',\n };\n\n if (this._pendingBatch == null) {\n this._pendingBatch = [];\n }\n\n const inflightRequest: any = { request, resolve: null, reject: null };\n\n const promise = new Promise((resolve, reject) => {\n inflightRequest.resolve = resolve;\n inflightRequest.reject = reject;\n });\n\n this._pendingBatch.push(inflightRequest);\n\n if (!this._pendingBatchAggregator) {\n // Schedule batch for next event loop + short duration\n this._pendingBatchAggregator = setTimeout(() => {\n this.runRequests();\n }, 1);\n }\n\n if (this._pendingBatch.length > 10) {\n this.flush();\n }\n\n return promise;\n }\n\n flush(): void {\n if (this._pendingBatchAggregator) {\n clearTimeout(this._pendingBatchAggregator);\n this.runRequests();\n }\n }\n\n private runRequests() {\n // Get teh current batch and clear it, so new requests\n // go into the next batch\n const batch = this._pendingBatch;\n this._pendingBatch = null;\n this._pendingBatchAggregator = null;\n\n // Get the request as an array of requests\n const request = batch.map((inflight) => inflight.request);\n\n this.emit('debug', {\n action: 'requestBatch',\n request: deepCopy(request),\n provider: this,\n });\n\n return fetchJson(this.connection, JSON.stringify(request))\n .then((result: RpcResult[]) => {\n this.emit('debug', {\n action: 'response',\n request: request,\n response: result,\n provider: this,\n });\n\n // if (!Array.isArray(result)) {\n // result = [result];\n // }\n\n // https://github.com/ethers-io/ethers.js/pull/2657\n if (!Array.isArray(result)) {\n const error = new Error(\n 'Invalid response \\n' + JSON.stringify(result),\n );\n batch.forEach((inflightRequest) => {\n inflightRequest.reject(error);\n });\n return;\n }\n\n // BSC returns a 200 response with this when being rate limited, we need a special case for it\n /*\n [\n {\n jsonrpc: '2.0',\n id: null,\n error: {\n code: -32005,\n message: 'method eth_getLogs in batch triggered rate limit'\n }\n }\n ]\n */\n if (result.length === 1 && result[0].id === null) {\n batch.forEach((inflightRequest) => {\n inflightRequest.reject(new Error(result[0].error?.message));\n });\n return;\n }\n\n const resultMap = result.reduce((resultMap, payload) => {\n resultMap[payload.id] = payload;\n return resultMap;\n }, {} as Record<number, RpcResult>);\n\n // For each result, feed it to the correct Promise, depending\n // on whether it was a success or error\n batch.forEach((inflightRequest) => {\n const payload = resultMap[inflightRequest.request.id];\n if (!payload) {\n inflightRequest.reject(\n new Error(\n `Missing payload in response for request ${inflightRequest.request.id}`,\n ),\n );\n } else if (payload.error) {\n const error = new Error(payload.error.message);\n (<any>error).code = payload.error.code;\n (<any>error).data = payload.error.data;\n inflightRequest.reject(error);\n } else {\n if (inflightRequest.request.method === 'eth_chainId') {\n this._chainIdCache = payload.result;\n }\n inflightRequest.resolve(payload.result);\n }\n });\n })\n .catch((error) => {\n this.emit('debug', {\n action: 'response',\n error: error,\n request: request,\n provider: this,\n });\n\n //logger.error(error);\n\n batch.forEach((inflightRequest) => {\n inflightRequest.reject(error);\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"json-rpc-batch-provider.js","sourceRoot":"","sources":["../../../src/ethereum/ethers/json-rpc-batch-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable */\nimport { deepCopy } from '@ethersproject/properties';\n\nimport { JsonRpcProvider } from '@ethersproject/providers';\nimport { Networkish } from '@ethersproject/networks';\nimport { ConnectionInfo, fetchJson } from './web';\nimport { getLogger } from '@subql/node-core';\n\nconst logger = getLogger('JsonRpcBatchProvider');\n\ninterface RpcResult {\n jsonrpc: '2.0';\n id: number;\n result?: string;\n error?: {\n code: number;\n message: string;\n data?: any;\n };\n}\n\n// Experimental\n\nexport class JsonRpcBatchProvider extends JsonRpcProvider {\n private batchSize = 1;\n private successfulBatchCount = 0;\n private failedBatchCount = 0;\n private batchSizeAdjustmentInterval = 10; // Adjust batch size after every 10 batches\n\n _pendingBatchAggregator: NodeJS.Timer;\n _pendingBatch: Array<{\n request: { method: string; params: Array<any>; id: number; jsonrpc: '2.0' };\n resolve: (result: any) => void;\n reject: (error: Error) => void;\n }>;\n\n _chainIdCache: string | null = null;\n\n constructor(url: string | ConnectionInfo, network?: Networkish) {\n super(url, network);\n }\n\n setBatchSize(batchSize: number) {\n this.batchSize = batchSize;\n }\n\n send(method: string, params: Array<any>): Promise<any> {\n if (method === 'eth_chainId' && this._chainIdCache !== null) {\n return Promise.resolve(this._chainIdCache);\n }\n\n const request = {\n method: method,\n params: params,\n id: this._nextId++,\n jsonrpc: '2.0',\n };\n\n if (this._pendingBatch == null) {\n this._pendingBatch = [];\n }\n\n const inflightRequest: any = { request, resolve: null, reject: null };\n\n const promise = new Promise((resolve, reject) => {\n inflightRequest.resolve = resolve;\n inflightRequest.reject = reject;\n });\n\n this._pendingBatch.push(inflightRequest);\n\n if (!this._pendingBatchAggregator) {\n // Schedule batch for next event loop + short duration\n this._pendingBatchAggregator = setTimeout(() => {\n this.runRequests();\n }, 1);\n }\n\n if (this._pendingBatch.length > this.batchSize) {\n this.flush();\n }\n\n return promise;\n }\n\n flush(): void {\n if (this._pendingBatchAggregator) {\n clearTimeout(this._pendingBatchAggregator);\n this.runRequests();\n }\n }\n\n private runRequests() {\n // Get teh current batch and clear it, so new requests\n // go into the next batch\n const batch = this._pendingBatch;\n this._pendingBatch = null;\n this._pendingBatchAggregator = null;\n\n // Get the request as an array of requests\n const request = batch.map((inflight) => inflight.request);\n\n this.emit('debug', {\n action: 'requestBatch',\n request: deepCopy(request),\n provider: this,\n });\n\n return fetchJson(this.connection, JSON.stringify(request))\n .then((result: RpcResult[]) => {\n this.emit('debug', {\n action: 'response',\n request: request,\n response: result,\n provider: this,\n });\n\n // if (!Array.isArray(result)) {\n // result = [result];\n // }\n\n // https://github.com/ethers-io/ethers.js/pull/2657\n if (!Array.isArray(result)) {\n const error = new Error(\n 'Invalid response \\n' + JSON.stringify(result),\n );\n batch.forEach((inflightRequest) => {\n inflightRequest.reject(error);\n });\n if (\n (result as RpcResult).error?.message === 'Batch size is too large'\n ) {\n this.adjustBatchSize(false);\n }\n return;\n }\n\n // BSC returns a 200 response with this when being rate limited, we need a special case for it\n /*\n [\n {\n jsonrpc: '2.0',\n id: null,\n error: {\n code: -32005,\n message: 'method eth_getLogs in batch triggered rate limit'\n }\n }\n ]\n */\n if (result.length === 1 && result[0].id === null) {\n batch.forEach((inflightRequest) => {\n inflightRequest.reject(new Error(result[0].error?.message));\n });\n this.adjustBatchSize(false);\n return;\n }\n\n const resultMap = result.reduce((resultMap, payload) => {\n resultMap[payload.id] = payload;\n return resultMap;\n }, {} as Record<number, RpcResult>);\n\n // For each result, feed it to the correct Promise, depending\n // on whether it was a success or error\n batch.forEach((inflightRequest) => {\n const payload = resultMap[inflightRequest.request.id];\n if (!payload) {\n inflightRequest.reject(\n new Error(\n `Missing payload in response for request ${inflightRequest.request.id}`,\n ),\n );\n } else if (payload.error) {\n const error = new Error(payload.error.message);\n (<any>error).code = payload.error.code;\n (<any>error).data = payload.error.data;\n if (\n payload.error.message === 'Batch size limit exceeded' || // onfinality\n payload.error.message === 'exceeded project rate limit' || // infura\n payload.error.message.includes(\n 'Failed to buffer the request body',\n ) ||\n payload.error.message.includes('Too Many Requests') ||\n payload.error.message.includes('Request Entity Too Large')\n ) {\n this.adjustBatchSize(false);\n }\n inflightRequest.reject(error);\n } else {\n if (inflightRequest.request.method === 'eth_chainId') {\n this._chainIdCache = payload.result;\n }\n inflightRequest.resolve(payload.result);\n }\n });\n\n this.adjustBatchSize(true);\n })\n .catch((error) => {\n this.emit('debug', {\n action: 'response',\n error: error,\n request: request,\n provider: this,\n });\n\n //logger.error(error);\n\n batch.forEach((inflightRequest) => {\n inflightRequest.reject(error);\n });\n\n //this.adjustBatchSize(false);\n });\n }\n\n private adjustBatchSize(success: boolean) {\n success ? this.successfulBatchCount++ : this.failedBatchCount++;\n const totalBatches = this.successfulBatchCount + this.failedBatchCount;\n\n if (totalBatches % this.batchSizeAdjustmentInterval === 0) {\n const successRate = this.successfulBatchCount / totalBatches;\n\n // Adjust the batch size based on the success rate.\n if (successRate < 0.9 && this.batchSize > 1) {\n this.batchSize--;\n } else if (successRate > 0.95 && this.batchSize < 10) {\n this.batchSize++;\n }\n\n // Reset the counters\n this.successfulBatchCount = 0;\n this.failedBatchCount = 0;\n }\n }\n}\n"]}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /* eslint-disable */
4
+ const json_rpc_batch_provider_1 = require("./json-rpc-batch-provider");
5
+ describe('JsonRpcBatchProvider', () => {
6
+ let batchProvider;
7
+ let fetchJsonMock;
8
+ beforeEach(() => {
9
+ // Create a new instance of the JsonRpcBatchProvider before each test
10
+ batchProvider = new json_rpc_batch_provider_1.JsonRpcBatchProvider('http://localhost:8545');
11
+ // Mock the fetchJson function from the ethers package to simulate server responses
12
+ fetchJsonMock = jest.spyOn(require('./web'), 'fetchJson');
13
+ });
14
+ afterEach(() => {
15
+ // Reset the fetchJson mock after each test
16
+ fetchJsonMock.mockRestore();
17
+ });
18
+ test('adjustBatchSize properly adjusts batch size based on success rate', async () => {
19
+ // Mock fetchJson to return a successful response
20
+ fetchJsonMock.mockImplementation(async (connection, payload) => {
21
+ const requests = JSON.parse(payload);
22
+ return requests.map((request) => ({
23
+ id: request.id,
24
+ jsonrpc: '2.0',
25
+ result: '0x1',
26
+ }));
27
+ });
28
+ // Execute the send method multiple times to simulate successful requests
29
+ const requestCount = 20;
30
+ const promises = [];
31
+ for (let i = 0; i < requestCount; i++) {
32
+ const promise = batchProvider.send('eth_call', []);
33
+ promises.push(promise);
34
+ }
35
+ await Promise.all(promises);
36
+ // Check if the batch size has increased due to the success rate
37
+ expect(batchProvider['batchSize']).toBeGreaterThan(1);
38
+ // Now, mock fetchJson to return an error response
39
+ fetchJsonMock.mockImplementation(async (connection, payload) => {
40
+ const requests = JSON.parse(payload);
41
+ return requests.map((request) => ({
42
+ id: request.id,
43
+ jsonrpc: '2.0',
44
+ error: { code: -32603, message: 'Batch size limit exceeded' },
45
+ }));
46
+ });
47
+ // Execute the send method multiple times to simulate failed requests
48
+ const failedPromises = [];
49
+ for (let i = 0; i < requestCount + 10; i++) {
50
+ const failedPromise = batchProvider.send('eth_call', []);
51
+ failedPromises.push(failedPromise);
52
+ }
53
+ try {
54
+ await Promise.all(failedPromises);
55
+ }
56
+ catch (_a) {
57
+ // ignore error
58
+ }
59
+ // Check if the batch size has decreased due to the failure rate
60
+ expect(batchProvider['batchSize']).toBeLessThan(2);
61
+ });
62
+ });
63
+ //# sourceMappingURL=json-rpc-batch-provider.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-rpc-batch-provider.spec.js","sourceRoot":"","sources":["../../../src/ethereum/ethers/json-rpc-batch-provider.spec.ts"],"names":[],"mappings":";;AAAA,oBAAoB;AACpB,uEAAiE;AAGjE,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,aAAmC,CAAC;IACxC,IAAI,aAA+B,CAAC;IAEpC,UAAU,CAAC,GAAG,EAAE;QACd,qEAAqE;QACrE,aAAa,GAAG,IAAI,8CAAoB,CAAC,uBAAuB,CAAC,CAAC;QAElE,mFAAmF;QACnF,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,2CAA2C;QAC3C,aAAa,CAAC,WAAW,EAAE,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACnF,iDAAiD;QACjD,aAAa,CAAC,kBAAkB,CAC9B,KAAK,EAAE,UAA0B,EAAE,OAAe,EAAE,EAAE;YACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAY,EAAE,EAAE,CAAC,CAAC;gBACrC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,KAAK;aACd,CAAC,CAAC,CAAC;QACN,CAAC,CACF,CAAC;QAEF,yEAAyE;QACzE,MAAM,YAAY,GAAG,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE;YACrC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SACxB;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE5B,gEAAgE;QAChE,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAEtD,kDAAkD;QAClD,aAAa,CAAC,kBAAkB,CAC9B,KAAK,EAAE,UAA0B,EAAE,OAAe,EAAE,EAAE;YACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAY,EAAE,EAAE,CAAC,CAAC;gBACrC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,2BAA2B,EAAE;aAC9D,CAAC,CAAC,CAAC;QACN,CAAC,CACF,CAAC;QAEF,qEAAqE;QACrE,MAAM,cAAc,GAAG,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YAC1C,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACzD,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;SACpC;QAED,IAAI;YACF,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;SACnC;QAAC,WAAM;YACN,eAAe;SAChB;QAED,gEAAgE;QAChE,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/* eslint-disable */\nimport { JsonRpcBatchProvider } from './json-rpc-batch-provider';\nimport { ConnectionInfo } from './web';\n\ndescribe('JsonRpcBatchProvider', () => {\n let batchProvider: JsonRpcBatchProvider;\n let fetchJsonMock: jest.SpyInstance;\n\n beforeEach(() => {\n // Create a new instance of the JsonRpcBatchProvider before each test\n batchProvider = new JsonRpcBatchProvider('http://localhost:8545');\n\n // Mock the fetchJson function from the ethers package to simulate server responses\n fetchJsonMock = jest.spyOn(require('./web'), 'fetchJson');\n });\n\n afterEach(() => {\n // Reset the fetchJson mock after each test\n fetchJsonMock.mockRestore();\n });\n\n test('adjustBatchSize properly adjusts batch size based on success rate', async () => {\n // Mock fetchJson to return a successful response\n fetchJsonMock.mockImplementation(\n async (connection: ConnectionInfo, payload: string) => {\n const requests = JSON.parse(payload);\n return requests.map((request: any) => ({\n id: request.id,\n jsonrpc: '2.0',\n result: '0x1',\n }));\n },\n );\n\n // Execute the send method multiple times to simulate successful requests\n const requestCount = 20;\n const promises = [];\n for (let i = 0; i < requestCount; i++) {\n const promise = batchProvider.send('eth_call', []);\n promises.push(promise);\n }\n await Promise.all(promises);\n\n // Check if the batch size has increased due to the success rate\n expect(batchProvider['batchSize']).toBeGreaterThan(1);\n\n // Now, mock fetchJson to return an error response\n fetchJsonMock.mockImplementation(\n async (connection: ConnectionInfo, payload: string) => {\n const requests = JSON.parse(payload);\n return requests.map((request: any) => ({\n id: request.id,\n jsonrpc: '2.0',\n error: { code: -32603, message: 'Batch size limit exceeded' },\n }));\n },\n );\n\n // Execute the send method multiple times to simulate failed requests\n const failedPromises = [];\n for (let i = 0; i < requestCount + 10; i++) {\n const failedPromise = batchProvider.send('eth_call', []);\n failedPromises.push(failedPromise);\n }\n\n try {\n await Promise.all(failedPromises);\n } catch {\n // ignore error\n }\n\n // Check if the batch size has decreased due to the failure rate\n expect(batchProvider['batchSize']).toBeLessThan(2);\n });\n});\n"]}
@@ -64,11 +64,20 @@ function eventFilterToQueryEntry(filter, dsOptions) {
64
64
  continue;
65
65
  }
66
66
  const field = `topics${i}`;
67
- conditions.push({
68
- field,
69
- value: (0, string_1.eventToTopic)(topic),
70
- matcher: 'equalTo',
71
- });
67
+ if (topic === '!null') {
68
+ conditions.push({
69
+ field,
70
+ value: false,
71
+ matcher: 'isNull',
72
+ });
73
+ }
74
+ else {
75
+ conditions.push({
76
+ field,
77
+ value: (0, string_1.eventToTopic)(topic),
78
+ matcher: 'equalTo',
79
+ });
80
+ }
72
81
  }
73
82
  }
74
83
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.service.js","sourceRoot":"","sources":["../../src/indexer/fetch.service.ts"],"names":[],"mappings":";AAAA,gEAAgE;AAChE,sCAAsC;;;;;;;;;;;;;;;AAEtC,2CAAoD;AACpD,yDAAsD;AACtD,+CAAqD;AAErD,4DAMgC;AAChC,gDAK0B;AAI1B,mCAAiD;AACjD,kEAA+E;AAG/E,+DAA0D;AAC1D,4CAAkE;AAClE,oCAAwC;AAExC,6DAAyD;AACzD,iEAA4D;AAC5D,6DAAwD;AACxD,2EAGqC;AAErC,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,eAAe,CAAC,CAAC;AAE1C,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAEjC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,SAAS,uBAAuB,CAC9B,MAAyB,EACzB,SAA0E;IAE1E,MAAM,iBAAiB,GAAG,oBAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAEnE,MAAM,UAAU,GAA+B,EAAE,CAAC;IAElD,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QAC5B,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAE5E,IAAI,SAAS,CAAC,MAAM,GAAG,iBAAiB,EAAE;YACxC,MAAM,CAAC,IAAI,CACT,qBAAqB,SAAS,CAAC,MAAM,wBAAwB,iBAAiB,wEAAwE,CACvJ,CAAC;SACH;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,iBAAiB,EAAE;YACnE,UAAU,CAAC,IAAI,CAAC;gBACd,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;SACJ;KACF;SAAM;QACL,IAAI,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,OAAO,EAAE;YACtB,UAAU,CAAC,IAAI,CAAC;gBACd,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE;gBACtC,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;SACJ;KACF;IACD,IAAI,MAAM,CAAC,MAAM,EAAE;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,CAAC,KAAK,EAAE;gBACV,SAAS;aACV;YACD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC;gBACd,KAAK;gBACL,KAAK,EAAE,IAAA,qBAAY,EAAC,KAAK,CAAC;gBAC1B,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;SACJ;KACF;IACD,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,UAAU;KACX,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,MAAiC;IAEjC,MAAM,UAAU,GAA+B,EAAE,CAAC;IAClD,IAAI,MAAM,CAAC,IAAI,EAAE;QACf,UAAU,CAAC,IAAI,CAAC;YACd,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE;YAChC,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;KACJ;IACD,IAAI,MAAM,CAAC,EAAE,EAAE;QACb,UAAU,CAAC,IAAI,CAAC;YACd,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE;YAC9B,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;KACJ;SAAM,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,EAAE;QAC7B,UAAU,CAAC,IAAI,CAAC;YACd,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAW;YAClB,OAAO,EAAE,QAAQ;SAClB,CAAC,CAAC;KACJ;IACD,IAAI,MAAM,CAAC,QAAQ,EAAE;QACnB,UAAU,CAAC,IAAI,CAAC;YACd,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,IAAA,0BAAiB,EAAC,MAAM,CAAC,QAAQ,CAAC;YACzC,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;KACJ;IACD,OAAO;QACL,MAAM,EAAE,iBAAiB;QACzB,UAAU;KACX,CAAC;AACJ,CAAC;AAKD,SAAgB,2BAA2B,CACzC,WAAoC,EACpC,UAAkB;;IAElB,MAAM,YAAY,GAA2B,EAAE,CAAC;IAEhD,wDAAwD;IACxD,kDAAkD;IAClD,MAAM,UAAU,GAAG,WAAW;SAC3B,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,IAAI,UAAU,CAAC;SAC3C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAE/C,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE;QAC3B,KAAK,MAAM,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE;YACzC,kCAAkC;YAClC,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,OAAO,EAAE,CAAC;YAE/B,QAAQ,OAAO,CAAC,IAAI,EAAE;gBACpB,KAAK,qCAAmB,CAAC,KAAK;oBAC5B,OAAO,EAAE,CAAC;gBACZ,KAAK,qCAAmB,CAAC,IAAI,CAAC,CAAC;oBAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAmC,CAAC;oBAC3D,IACE,MAAM,CAAC,IAAI,KAAK,SAAS;wBACzB,MAAM,CAAC,EAAE,KAAK,SAAS;wBACvB,MAAM,CAAC,QAAQ,EACf;wBACA,YAAY,CAAC,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;qBACnD;yBAAM;wBACL,OAAO,EAAE,CAAC;qBACX;oBACD,MAAM;iBACP;gBACD,KAAK,qCAAmB,CAAC,KAAK,CAAC,CAAC;oBAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,MAA2B,CAAC;oBACnD,IAAI,EAAE,CAAC,cAAc,EAAE;wBACrB,YAAY,CAAC,IAAI,CACf,uBAAuB,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,CACnD,CAAC;qBACH;yBAAM,IAAI,CAAA,MAAA,EAAE,CAAC,OAAO,0CAAE,OAAO,KAAI,MAAM,CAAC,MAAM,EAAE;wBAC/C,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;qBAChE;yBAAM;wBACL,OAAO,EAAE,CAAC;qBACX;oBACD,MAAM;iBACP;gBACD,QAAQ;aACT;SACF;KACF;IAED,OAAO,IAAA,eAAM,EACX,YAAY,EACZ,CAAC,IAAI,EAAE,EAAE,CACP,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAC9B,IAAA,eAAM,EAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CACxC,EAAE,CACN,CAAC;AACJ,CAAC;AA1DD,kEA0DC;AAGM,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,4BAKjC;IACC,YACE,UAAsB,EACtB,UAAsB,EACM,OAAwB,EAEpD,eAAyC,EACzC,iBAAoC,EACpC,kBAAsC,EACtC,gBAAkC,EAC1B,wBAAkD,EAC1D,YAA2B,EAC3B,iBAAoC;QAEpC,KAAK,CACH,UAAU,EACV,UAAU,EACV,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,CAClB,CAAC;QAdM,6BAAwB,GAAxB,wBAAwB,CAA0B;IAe5D,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;IACnC,CAAC;IAED,2BAA2B,CAAC,UAAkB;QAC5C,MAAM,eAAe,GAA4B,MAAM,CAAC,MAAM,CAC5D,IAAA,gBAAO,EAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CACzD,CAAC,GAAG,CAAC,CAAC,OAAyB,EAAE,EAAE;YAClC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAEvB,uCACK,GAAG,KACN,cAAc,EAAE,OAAO,IACvB;QACJ,CAAC,CAAC,CAAC;QAEH,wDAAwD;QACxD,kDAAkD;QAClD,MAAM,UAAU,GACd,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAEnD,OAAO,2BAA2B,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC;IAES,KAAK,CAAC,kBAAkB;QAChC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAEjD,MAAM,MAAM,GAAG,IAAA,yCAAa,EAAC,KAAK,CAAC,CAAC;QAEpC,IAAI,CAAC,wBAAwB,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC,WAAW,CAAC;IAC5B,CAAC;IAES,KAAK,CAAC,aAAa;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;IACvC,CAAC;IAED,4DAA4D;IAClD,KAAK,CAAC,gBAAgB;QAC9B,MAAM,cAAc,GAAG,IAAA,6BAAY,EAAC,IAAI,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC;QAEjE,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;IACvD,CAAC;IAES,KAAK,CAAC,UAAU;QACxB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3D,CAAC;IAES,UAAU;QAClB,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;YACzC,IAAI,IAAA,4BAAU,EAAC,EAAE,CAAC,EAAE;gBAClB,SAAS;aACV;YACD,KAAK,MAAM,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACzC,IACE,OAAO,CAAC,IAAI,KAAK,qCAAmB,CAAC,KAAK;oBAC1C,OAAO,CAAC,MAAM;oBACd,OAAO,CAAC,MAAM,CAAC,MAAM,EACrB;oBACA,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;iBACrC;aACF;SACF;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,KAAK,CAAC,mBAAmB;QACjC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,CAAC;IAES,KAAK,CAAC,wBAAwB,CACtC,QAAkB;QAElB,OAAO,OAAO,CAAC,OAAO;QACpB,yBAAyB;QACzB,QAAQ,CAAC,WAAW,KAAK,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE;YAChD,6BAA6B;YAC7B,QAAQ,CAAC,WAAW,KAAK,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAC1D,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,WAAW;QACzB,4CAA4C;QAC5C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF,CAAA;AAvHY,YAAY;IADxB,IAAA,mBAAU,GAAE;IAUR,WAAA,IAAA,eAAM,EAAC,kBAAkB,CAAC,CAAA;IAC1B,WAAA,IAAA,eAAM,EAAC,kBAAkB,CAAC,CAAA;qCAHf,sBAAU;QACV,sBAAU;QACe,iCAAe,UAGjC,sCAAiB;QAChB,yCAAkB;QACpB,qCAAgB;QACA,oDAAwB;QAC5C,6BAAa;QACR,4BAAiB;GAjB3B,YAAY,CAuHxB;AAvHY,oCAAY","sourcesContent":["// Copyright 2020-2022 OnFinality Limited authors & contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { SchedulerRegistry } from '@nestjs/schedule';\n\nimport {\n isCustomDs,\n EthereumHandlerKind,\n EthereumLogFilter,\n SubqlEthereumProcessorOptions,\n EthereumTransactionFilter,\n} from '@subql/common-ethereum';\nimport {\n NodeConfig,\n BaseFetchService,\n ApiService,\n getLogger,\n} from '@subql/node-core';\nimport { DictionaryQueryCondition, DictionaryQueryEntry } from '@subql/types';\nimport { SubqlDatasource } from '@subql/types-ethereum';\nimport { MetaData } from '@subql/utils';\nimport { groupBy, sortBy, uniqBy } from 'lodash';\nimport { SubqlProjectDs, SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApi, EthereumApiService } from '../ethereum';\nimport SafeEthProvider from '../ethereum/safe-api';\nimport { calcInterval } from '../ethereum/utils.ethereum';\nimport { eventToTopic, functionToSighash } from '../utils/string';\nimport { yargsOptions } from '../yargs';\nimport { IEthereumBlockDispatcher } from './blockDispatcher';\nimport { DictionaryService } from './dictionary.service';\nimport { DsProcessorService } from './ds-processor.service';\nimport { DynamicDsService } from './dynamic-ds.service';\nimport {\n blockToHeader,\n UnfinalizedBlocksService,\n} from './unfinalizedBlocks.service';\n\nconst logger = getLogger('fetch.service');\n\nconst BLOCK_TIME_VARIANCE = 5000;\n\nconst INTERVAL_PERCENT = 0.9;\n\nfunction eventFilterToQueryEntry(\n filter: EthereumLogFilter,\n dsOptions: SubqlEthereumProcessorOptions | SubqlEthereumProcessorOptions[],\n): DictionaryQueryEntry {\n const queryAddressLimit = yargsOptions.argv['query-address-limit'];\n\n const conditions: DictionaryQueryCondition[] = [];\n\n if (Array.isArray(dsOptions)) {\n const addresses = dsOptions.map((option) => option.address).filter(Boolean);\n\n if (addresses.length > queryAddressLimit) {\n logger.warn(\n `Addresses length: ${addresses.length} is exceeding limit: ${queryAddressLimit}. Consider increasing this value with the flag --query-address-limit `,\n );\n }\n\n if (addresses.length !== 0 && addresses.length <= queryAddressLimit) {\n conditions.push({\n field: 'address',\n value: addresses,\n matcher: 'in',\n });\n }\n } else {\n if (dsOptions?.address) {\n conditions.push({\n field: 'address',\n value: dsOptions.address.toLowerCase(),\n matcher: 'equalTo',\n });\n }\n }\n if (filter.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n const field = `topics${i}`;\n conditions.push({\n field,\n value: eventToTopic(topic),\n matcher: 'equalTo',\n });\n }\n }\n return {\n entity: 'evmLogs',\n conditions,\n };\n}\n\nfunction callFilterToQueryEntry(\n filter: EthereumTransactionFilter,\n): DictionaryQueryEntry {\n const conditions: DictionaryQueryCondition[] = [];\n if (filter.from) {\n conditions.push({\n field: 'from',\n value: filter.from.toLowerCase(),\n matcher: 'equalTo',\n });\n }\n if (filter.to) {\n conditions.push({\n field: 'to',\n value: filter.to.toLowerCase(),\n matcher: 'equalTo',\n });\n } else if (filter.to === null) {\n conditions.push({\n field: 'to',\n value: true as any, // TODO update types to allow boolean\n matcher: 'isNull',\n });\n }\n if (filter.function) {\n conditions.push({\n field: 'func',\n value: functionToSighash(filter.function),\n matcher: 'equalTo',\n });\n }\n return {\n entity: 'evmTransactions',\n conditions,\n };\n}\n\ntype GroupedSubqlProjectDs = SubqlDatasource & {\n groupedOptions?: SubqlEthereumProcessorOptions[];\n};\nexport function buildDictionaryQueryEntries(\n dataSources: GroupedSubqlProjectDs[],\n startBlock: number,\n): DictionaryQueryEntry[] {\n const queryEntries: DictionaryQueryEntry[] = [];\n\n // Only run the ds that is equal or less than startBlock\n // sort array from lowest ds.startBlock to highest\n const filteredDs = dataSources\n .filter((ds) => ds.startBlock <= startBlock)\n .sort((a, b) => a.startBlock - b.startBlock);\n\n for (const ds of filteredDs) {\n for (const handler of ds.mapping.handlers) {\n // No filters, cant use dictionary\n if (!handler.filter) return [];\n\n switch (handler.kind) {\n case EthereumHandlerKind.Block:\n return [];\n case EthereumHandlerKind.Call: {\n const filter = handler.filter as EthereumTransactionFilter;\n if (\n filter.from !== undefined ||\n filter.to !== undefined ||\n filter.function\n ) {\n queryEntries.push(callFilterToQueryEntry(filter));\n } else {\n return [];\n }\n break;\n }\n case EthereumHandlerKind.Event: {\n const filter = handler.filter as EthereumLogFilter;\n if (ds.groupedOptions) {\n queryEntries.push(\n eventFilterToQueryEntry(filter, ds.groupedOptions),\n );\n } else if (ds.options?.address || filter.topics) {\n queryEntries.push(eventFilterToQueryEntry(filter, ds.options));\n } else {\n return [];\n }\n break;\n }\n default:\n }\n }\n }\n\n return uniqBy(\n queryEntries,\n (item) =>\n `${item.entity}|${JSON.stringify(\n sortBy(item.conditions, (c) => c.field),\n )}`,\n );\n}\n\n@Injectable()\nexport class FetchService extends BaseFetchService<\n ApiService,\n SubqlDatasource,\n IEthereumBlockDispatcher,\n DictionaryService\n> {\n constructor(\n apiService: ApiService,\n nodeConfig: NodeConfig,\n @Inject('ISubqueryProject') project: SubqueryProject,\n @Inject('IBlockDispatcher')\n blockDispatcher: IEthereumBlockDispatcher,\n dictionaryService: DictionaryService,\n dsProcessorService: DsProcessorService,\n dynamicDsService: DynamicDsService,\n private unfinalizedBlocksService: UnfinalizedBlocksService,\n eventEmitter: EventEmitter2,\n schedulerRegistry: SchedulerRegistry,\n ) {\n super(\n apiService,\n nodeConfig,\n project,\n blockDispatcher,\n dictionaryService,\n dsProcessorService,\n dynamicDsService,\n eventEmitter,\n schedulerRegistry,\n );\n }\n\n get api(): EthereumApi {\n return this.apiService.unsafeApi;\n }\n\n buildDictionaryQueryEntries(startBlock: number): DictionaryQueryEntry[] {\n const groupdDynamicDs: GroupedSubqlProjectDs[] = Object.values(\n groupBy(this.templateDynamicDatasouces, (ds) => ds.name),\n ).map((grouped: SubqlProjectDs[]) => {\n const options = grouped.map((ds) => ds.options);\n const ref = grouped[0];\n\n return {\n ...ref,\n groupedOptions: options,\n };\n });\n\n // Only run the ds that is equal or less than startBlock\n // sort array from lowest ds.startBlock to highest\n const filteredDs: GroupedSubqlProjectDs[] =\n this.project.dataSources.concat(groupdDynamicDs);\n\n return buildDictionaryQueryEntries(filteredDs, startBlock);\n }\n\n protected async getFinalizedHeight(): Promise<number> {\n const block = await this.api.getFinalizedBlock();\n\n const header = blockToHeader(block);\n\n this.unfinalizedBlocksService.registerFinalizedBlock(header);\n return header.blockHeight;\n }\n\n protected async getBestHeight(): Promise<number> {\n return this.api.getBestBlockHeight();\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n protected async getChainInterval(): Promise<number> {\n const CHAIN_INTERVAL = calcInterval(this.api) * INTERVAL_PERCENT;\n\n return Math.min(BLOCK_TIME_VARIANCE, CHAIN_INTERVAL);\n }\n\n protected async getChainId(): Promise<string> {\n return Promise.resolve(this.api.getChainId().toString());\n }\n\n protected getModulos(): number[] {\n const modulos: number[] = [];\n for (const ds of this.project.dataSources) {\n if (isCustomDs(ds)) {\n continue;\n }\n for (const handler of ds.mapping.handlers) {\n if (\n handler.kind === EthereumHandlerKind.Block &&\n handler.filter &&\n handler.filter.modulo\n ) {\n modulos.push(handler.filter.modulo);\n }\n }\n }\n return modulos;\n }\n\n protected async initBlockDispatcher(): Promise<void> {\n await this.blockDispatcher.init(this.resetForNewDs.bind(this));\n }\n\n protected async validatateDictionaryMeta(\n metaData: MetaData,\n ): Promise<boolean> {\n return Promise.resolve(\n // When alias is not used\n metaData.genesisHash !== this.api.getGenesisHash() &&\n // Case when an alias is used\n metaData.genesisHash !== this.dictionaryService.chainId,\n );\n }\n\n protected async preLoopHook(): Promise<void> {\n // Ethereum doesn't need to do anything here\n return Promise.resolve();\n }\n}\n"]}
1
+ {"version":3,"file":"fetch.service.js","sourceRoot":"","sources":["../../src/indexer/fetch.service.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2022 OnFinality Limited authors & contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { SchedulerRegistry } from '@nestjs/schedule';\n\nimport {\n isCustomDs,\n EthereumHandlerKind,\n EthereumLogFilter,\n SubqlEthereumProcessorOptions,\n EthereumTransactionFilter,\n} from '@subql/common-ethereum';\nimport {\n NodeConfig,\n BaseFetchService,\n ApiService,\n getLogger,\n} from '@subql/node-core';\nimport { DictionaryQueryCondition, DictionaryQueryEntry } from '@subql/types';\nimport { SubqlDatasource } from '@subql/types-ethereum';\nimport { MetaData } from '@subql/utils';\nimport { groupBy, sortBy, uniqBy } from 'lodash';\nimport { SubqlProjectDs, SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApi, EthereumApiService } from '../ethereum';\nimport SafeEthProvider from '../ethereum/safe-api';\nimport { calcInterval } from '../ethereum/utils.ethereum';\nimport { eventToTopic, functionToSighash } from '../utils/string';\nimport { yargsOptions } from '../yargs';\nimport { IEthereumBlockDispatcher } from './blockDispatcher';\nimport { DictionaryService } from './dictionary.service';\nimport { DsProcessorService } from './ds-processor.service';\nimport { DynamicDsService } from './dynamic-ds.service';\nimport {\n blockToHeader,\n UnfinalizedBlocksService,\n} from './unfinalizedBlocks.service';\n\nconst logger = getLogger('fetch.service');\n\nconst BLOCK_TIME_VARIANCE = 5000;\n\nconst INTERVAL_PERCENT = 0.9;\n\nfunction eventFilterToQueryEntry(\n filter: EthereumLogFilter,\n dsOptions: SubqlEthereumProcessorOptions | SubqlEthereumProcessorOptions[],\n): DictionaryQueryEntry {\n const queryAddressLimit = yargsOptions.argv['query-address-limit'];\n\n const conditions: DictionaryQueryCondition[] = [];\n\n if (Array.isArray(dsOptions)) {\n const addresses = dsOptions.map((option) => option.address).filter(Boolean);\n\n if (addresses.length > queryAddressLimit) {\n logger.warn(\n `Addresses length: ${addresses.length} is exceeding limit: ${queryAddressLimit}. Consider increasing this value with the flag --query-address-limit `,\n );\n }\n\n if (addresses.length !== 0 && addresses.length <= queryAddressLimit) {\n conditions.push({\n field: 'address',\n value: addresses,\n matcher: 'in',\n });\n }\n } else {\n if (dsOptions?.address) {\n conditions.push({\n field: 'address',\n value: dsOptions.address.toLowerCase(),\n matcher: 'equalTo',\n });\n }\n }\n if (filter.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n const field = `topics${i}`;\n\n if (topic === '!null') {\n conditions.push({\n field,\n value: false as any, // TODO update types to allow boolean\n matcher: 'isNull',\n });\n } else {\n conditions.push({\n field,\n value: eventToTopic(topic),\n matcher: 'equalTo',\n });\n }\n }\n }\n return {\n entity: 'evmLogs',\n conditions,\n };\n}\n\nfunction callFilterToQueryEntry(\n filter: EthereumTransactionFilter,\n): DictionaryQueryEntry {\n const conditions: DictionaryQueryCondition[] = [];\n if (filter.from) {\n conditions.push({\n field: 'from',\n value: filter.from.toLowerCase(),\n matcher: 'equalTo',\n });\n }\n if (filter.to) {\n conditions.push({\n field: 'to',\n value: filter.to.toLowerCase(),\n matcher: 'equalTo',\n });\n } else if (filter.to === null) {\n conditions.push({\n field: 'to',\n value: true as any, // TODO update types to allow boolean\n matcher: 'isNull',\n });\n }\n if (filter.function) {\n conditions.push({\n field: 'func',\n value: functionToSighash(filter.function),\n matcher: 'equalTo',\n });\n }\n return {\n entity: 'evmTransactions',\n conditions,\n };\n}\n\ntype GroupedSubqlProjectDs = SubqlDatasource & {\n groupedOptions?: SubqlEthereumProcessorOptions[];\n};\nexport function buildDictionaryQueryEntries(\n dataSources: GroupedSubqlProjectDs[],\n startBlock: number,\n): DictionaryQueryEntry[] {\n const queryEntries: DictionaryQueryEntry[] = [];\n\n // Only run the ds that is equal or less than startBlock\n // sort array from lowest ds.startBlock to highest\n const filteredDs = dataSources\n .filter((ds) => ds.startBlock <= startBlock)\n .sort((a, b) => a.startBlock - b.startBlock);\n\n for (const ds of filteredDs) {\n for (const handler of ds.mapping.handlers) {\n // No filters, cant use dictionary\n if (!handler.filter) return [];\n\n switch (handler.kind) {\n case EthereumHandlerKind.Block:\n return [];\n case EthereumHandlerKind.Call: {\n const filter = handler.filter as EthereumTransactionFilter;\n if (\n filter.from !== undefined ||\n filter.to !== undefined ||\n filter.function\n ) {\n queryEntries.push(callFilterToQueryEntry(filter));\n } else {\n return [];\n }\n break;\n }\n case EthereumHandlerKind.Event: {\n const filter = handler.filter as EthereumLogFilter;\n if (ds.groupedOptions) {\n queryEntries.push(\n eventFilterToQueryEntry(filter, ds.groupedOptions),\n );\n } else if (ds.options?.address || filter.topics) {\n queryEntries.push(eventFilterToQueryEntry(filter, ds.options));\n } else {\n return [];\n }\n break;\n }\n default:\n }\n }\n }\n\n return uniqBy(\n queryEntries,\n (item) =>\n `${item.entity}|${JSON.stringify(\n sortBy(item.conditions, (c) => c.field),\n )}`,\n );\n}\n\n@Injectable()\nexport class FetchService extends BaseFetchService<\n ApiService,\n SubqlDatasource,\n IEthereumBlockDispatcher,\n DictionaryService\n> {\n constructor(\n apiService: ApiService,\n nodeConfig: NodeConfig,\n @Inject('ISubqueryProject') project: SubqueryProject,\n @Inject('IBlockDispatcher')\n blockDispatcher: IEthereumBlockDispatcher,\n dictionaryService: DictionaryService,\n dsProcessorService: DsProcessorService,\n dynamicDsService: DynamicDsService,\n private unfinalizedBlocksService: UnfinalizedBlocksService,\n eventEmitter: EventEmitter2,\n schedulerRegistry: SchedulerRegistry,\n ) {\n super(\n apiService,\n nodeConfig,\n project,\n blockDispatcher,\n dictionaryService,\n dsProcessorService,\n dynamicDsService,\n eventEmitter,\n schedulerRegistry,\n );\n }\n\n get api(): EthereumApi {\n return this.apiService.unsafeApi;\n }\n\n buildDictionaryQueryEntries(startBlock: number): DictionaryQueryEntry[] {\n const groupdDynamicDs: GroupedSubqlProjectDs[] = Object.values(\n groupBy(this.templateDynamicDatasouces, (ds) => ds.name),\n ).map((grouped: SubqlProjectDs[]) => {\n const options = grouped.map((ds) => ds.options);\n const ref = grouped[0];\n\n return {\n ...ref,\n groupedOptions: options,\n };\n });\n\n // Only run the ds that is equal or less than startBlock\n // sort array from lowest ds.startBlock to highest\n const filteredDs: GroupedSubqlProjectDs[] =\n this.project.dataSources.concat(groupdDynamicDs);\n\n return buildDictionaryQueryEntries(filteredDs, startBlock);\n }\n\n protected async getFinalizedHeight(): Promise<number> {\n const block = await this.api.getFinalizedBlock();\n\n const header = blockToHeader(block);\n\n this.unfinalizedBlocksService.registerFinalizedBlock(header);\n return header.blockHeight;\n }\n\n protected async getBestHeight(): Promise<number> {\n return this.api.getBestBlockHeight();\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n protected async getChainInterval(): Promise<number> {\n const CHAIN_INTERVAL = calcInterval(this.api) * INTERVAL_PERCENT;\n\n return Math.min(BLOCK_TIME_VARIANCE, CHAIN_INTERVAL);\n }\n\n protected async getChainId(): Promise<string> {\n return Promise.resolve(this.api.getChainId().toString());\n }\n\n protected getModulos(): number[] {\n const modulos: number[] = [];\n for (const ds of this.project.dataSources) {\n if (isCustomDs(ds)) {\n continue;\n }\n for (const handler of ds.mapping.handlers) {\n if (\n handler.kind === EthereumHandlerKind.Block &&\n handler.filter &&\n handler.filter.modulo\n ) {\n modulos.push(handler.filter.modulo);\n }\n }\n }\n return modulos;\n }\n\n protected async initBlockDispatcher(): Promise<void> {\n await this.blockDispatcher.init(this.resetForNewDs.bind(this));\n }\n\n protected async validatateDictionaryMeta(\n metaData: MetaData,\n ): Promise<boolean> {\n return Promise.resolve(\n // When alias is not used\n metaData.genesisHash !== this.api.getGenesisHash() &&\n // Case when an alias is used\n metaData.genesisHash !== this.dictionaryService.chainId,\n );\n }\n\n protected async preLoopHook(): Promise<void> {\n // Ethereum doesn't need to do anything here\n return Promise.resolve();\n }\n}\n"]}
@@ -62,7 +62,51 @@ function testSubqueryProject(endpoint, ds, mockTempDs) {
62
62
  templates: mockTempDs,
63
63
  };
64
64
  }
65
- describe('Dictioanry queries', () => {
65
+ describe('Dictionary queries', () => {
66
+ describe('Log filters', () => {
67
+ it('Build filter for !null', () => {
68
+ const ds = {
69
+ kind: types_ethereum_1.EthereumDatasourceKind.Runtime,
70
+ assets: new Map(),
71
+ startBlock: 1,
72
+ mapping: {
73
+ file: '',
74
+ handlers: [
75
+ {
76
+ handler: 'handleLog',
77
+ kind: types_ethereum_1.EthereumHandlerKind.Event,
78
+ filter: {
79
+ topics: [
80
+ 'Transfer(address, address, uint256)',
81
+ undefined,
82
+ undefined,
83
+ '!null',
84
+ ],
85
+ },
86
+ },
87
+ ],
88
+ },
89
+ };
90
+ const result = (0, fetch_service_1.buildDictionaryQueryEntries)([ds], 1);
91
+ expect(result).toEqual([
92
+ {
93
+ entity: 'evmLogs',
94
+ conditions: [
95
+ {
96
+ field: 'topics0',
97
+ value: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
98
+ matcher: 'equalTo',
99
+ },
100
+ {
101
+ field: 'topics3',
102
+ value: false,
103
+ matcher: 'isNull',
104
+ },
105
+ ],
106
+ },
107
+ ]);
108
+ });
109
+ });
66
110
  describe('Transaction filters', () => {
67
111
  it('Build a filter for contract creation transactions', () => {
68
112
  const ds = {