@subql/node-ethereum 6.2.2-0 → 6.3.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.
- package/CHANGELOG.md +6 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/utils/string.js +2 -1
- package/dist/utils/string.js.map +1 -1
- package/package.json +3 -4
- package/dist/blockchain.service.test.d.ts +0 -1
- package/dist/blockchain.service.test.js +0 -27
- package/dist/blockchain.service.test.js.map +0 -1
- package/dist/ethereum/api.ethereum.test.d.ts +0 -1
- package/dist/ethereum/api.ethereum.test.js +0 -266
- package/dist/ethereum/api.ethereum.test.js.map +0 -1
- package/dist/ethereum/api.service.ethereum.test.d.ts +0 -1
- package/dist/ethereum/api.service.ethereum.test.js +0 -91
- package/dist/ethereum/api.service.ethereum.test.js.map +0 -1
- package/dist/ethereum/ethers/celo/celo-ws-provider.spec.d.ts +0 -1
- package/dist/ethereum/ethers/celo/celo-ws-provider.spec.js +0 -33
- package/dist/ethereum/ethers/celo/celo-ws-provider.spec.js.map +0 -1
- package/dist/ethereum/ethers/json-rpc-batch-provider.spec.d.ts +0 -1
- package/dist/ethereum/ethers/json-rpc-batch-provider.spec.js +0 -63
- package/dist/ethereum/ethers/json-rpc-batch-provider.spec.js.map +0 -1
- package/dist/ethereum/ethers/op/op-provider.spec.d.ts +0 -1
- package/dist/ethereum/ethers/op/op-provider.spec.js +0 -32
- package/dist/ethereum/ethers/op/op-provider.spec.js.map +0 -1
- package/dist/indexer/dictionary/utils.spec.d.ts +0 -1
- package/dist/indexer/dictionary/utils.spec.js +0 -101
- package/dist/indexer/dictionary/utils.spec.js.map +0 -1
- package/dist/indexer/dictionary/v1/ethDictionaryV1.spec.d.ts +0 -1
- package/dist/indexer/dictionary/v1/ethDictionaryV1.spec.js +0 -519
- package/dist/indexer/dictionary/v1/ethDictionaryV1.spec.js.map +0 -1
- package/dist/indexer/dictionary/v2/ethDictionaryV2.spec.d.ts +0 -1
- package/dist/indexer/dictionary/v2/ethDictionaryV2.spec.js +0 -585
- package/dist/indexer/dictionary/v2/ethDictionaryV2.spec.js.map +0 -1
- package/dist/indexer/dictionary/v2/utils.spec.d.ts +0 -1
- package/dist/indexer/dictionary/v2/utils.spec.js +0 -92
- package/dist/indexer/dictionary/v2/utils.spec.js.map +0 -1
- package/dist/indexer/unfinalizedBlocks.service.spec.d.ts +0 -1
- package/dist/indexer/unfinalizedBlocks.service.spec.js +0 -169
- package/dist/indexer/unfinalizedBlocks.service.spec.js.map +0 -1
- package/dist/utils/project.spec.d.ts +0 -1
- package/dist/utils/project.spec.js +0 -99
- package/dist/utils/project.spec.js.map +0 -1
- package/dist/utils/string.spec.d.ts +0 -1
- package/dist/utils/string.spec.js +0 -103
- package/dist/utils/string.spec.js.map +0 -1
package/dist/utils/string.js
CHANGED
|
@@ -224,7 +224,8 @@ function eventToTopic(input) {
|
|
|
224
224
|
if ((0, bytes_1.isHexString)(input))
|
|
225
225
|
return input;
|
|
226
226
|
if (!eventTopicsCache[input]) {
|
|
227
|
-
|
|
227
|
+
const cleanedInput = input.replace(/\bindexed\b/g, '');
|
|
228
|
+
eventTopicsCache[input] = (0, hash_1.id)(abi_1.EventFragment.fromString(cleanedInput).format());
|
|
228
229
|
}
|
|
229
230
|
return eventTopicsCache[input];
|
|
230
231
|
}
|
package/dist/utils/string.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/utils/string.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventFragment, FunctionFragment, Interface } from '@ethersproject/abi';\nimport { isHexString, hexStripZeros, hexDataSlice } from '@ethersproject/bytes';\nimport { id } from '@ethersproject/hash';\n\nexport function stringNormalizedEq(a: string, b?: string): boolean {\n return a.toLowerCase() === b?.toLowerCase();\n}\n\nexport function hexStringEq(a: string, b: string): boolean {\n if (!isHexString(a) || !isHexString(b)) {\n throw new Error('Inputs are not hex strings');\n }\n return stringNormalizedEq(hexStripZeros(a), hexStripZeros(b));\n}\n\nconst eventTopicsCache: Record<string, string> = {};\nconst functionSighashCache: Record<string, string> = {};\n\nexport interface AbiCustomType {\n name: string;\n type: 'enum' | 'struct';\n resolvedType: string;\n}\n\nexport function extractCustomTypesFromAbi(\n abiInterface: Interface,\n): Map<string, AbiCustomType> {\n const customTypes = new Map<string, AbiCustomType>();\n\n try {\n // Process event fragments\n Object.values(abiInterface.events).forEach(\n (eventFragment: EventFragment) => {\n eventFragment.inputs.forEach((input) => {\n extractCustomTypeFromInput(input, customTypes);\n });\n },\n );\n\n // Process function fragments\n Object.values(abiInterface.functions).forEach(\n (functionFragment: FunctionFragment) => {\n functionFragment.inputs.forEach((input) => {\n extractCustomTypeFromInput(input, customTypes);\n });\n },\n );\n } catch (error) {\n // Silently handle extraction errors in runtime\n }\n\n return customTypes;\n}\n\nfunction extractCustomTypeFromInput(\n input: { type: string; internalType?: string; components?: any[] },\n customTypes: Map<string, AbiCustomType>,\n): void {\n // Handle tuple types (structs)\n if (input.type === 'tuple' && input.internalType) {\n // Extract struct name from internal type (e.g., \"struct MoreData\" -> \"MoreData\", \"contract.MoreData\" -> \"MoreData\")\n const structName = input.internalType\n .replace(/^struct\\s+/, '') // Remove \"struct \" prefix\n .replace(/^.*\\./, ''); // Remove contract prefix if present (e.g., \"contract.Name\" -> \"Name\")\n\n if (!customTypes.has(structName) && input.components) {\n const tupleType = `(${input.components\n .map((comp: any) => resolveBaseType(comp.type))\n .join(',')})`;\n customTypes.set(structName, {\n name: structName,\n type: 'struct',\n resolvedType: tupleType,\n });\n }\n }\n\n // Handle enum types - look for custom internal types that aren't standard solidity types\n if (input.internalType && input.internalType !== input.type) {\n // Extract enum name from internal type (e.g., \"enum DisputeType\" -> \"DisputeType\", \"contract.DisputeType\" -> \"DisputeType\")\n const enumName = input.internalType\n .replace(/^enum\\s+/, '') // Remove \"enum \" prefix\n .replace(/^.*\\./, ''); // Remove contract prefix if present (e.g., \"contract.Name\" -> \"Name\")\n\n // Check if it's likely an enum (uint8/uint256 type with custom internal type)\n if (\n (input.type === 'uint8' || input.type === 'uint256') &&\n !enumName.startsWith('struct ') &&\n !isStandardSolidityType(enumName)\n ) {\n if (!customTypes.has(enumName)) {\n customTypes.set(enumName, {\n name: enumName,\n type: 'enum',\n resolvedType: 'uint8',\n });\n }\n }\n }\n\n // Recursively handle components for nested tuples\n if (input.components) {\n input.components.forEach((comp: any) => {\n extractCustomTypeFromInput(comp, customTypes);\n });\n }\n}\n\nfunction resolveBaseType(type: string): string {\n // Map common type aliases to their canonical forms\n const typeMapping: Record<string, string> = {\n uint: 'uint256',\n int: 'int256',\n };\n return typeMapping[type] || type;\n}\n\nfunction isStandardSolidityType(type: string): boolean {\n const standardTypes = [\n 'address',\n 'bool',\n 'string',\n 'bytes',\n // uint variants\n 'uint',\n 'uint8',\n 'uint16',\n 'uint24',\n 'uint32',\n 'uint40',\n 'uint48',\n 'uint56',\n 'uint64',\n 'uint72',\n 'uint80',\n 'uint88',\n 'uint96',\n 'uint104',\n 'uint112',\n 'uint120',\n 'uint128',\n 'uint136',\n 'uint144',\n 'uint152',\n 'uint160',\n 'uint168',\n 'uint176',\n 'uint184',\n 'uint192',\n 'uint200',\n 'uint208',\n 'uint216',\n 'uint224',\n 'uint232',\n 'uint240',\n 'uint248',\n 'uint256',\n // int variants\n 'int',\n 'int8',\n 'int16',\n 'int24',\n 'int32',\n 'int40',\n 'int48',\n 'int56',\n 'int64',\n 'int72',\n 'int80',\n 'int88',\n 'int96',\n 'int104',\n 'int112',\n 'int120',\n 'int128',\n 'int136',\n 'int144',\n 'int152',\n 'int160',\n 'int168',\n 'int176',\n 'int184',\n 'int192',\n 'int200',\n 'int208',\n 'int216',\n 'int224',\n 'int232',\n 'int240',\n 'int248',\n 'int256',\n // bytes variants\n 'bytes1',\n 'bytes2',\n 'bytes3',\n 'bytes4',\n 'bytes5',\n 'bytes6',\n 'bytes7',\n 'bytes8',\n 'bytes9',\n 'bytes10',\n 'bytes11',\n 'bytes12',\n 'bytes13',\n 'bytes14',\n 'bytes15',\n 'bytes16',\n 'bytes17',\n 'bytes18',\n 'bytes19',\n 'bytes20',\n 'bytes21',\n 'bytes22',\n 'bytes23',\n 'bytes24',\n 'bytes25',\n 'bytes26',\n 'bytes27',\n 'bytes28',\n 'bytes29',\n 'bytes30',\n 'bytes31',\n 'bytes32',\n ];\n\n // handle array types\n const baseType = type.replace(/\\[\\d*\\]$/, '');\n return standardTypes.includes(baseType);\n}\n\nexport function resolveCustomTypesInSignature(\n signature: string,\n customTypes: Map<string, AbiCustomType>,\n): string {\n let resolvedSignature = signature;\n\n // Replace custom types in the signature\n customTypes.forEach((customType, typeName) => {\n // Create regex to match the custom type name as a parameter type\n const regex = new RegExp(`\\\\b${escapeRegex(typeName)}\\\\b`, 'g');\n resolvedSignature = resolvedSignature.replace(\n regex,\n customType.resolvedType,\n );\n });\n\n return resolvedSignature;\n}\n\nfunction escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function eventToTopic(input: string): string {\n if (isHexString(input)) return input;\n\n if (!eventTopicsCache[input]) {\n eventTopicsCache[input] = id(EventFragment.fromString(input).format());\n }\n\n return eventTopicsCache[input];\n}\n\nexport function functionToSighash(input: string): string {\n if (isHexString(input)) return input;\n\n if (!functionSighashCache[input]) {\n functionSighashCache[input] = hexDataSlice(\n id(FunctionFragment.fromString(input).format()),\n 0,\n 4,\n );\n }\n\n return functionSighashCache[input];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/utils/string.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventFragment, FunctionFragment, Interface } from '@ethersproject/abi';\nimport { isHexString, hexStripZeros, hexDataSlice } from '@ethersproject/bytes';\nimport { id } from '@ethersproject/hash';\n\nexport function stringNormalizedEq(a: string, b?: string): boolean {\n return a.toLowerCase() === b?.toLowerCase();\n}\n\nexport function hexStringEq(a: string, b: string): boolean {\n if (!isHexString(a) || !isHexString(b)) {\n throw new Error('Inputs are not hex strings');\n }\n return stringNormalizedEq(hexStripZeros(a), hexStripZeros(b));\n}\n\nconst eventTopicsCache: Record<string, string> = {};\nconst functionSighashCache: Record<string, string> = {};\n\nexport interface AbiCustomType {\n name: string;\n type: 'enum' | 'struct';\n resolvedType: string;\n}\n\nexport function extractCustomTypesFromAbi(\n abiInterface: Interface,\n): Map<string, AbiCustomType> {\n const customTypes = new Map<string, AbiCustomType>();\n\n try {\n // Process event fragments\n Object.values(abiInterface.events).forEach(\n (eventFragment: EventFragment) => {\n eventFragment.inputs.forEach((input) => {\n extractCustomTypeFromInput(input, customTypes);\n });\n },\n );\n\n // Process function fragments\n Object.values(abiInterface.functions).forEach(\n (functionFragment: FunctionFragment) => {\n functionFragment.inputs.forEach((input) => {\n extractCustomTypeFromInput(input, customTypes);\n });\n },\n );\n } catch (error) {\n // Silently handle extraction errors in runtime\n }\n\n return customTypes;\n}\n\nfunction extractCustomTypeFromInput(\n input: { type: string; internalType?: string; components?: any[] },\n customTypes: Map<string, AbiCustomType>,\n): void {\n // Handle tuple types (structs)\n if (input.type === 'tuple' && input.internalType) {\n // Extract struct name from internal type (e.g., \"struct MoreData\" -> \"MoreData\", \"contract.MoreData\" -> \"MoreData\")\n const structName = input.internalType\n .replace(/^struct\\s+/, '') // Remove \"struct \" prefix\n .replace(/^.*\\./, ''); // Remove contract prefix if present (e.g., \"contract.Name\" -> \"Name\")\n\n if (!customTypes.has(structName) && input.components) {\n const tupleType = `(${input.components\n .map((comp: any) => resolveBaseType(comp.type))\n .join(',')})`;\n customTypes.set(structName, {\n name: structName,\n type: 'struct',\n resolvedType: tupleType,\n });\n }\n }\n\n // Handle enum types - look for custom internal types that aren't standard solidity types\n if (input.internalType && input.internalType !== input.type) {\n // Extract enum name from internal type (e.g., \"enum DisputeType\" -> \"DisputeType\", \"contract.DisputeType\" -> \"DisputeType\")\n const enumName = input.internalType\n .replace(/^enum\\s+/, '') // Remove \"enum \" prefix\n .replace(/^.*\\./, ''); // Remove contract prefix if present (e.g., \"contract.Name\" -> \"Name\")\n\n // Check if it's likely an enum (uint8/uint256 type with custom internal type)\n if (\n (input.type === 'uint8' || input.type === 'uint256') &&\n !enumName.startsWith('struct ') &&\n !isStandardSolidityType(enumName)\n ) {\n if (!customTypes.has(enumName)) {\n customTypes.set(enumName, {\n name: enumName,\n type: 'enum',\n resolvedType: 'uint8',\n });\n }\n }\n }\n\n // Recursively handle components for nested tuples\n if (input.components) {\n input.components.forEach((comp: any) => {\n extractCustomTypeFromInput(comp, customTypes);\n });\n }\n}\n\nfunction resolveBaseType(type: string): string {\n // Map common type aliases to their canonical forms\n const typeMapping: Record<string, string> = {\n uint: 'uint256',\n int: 'int256',\n };\n return typeMapping[type] || type;\n}\n\nfunction isStandardSolidityType(type: string): boolean {\n const standardTypes = [\n 'address',\n 'bool',\n 'string',\n 'bytes',\n // uint variants\n 'uint',\n 'uint8',\n 'uint16',\n 'uint24',\n 'uint32',\n 'uint40',\n 'uint48',\n 'uint56',\n 'uint64',\n 'uint72',\n 'uint80',\n 'uint88',\n 'uint96',\n 'uint104',\n 'uint112',\n 'uint120',\n 'uint128',\n 'uint136',\n 'uint144',\n 'uint152',\n 'uint160',\n 'uint168',\n 'uint176',\n 'uint184',\n 'uint192',\n 'uint200',\n 'uint208',\n 'uint216',\n 'uint224',\n 'uint232',\n 'uint240',\n 'uint248',\n 'uint256',\n // int variants\n 'int',\n 'int8',\n 'int16',\n 'int24',\n 'int32',\n 'int40',\n 'int48',\n 'int56',\n 'int64',\n 'int72',\n 'int80',\n 'int88',\n 'int96',\n 'int104',\n 'int112',\n 'int120',\n 'int128',\n 'int136',\n 'int144',\n 'int152',\n 'int160',\n 'int168',\n 'int176',\n 'int184',\n 'int192',\n 'int200',\n 'int208',\n 'int216',\n 'int224',\n 'int232',\n 'int240',\n 'int248',\n 'int256',\n // bytes variants\n 'bytes1',\n 'bytes2',\n 'bytes3',\n 'bytes4',\n 'bytes5',\n 'bytes6',\n 'bytes7',\n 'bytes8',\n 'bytes9',\n 'bytes10',\n 'bytes11',\n 'bytes12',\n 'bytes13',\n 'bytes14',\n 'bytes15',\n 'bytes16',\n 'bytes17',\n 'bytes18',\n 'bytes19',\n 'bytes20',\n 'bytes21',\n 'bytes22',\n 'bytes23',\n 'bytes24',\n 'bytes25',\n 'bytes26',\n 'bytes27',\n 'bytes28',\n 'bytes29',\n 'bytes30',\n 'bytes31',\n 'bytes32',\n ];\n\n // handle array types\n const baseType = type.replace(/\\[\\d*\\]$/, '');\n return standardTypes.includes(baseType);\n}\n\nexport function resolveCustomTypesInSignature(\n signature: string,\n customTypes: Map<string, AbiCustomType>,\n): string {\n let resolvedSignature = signature;\n\n // Replace custom types in the signature\n customTypes.forEach((customType, typeName) => {\n // Create regex to match the custom type name as a parameter type\n const regex = new RegExp(`\\\\b${escapeRegex(typeName)}\\\\b`, 'g');\n resolvedSignature = resolvedSignature.replace(\n regex,\n customType.resolvedType,\n );\n });\n\n return resolvedSignature;\n}\n\nfunction escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function eventToTopic(input: string): string {\n if (isHexString(input)) return input;\n\n if (!eventTopicsCache[input]) {\n const cleanedInput = input.replace(/\\bindexed\\b/g, '');\n eventTopicsCache[input] = id(\n EventFragment.fromString(cleanedInput).format(),\n );\n }\n\n return eventTopicsCache[input];\n}\n\nexport function functionToSighash(input: string): string {\n if (isHexString(input)) return input;\n\n if (!functionSighashCache[input]) {\n functionSighashCache[input] = hexDataSlice(\n id(FunctionFragment.fromString(input).format()),\n 0,\n 4,\n );\n }\n\n return functionSighashCache[input];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subql/node-ethereum",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Ian He",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@nestjs/platform-express": "^11.0.7",
|
|
26
26
|
"@nestjs/schedule": "^5.0.1",
|
|
27
27
|
"@subql/common": "^5.7.3",
|
|
28
|
-
"@subql/common-ethereum": "4.
|
|
28
|
+
"@subql/common-ethereum": "4.10.0",
|
|
29
29
|
"@subql/node-core": "^18.3.1",
|
|
30
30
|
"@subql/testing": "^2.2.1",
|
|
31
31
|
"@subql/types-ethereum": "4.2.2",
|
|
@@ -69,6 +69,5 @@
|
|
|
69
69
|
"README.md",
|
|
70
70
|
"CHANGELOG.md",
|
|
71
71
|
"LICENSE"
|
|
72
|
-
]
|
|
73
|
-
"stableVersion": "6.2.1"
|
|
72
|
+
]
|
|
74
73
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
6
|
-
const blockchain_service_1 = require("./blockchain.service");
|
|
7
|
-
const ethereum_1 = require("./ethereum");
|
|
8
|
-
const HTTP_ENDPOINT = 'https://ethereum.rpc.subquery.network/public';
|
|
9
|
-
const mockApiService = () => {
|
|
10
|
-
const ethApi = new ethereum_1.EthereumApi(HTTP_ENDPOINT, 20, new event_emitter_1.EventEmitter2());
|
|
11
|
-
// await ethApi.init();
|
|
12
|
-
return {
|
|
13
|
-
unsafeApi: ethApi,
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
describe('BlockchainService', () => {
|
|
17
|
-
let blockchainService;
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
const apiService = mockApiService();
|
|
20
|
-
blockchainService = new blockchain_service_1.BlockchainService(apiService);
|
|
21
|
-
});
|
|
22
|
-
it('can get a block timestamps', async () => {
|
|
23
|
-
const timestamp = await blockchainService.getBlockTimestamp(4_000_000);
|
|
24
|
-
expect(timestamp).toEqual(new Date('2017-07-09T20:52:47.000Z'));
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
//# sourceMappingURL=blockchain.service.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blockchain.service.test.js","sourceRoot":"","sources":["../src/blockchain.service.test.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAEnC,yDAAsD;AACtD,6DAAyD;AACzD,yCAA6D;AAE7D,MAAM,aAAa,GAAG,8CAA8C,CAAC;AAErE,MAAM,cAAc,GAAG,GAAuB,EAAE;IAC9C,MAAM,MAAM,GAAG,IAAI,sBAAW,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,6BAAa,EAAE,CAAC,CAAC;IAEvE,uBAAuB;IAEvB,OAAO;QACL,SAAS,EAAE,MAAM;KACX,CAAC;AACX,CAAC,CAAC;AAEF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,iBAAoC,CAAC;IAEzC,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;QAEpC,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,UAAU,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEvE,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { BlockchainService } from './blockchain.service';\nimport { EthereumApi, EthereumApiService } from './ethereum';\n\nconst HTTP_ENDPOINT = 'https://ethereum.rpc.subquery.network/public';\n\nconst mockApiService = (): EthereumApiService => {\n const ethApi = new EthereumApi(HTTP_ENDPOINT, 20, new EventEmitter2());\n\n // await ethApi.init();\n\n return {\n unsafeApi: ethApi,\n } as any;\n};\n\ndescribe('BlockchainService', () => {\n let blockchainService: BlockchainService;\n\n beforeEach(() => {\n const apiService = mockApiService();\n\n blockchainService = new BlockchainService(apiService);\n });\n\n it('can get a block timestamps', async () => {\n const timestamp = await blockchainService.getBlockTimestamp(4_000_000);\n\n expect(timestamp).toEqual(new Date('2017-07-09T20:52:47.000Z'));\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
-
};
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
10
|
-
const common_ethereum_1 = require("@subql/common-ethereum");
|
|
11
|
-
const types_ethereum_1 = require("@subql/types-ethereum");
|
|
12
|
-
const api_ethereum_1 = require("./api.ethereum");
|
|
13
|
-
const block_ethereum_1 = require("./block.ethereum");
|
|
14
|
-
// Add api key to work
|
|
15
|
-
const HTTP_ENDPOINT = 'https://ethereum-rpc.publicnode.com';
|
|
16
|
-
const BLOCK_CONFIRMATIONS = 20;
|
|
17
|
-
const MOONBEAM_ENDPOINT = 'https://rpc.api.moonbeam.network';
|
|
18
|
-
const ds = {
|
|
19
|
-
mapping: {
|
|
20
|
-
file: '',
|
|
21
|
-
handlers: [
|
|
22
|
-
{
|
|
23
|
-
handler: 'test',
|
|
24
|
-
kind: types_ethereum_1.EthereumHandlerKind.Call,
|
|
25
|
-
filter: { function: '0x23b872dd' },
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
kind: types_ethereum_1.EthereumDatasourceKind.Runtime,
|
|
30
|
-
startBlock: 16258633,
|
|
31
|
-
options: { abi: 'erc721' },
|
|
32
|
-
assets: new Map([
|
|
33
|
-
['erc721', { file: path_1.default.join(__dirname, '../../test/erc721.json') }],
|
|
34
|
-
]),
|
|
35
|
-
};
|
|
36
|
-
jest.setTimeout(90000);
|
|
37
|
-
describe('Api.ethereum', () => {
|
|
38
|
-
let ethApi;
|
|
39
|
-
const eventEmitter = new event_emitter_1.EventEmitter2();
|
|
40
|
-
let blockData;
|
|
41
|
-
const fetchBlock = async (height) => {
|
|
42
|
-
const block = await ethApi.fetchBlock(height);
|
|
43
|
-
return block.block;
|
|
44
|
-
};
|
|
45
|
-
beforeEach(async () => {
|
|
46
|
-
ethApi = new api_ethereum_1.EthereumApi(HTTP_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
47
|
-
await ethApi.init();
|
|
48
|
-
blockData = await fetchBlock(16258633);
|
|
49
|
-
});
|
|
50
|
-
it('Should format transaction in logs, and the transaction gas should be bigInt type', () => {
|
|
51
|
-
expect(typeof blockData.logs[0].transaction.gas).toBe('bigint');
|
|
52
|
-
expect(typeof blockData.logs[0].transaction.blockNumber).toBe('number');
|
|
53
|
-
expect(typeof blockData.logs[0].transaction.gasPrice).toBe('bigint');
|
|
54
|
-
expect(typeof blockData.logs[0].transaction.maxPriorityFeePerGas).toBe('bigint');
|
|
55
|
-
expect(typeof blockData.logs[0].transaction.transactionIndex).toBe('bigint');
|
|
56
|
-
});
|
|
57
|
-
it('should have the ability to get receipts via transactions from all types', () => {
|
|
58
|
-
expect(typeof blockData.transactions[0].receipt).toEqual('function');
|
|
59
|
-
expect(typeof blockData.logs[0].transaction.receipt).toEqual('function');
|
|
60
|
-
expect(typeof blockData.logs[0].transaction.from).toEqual('string');
|
|
61
|
-
expect(typeof blockData.transactions[81].logs[0].transaction.from).toEqual('string');
|
|
62
|
-
expect(typeof blockData.transactions[81].logs[0].transaction.receipt).toEqual('function');
|
|
63
|
-
});
|
|
64
|
-
it('Decode nested logs in transactions', async () => {
|
|
65
|
-
// Erc721
|
|
66
|
-
const tx = blockData.transactions.find((e) => e.hash ===
|
|
67
|
-
'0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc');
|
|
68
|
-
const parsedTx = await ethApi.parseTransaction(tx, ds);
|
|
69
|
-
expect(parsedTx.logs[0].args).toBeTruthy();
|
|
70
|
-
});
|
|
71
|
-
it('Should decode transaction data and not clone object', async () => {
|
|
72
|
-
const tx = blockData.transactions.find((e) => e.hash ===
|
|
73
|
-
'0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc');
|
|
74
|
-
const parsedTx = await ethApi.parseTransaction(tx, ds);
|
|
75
|
-
expect(parsedTx).toBe(tx);
|
|
76
|
-
});
|
|
77
|
-
it('Should return raw logs, if decode fails', async () => {
|
|
78
|
-
// not Erc721
|
|
79
|
-
const tx = blockData.transactions.find((e) => e.hash ===
|
|
80
|
-
'0xed62f7a7720fe6ae05dec45ad9dd4f53034a0aae2c140d229b1151504ee9a6c9');
|
|
81
|
-
const parsedLog = await ethApi.parseLog(tx.logs[0], ds);
|
|
82
|
-
expect(parsedLog).not.toHaveProperty('args');
|
|
83
|
-
expect(parsedLog).toBeTruthy();
|
|
84
|
-
});
|
|
85
|
-
// This test is here to ensure getters aren't removed
|
|
86
|
-
it('Should not clone logs when parsing args', async () => {
|
|
87
|
-
const log = blockData.transactions.find((e) => e.hash ===
|
|
88
|
-
'0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc').logs[1];
|
|
89
|
-
const parsedLog = await ethApi.parseLog(log, ds);
|
|
90
|
-
expect(parsedLog).toBe(log);
|
|
91
|
-
});
|
|
92
|
-
it('Null filter support', async () => {
|
|
93
|
-
ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
94
|
-
await ethApi.init();
|
|
95
|
-
blockData = await fetchBlock(2847447);
|
|
96
|
-
const result = blockData.transactions.filter((tx) => {
|
|
97
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { to: null }, '0x72a33394f0652e2bf15d7901f3cd46863d968424')) {
|
|
98
|
-
return tx.hash;
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
expect(result[0].hash).toBe('0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05');
|
|
102
|
-
expect(result.length).toBe(1);
|
|
103
|
-
});
|
|
104
|
-
it('!null filter support for logs, expect to filter out', async () => {
|
|
105
|
-
ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
106
|
-
await ethApi.init();
|
|
107
|
-
const filter_1 = {
|
|
108
|
-
topics: [
|
|
109
|
-
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
|
|
110
|
-
undefined,
|
|
111
|
-
undefined,
|
|
112
|
-
common_ethereum_1.NOT_NULL_FILTER,
|
|
113
|
-
],
|
|
114
|
-
};
|
|
115
|
-
const filter_2 = {
|
|
116
|
-
topics: [
|
|
117
|
-
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
|
|
118
|
-
],
|
|
119
|
-
};
|
|
120
|
-
blockData = await fetchBlock(4015990);
|
|
121
|
-
const transaction = blockData.transactions.find((tx) => tx.hash ===
|
|
122
|
-
'0xeb2e443f2d4e784193fa13bbbae2b85e6ee459e7b7b53f8ca098ffae9b25b059');
|
|
123
|
-
const erc20Transfers = transaction.logs.filter((log) => (0, block_ethereum_1.filterLogsProcessor)(log, filter_2));
|
|
124
|
-
const erc721Transfers = transaction.logs.filter((log) => (0, block_ethereum_1.filterLogsProcessor)(log, filter_1));
|
|
125
|
-
expect(erc20Transfers.length).toBe(7);
|
|
126
|
-
expect(erc721Transfers.length).toBe(2);
|
|
127
|
-
});
|
|
128
|
-
it('Null and 0x (empty) filter support for transaction data', async () => {
|
|
129
|
-
const beamEndpoint = 'https://mainnet.base.org/';
|
|
130
|
-
ethApi = new api_ethereum_1.EthereumApi(beamEndpoint, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
131
|
-
await ethApi.init();
|
|
132
|
-
blockData = await fetchBlock(1104962);
|
|
133
|
-
// blockData.transactions[0].to = undefined;
|
|
134
|
-
const result = blockData.transactions.filter((tx) => {
|
|
135
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { function: null })) {
|
|
136
|
-
return tx.hash;
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
expect(result.length).toBe(1);
|
|
140
|
-
expect(result[0].hash).toBe('0x182c5381f8fa3332a7bd676b1c819a15119972db52bd5210afead88f18fff642');
|
|
141
|
-
const result2 = blockData.transactions.filter((tx) => {
|
|
142
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { function: '0x' })) {
|
|
143
|
-
return tx.hash;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
expect(result2.length).toBe(1);
|
|
147
|
-
expect(result2[0].hash).toBe('0x182c5381f8fa3332a7bd676b1c819a15119972db52bd5210afead88f18fff642');
|
|
148
|
-
});
|
|
149
|
-
it('Null filter support, for undefined transaction.to', async () => {
|
|
150
|
-
ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
151
|
-
await ethApi.init();
|
|
152
|
-
blockData = await fetchBlock(2847447);
|
|
153
|
-
blockData.transactions[1].to = undefined;
|
|
154
|
-
const result = blockData.transactions.filter((tx) => {
|
|
155
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { to: null }, '0x72a33394f0652e2bf15d7901f3cd46863d968424')) {
|
|
156
|
-
return tx.hash;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
expect(result[0].hash).toBe('0x24bef923522a4d6a79f9ab9242a74fb987dce94002c0f107c2a7d0b7e24bcf05');
|
|
160
|
-
expect(result.length).toBe(1);
|
|
161
|
-
});
|
|
162
|
-
it('Should return all tx if filter.to is not defined', async () => {
|
|
163
|
-
ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
164
|
-
await ethApi.init();
|
|
165
|
-
blockData = await fetchBlock(2847447);
|
|
166
|
-
const result = blockData.transactions.filter((tx) => {
|
|
167
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, undefined, '0x72a33394f0652e2bf15d7901f3cd46863d968424')) {
|
|
168
|
-
return tx.hash;
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
expect(result.length).toBe(2);
|
|
172
|
-
});
|
|
173
|
-
it('filter.to Should support only null not undefined', async () => {
|
|
174
|
-
ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
175
|
-
await ethApi.init();
|
|
176
|
-
blockData = await fetchBlock(2847447);
|
|
177
|
-
const result = blockData.transactions.filter((tx) => {
|
|
178
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { to: undefined }, '0x72a33394f0652e2bf15d7901f3cd46863d968424')) {
|
|
179
|
-
return tx.hash;
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
expect(result.length).toBe(0);
|
|
183
|
-
});
|
|
184
|
-
it('If transaction is undefined, with null filter, should be supported', async () => {
|
|
185
|
-
ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
186
|
-
await ethApi.init();
|
|
187
|
-
blockData = await fetchBlock(2847447);
|
|
188
|
-
const result = blockData.transactions.filter((tx) => {
|
|
189
|
-
tx.to = undefined;
|
|
190
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { to: null }, '0x72a33394f0652e2bf15d7901f3cd46863d968424')) {
|
|
191
|
-
return tx.hash;
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
expect(result.length).toBe(2);
|
|
195
|
-
});
|
|
196
|
-
it('Filters transaction type correctly', async () => {
|
|
197
|
-
blockData = await fetchBlock(22678424);
|
|
198
|
-
const result = blockData.transactions.filter((tx) => {
|
|
199
|
-
if ((0, block_ethereum_1.filterTransactionsProcessor)(tx, { type: '0x3' })) {
|
|
200
|
-
return tx.hash;
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
expect(result.length).toBe(3);
|
|
204
|
-
expect(result[1].hash).toBe('0x6ae305d4cc361c24b24953b59a84a9ea5cb02792d3ad1576c1e2b81a456169db');
|
|
205
|
-
});
|
|
206
|
-
it.each([
|
|
207
|
-
// TODO all these networs now support finalization tags, need to find one that does not
|
|
208
|
-
[HTTP_ENDPOINT, true],
|
|
209
|
-
[MOONBEAM_ENDPOINT, true],
|
|
210
|
-
['https://binance.llamarpc.com', true],
|
|
211
|
-
['https://polygon-rpc.com', true],
|
|
212
|
-
])('Resolve the correct finalization tags for %s', async (endpoint, finalization) => {
|
|
213
|
-
ethApi = new api_ethereum_1.EthereumApi(endpoint, BLOCK_CONFIRMATIONS, eventEmitter);
|
|
214
|
-
await ethApi.init();
|
|
215
|
-
expect(ethApi.supportsFinalization).toEqual(finalization);
|
|
216
|
-
});
|
|
217
|
-
it('Assert blockHash on logs and block', async () => {
|
|
218
|
-
ethApi = new api_ethereum_1.EthereumApi('https://rpc.ankr.com/xdc', BLOCK_CONFIRMATIONS, eventEmitter);
|
|
219
|
-
await ethApi.init();
|
|
220
|
-
const mockBlockNumber = 72194336;
|
|
221
|
-
const mockBlockHash = 'mockBlockHash';
|
|
222
|
-
const mockIncorrectBlockHash = 'mockIncorrectBlockHash';
|
|
223
|
-
jest.spyOn(ethApi, 'getBlockPromise').mockResolvedValueOnce({
|
|
224
|
-
hash: mockBlockHash,
|
|
225
|
-
transactions: [],
|
|
226
|
-
});
|
|
227
|
-
jest.spyOn(ethApi.client, 'getLogs').mockResolvedValueOnce([
|
|
228
|
-
{
|
|
229
|
-
blockNumber: '0x1831a96',
|
|
230
|
-
blockHash: mockIncorrectBlockHash,
|
|
231
|
-
transactionHash: 'tx1',
|
|
232
|
-
logIndex: '0x0',
|
|
233
|
-
},
|
|
234
|
-
]);
|
|
235
|
-
await expect(ethApi.fetchBlock(mockBlockNumber)).rejects.toThrow(`Log BlockHash does not match block: 72194336, blockHash mockBlockHash. Log 0 got block 25369238 blockHash mockIncorrectBlockHash. Please check with rpc provider`);
|
|
236
|
-
});
|
|
237
|
-
it('Should able to check is fullBlock', async () => {
|
|
238
|
-
// block with transactions
|
|
239
|
-
const lightBlock = (await ethApi.fetchLightBlock(16258633)).block;
|
|
240
|
-
expect((0, block_ethereum_1.isFullBlock)(blockData)).toBeTruthy();
|
|
241
|
-
expect((0, block_ethereum_1.isFullBlock)(lightBlock)).toBeFalsy();
|
|
242
|
-
// block with transactions, but no logs 4913287
|
|
243
|
-
const noLogBlockData = (await ethApi.fetchBlock(4913287)).block;
|
|
244
|
-
expect((0, block_ethereum_1.isFullBlock)(noLogBlockData)).toBeTruthy();
|
|
245
|
-
// block without transaction
|
|
246
|
-
const block10001 = (await ethApi.fetchBlock(10001)).block;
|
|
247
|
-
const lightBlock10001 = (await ethApi.fetchLightBlock(10001))
|
|
248
|
-
.block;
|
|
249
|
-
expect((0, block_ethereum_1.isFullBlock)(block10001)).toBeFalsy();
|
|
250
|
-
expect((0, block_ethereum_1.isFullBlock)(lightBlock10001)).toBeFalsy();
|
|
251
|
-
});
|
|
252
|
-
it('Should have the ERC-4844 Fields', async () => {
|
|
253
|
-
blockData = await fetchBlock(22678424);
|
|
254
|
-
expect(blockData.blobGasUsed).toBe(655360n);
|
|
255
|
-
expect(blockData.excessBlobGas).toBe(0n);
|
|
256
|
-
const tx = blockData.transactions.find((tx) => tx.hash ===
|
|
257
|
-
'0x6ae305d4cc361c24b24953b59a84a9ea5cb02792d3ad1576c1e2b81a456169db');
|
|
258
|
-
expect(tx.blobVersionedHashes).toEqual([
|
|
259
|
-
'0x017c682fba2cea00c4ad7ed2888ed2eb7116595e6a995500bd105e842b041340',
|
|
260
|
-
'0x01585afe4cada3a77e5f07c73fb4d10e0a908ad22e7af13ff988569b842de17a',
|
|
261
|
-
'0x01248e92f9bec9ee102717029519bc38cda783a7df3b70d90e86ef4d8ead450c',
|
|
262
|
-
]);
|
|
263
|
-
expect(tx.maxFeePerBlobGas).toEqual(1000000000n);
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
//# sourceMappingURL=api.ethereum.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport path from 'path';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { NOT_NULL_FILTER } from '@subql/common-ethereum';\nimport {\n EthereumBlock,\n EthereumDatasourceKind,\n EthereumHandlerKind,\n EthereumLogFilter,\n SubqlRuntimeDatasource,\n} from '@subql/types-ethereum';\nimport { EthereumApi } from './api.ethereum';\nimport {\n filterLogsProcessor,\n filterTransactionsProcessor,\n isFullBlock,\n} from './block.ethereum';\n\n// Add api key to work\nconst HTTP_ENDPOINT = 'https://ethereum-rpc.publicnode.com';\nconst BLOCK_CONFIRMATIONS = 20;\nconst MOONBEAM_ENDPOINT = 'https://rpc.api.moonbeam.network';\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: new Map([\n ['erc721', { file: path.join(__dirname, '../../test/erc721.json') }],\n ]),\n};\n\njest.setTimeout(90000);\ndescribe('Api.ethereum', () => {\n let ethApi: EthereumApi;\n const eventEmitter = new EventEmitter2();\n let blockData: EthereumBlock;\n\n const fetchBlock = async (height: number) => {\n const block = await ethApi.fetchBlock(height);\n\n return block.block as EthereumBlock;\n };\n\n beforeEach(async () => {\n ethApi = new EthereumApi(HTTP_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);\n await ethApi.init();\n blockData = await fetchBlock(16258633);\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('should have the ability to get receipts via transactions from all types', () => {\n expect(typeof blockData.transactions[0].receipt).toEqual('function');\n expect(typeof blockData.logs[0].transaction.receipt).toEqual('function');\n expect(typeof blockData.logs[0].transaction.from).toEqual('string');\n expect(typeof blockData.transactions[81].logs![0].transaction.from).toEqual(\n 'string',\n );\n expect(\n typeof blockData.transactions[81].logs![0].transaction.receipt,\n ).toEqual('function');\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 decode transaction data and not clone object', async () => {\n const tx = blockData.transactions.find(\n (e) =>\n e.hash ===\n '0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc',\n );\n const parsedTx = await ethApi.parseTransaction(tx!, ds);\n\n expect(parsedTx).toBe(tx);\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\n // This test is here to ensure getters aren't removed\n it('Should not clone logs when parsing args', async () => {\n const log = blockData.transactions.find(\n (e) =>\n e.hash ===\n '0x8e419d0e36d7f9c099a001fded516bd168edd9d27b4aec2bcd56ba3b3b955ccc',\n )!.logs![1];\n\n const parsedLog = await ethApi.parseLog(log, ds);\n expect(parsedLog).toBe(log);\n });\n\n it('Null filter support', async () => {\n ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n blockData = await fetchBlock(2847447);\n const result = blockData.transactions.filter((tx) => {\n if (\n 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 ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n const filter_1: EthereumLogFilter = {\n topics: [\n '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',\n undefined,\n undefined,\n NOT_NULL_FILTER,\n ],\n };\n\n const filter_2: EthereumLogFilter = {\n topics: [\n '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',\n ],\n };\n\n blockData = await fetchBlock(4015990);\n const transaction = blockData.transactions.find(\n (tx) =>\n tx.hash ===\n '0xeb2e443f2d4e784193fa13bbbae2b85e6ee459e7b7b53f8ca098ffae9b25b059',\n )!;\n\n const erc20Transfers = transaction.logs!.filter((log) =>\n filterLogsProcessor(log, filter_2),\n );\n const erc721Transfers = transaction.logs!.filter((log) =>\n filterLogsProcessor(log, filter_1),\n );\n\n expect(erc20Transfers.length).toBe(7);\n expect(erc721Transfers.length).toBe(2);\n });\n\n it('Null and 0x (empty) filter support for transaction data', async () => {\n const beamEndpoint = 'https://mainnet.base.org/';\n ethApi = new EthereumApi(beamEndpoint, BLOCK_CONFIRMATIONS, eventEmitter);\n await ethApi.init();\n blockData = await fetchBlock(1104962);\n // blockData.transactions[0].to = undefined;\n const result = blockData.transactions.filter((tx) => {\n if (filterTransactionsProcessor(tx, { function: null })) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(1);\n expect(result[0].hash).toBe(\n '0x182c5381f8fa3332a7bd676b1c819a15119972db52bd5210afead88f18fff642',\n );\n\n const result2 = blockData.transactions.filter((tx) => {\n if (filterTransactionsProcessor(tx, { function: '0x' })) {\n return tx.hash;\n }\n });\n expect(result2.length).toBe(1);\n expect(result2[0].hash).toBe(\n '0x182c5381f8fa3332a7bd676b1c819a15119972db52bd5210afead88f18fff642',\n );\n });\n\n it('Null filter support, for undefined transaction.to', async () => {\n ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n blockData = await fetchBlock(2847447);\n blockData.transactions[1].to = undefined;\n const result = blockData.transactions.filter((tx) => {\n if (\n 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 ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n blockData = await fetchBlock(2847447);\n const result = blockData.transactions.filter((tx) => {\n if (\n 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 ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n blockData = await fetchBlock(2847447);\n const result = blockData.transactions.filter((tx) => {\n if (\n filterTransactionsProcessor(\n tx,\n { to: undefined },\n '0x72a33394f0652e2bf15d7901f3cd46863d968424',\n )\n ) {\n return tx.hash;\n }\n });\n expect(result.length).toBe(0);\n });\n\n it('If transaction is undefined, with null filter, should be supported', async () => {\n ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n blockData = await fetchBlock(2847447);\n const result = blockData.transactions.filter((tx) => {\n tx.to = undefined;\n if (\n 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('Filters transaction type correctly', async () => {\n blockData = await fetchBlock(22678424);\n const result = blockData.transactions.filter((tx) => {\n if (filterTransactionsProcessor(tx, { type: '0x3' })) {\n return tx.hash;\n }\n });\n\n expect(result.length).toBe(3);\n expect(result[1].hash).toBe(\n '0x6ae305d4cc361c24b24953b59a84a9ea5cb02792d3ad1576c1e2b81a456169db',\n );\n });\n\n it.each([\n // TODO all these networs now support finalization tags, need to find one that does not\n [HTTP_ENDPOINT, true],\n [MOONBEAM_ENDPOINT, true],\n ['https://binance.llamarpc.com', true],\n ['https://polygon-rpc.com', true],\n ])(\n 'Resolve the correct finalization tags for %s',\n async (endpoint, finalization) => {\n ethApi = new EthereumApi(endpoint, BLOCK_CONFIRMATIONS, eventEmitter);\n await ethApi.init();\n\n expect(ethApi.supportsFinalization).toEqual(finalization);\n },\n );\n\n it('Assert blockHash on logs and block', async () => {\n ethApi = new EthereumApi(\n 'https://rpc.ankr.com/xdc',\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n\n const mockBlockNumber = 72194336;\n const mockBlockHash = 'mockBlockHash';\n const mockIncorrectBlockHash = 'mockIncorrectBlockHash';\n\n jest.spyOn(ethApi as any, 'getBlockPromise').mockResolvedValueOnce({\n hash: mockBlockHash,\n transactions: [],\n });\n\n jest.spyOn((ethApi as any).client, 'getLogs').mockResolvedValueOnce([\n {\n blockNumber: '0x1831a96',\n blockHash: mockIncorrectBlockHash,\n transactionHash: 'tx1',\n logIndex: '0x0',\n },\n ]);\n\n await expect(ethApi.fetchBlock(mockBlockNumber)).rejects.toThrow(\n `Log BlockHash does not match block: 72194336, blockHash mockBlockHash. Log 0 got block 25369238 blockHash mockIncorrectBlockHash. Please check with rpc provider`,\n );\n });\n\n it('Should able to check is fullBlock', async () => {\n // block with transactions\n const lightBlock = (await (ethApi as any).fetchLightBlock(16258633)).block;\n expect(isFullBlock(blockData)).toBeTruthy();\n expect(isFullBlock(lightBlock)).toBeFalsy();\n\n // block with transactions, but no logs 4913287\n const noLogBlockData = (await (ethApi as any).fetchBlock(4913287)).block;\n expect(isFullBlock(noLogBlockData)).toBeTruthy();\n\n // block without transaction\n const block10001 = (await (ethApi as any).fetchBlock(10001)).block;\n const lightBlock10001 = (await (ethApi as any).fetchLightBlock(10001))\n .block;\n expect(isFullBlock(block10001)).toBeFalsy();\n expect(isFullBlock(lightBlock10001)).toBeFalsy();\n });\n\n it('Should have the ERC-4844 Fields', async () => {\n blockData = await fetchBlock(22678424);\n\n expect(blockData.blobGasUsed).toBe(655360n);\n expect(blockData.excessBlobGas).toBe(0n);\n\n const tx = blockData.transactions.find(\n (tx) =>\n tx.hash ===\n '0x6ae305d4cc361c24b24953b59a84a9ea5cb02792d3ad1576c1e2b81a456169db',\n )!;\n\n expect(tx.blobVersionedHashes).toEqual([\n '0x017c682fba2cea00c4ad7ed2888ed2eb7116595e6a995500bd105e842b041340',\n '0x01585afe4cada3a77e5f07c73fb4d10e0a908ad22e7af13ff988569b842de17a',\n '0x01248e92f9bec9ee102717029519bc38cda783a7df3b70d90e86ef4d8ead450c',\n ]);\n expect(tx.maxFeePerBlobGas).toEqual(1000000000n);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
6
|
-
const testing_1 = require("@nestjs/testing");
|
|
7
|
-
const node_core_1 = require("@subql/node-core");
|
|
8
|
-
const graphql_1 = require("graphql");
|
|
9
|
-
const lodash_1 = require("lodash");
|
|
10
|
-
const api_service_ethereum_1 = require("./api.service.ethereum");
|
|
11
|
-
// Add api key to work
|
|
12
|
-
const HTTP_ENDPOINT = 'https://eth.llamarpc.com';
|
|
13
|
-
function testSubqueryProject(endpoint) {
|
|
14
|
-
return {
|
|
15
|
-
network: {
|
|
16
|
-
endpoint: [endpoint],
|
|
17
|
-
chainId: '1',
|
|
18
|
-
},
|
|
19
|
-
dataSources: [],
|
|
20
|
-
id: 'test',
|
|
21
|
-
root: './',
|
|
22
|
-
schema: new graphql_1.GraphQLSchema({}),
|
|
23
|
-
templates: [],
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
const prepareApiService = async (endpoint = HTTP_ENDPOINT) => {
|
|
27
|
-
const module = await testing_1.Test.createTestingModule({
|
|
28
|
-
providers: [
|
|
29
|
-
node_core_1.ConnectionPoolService,
|
|
30
|
-
node_core_1.ConnectionPoolStateManager,
|
|
31
|
-
{
|
|
32
|
-
provide: node_core_1.NodeConfig,
|
|
33
|
-
useFactory: () => ({}),
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
provide: 'ISubqueryProject',
|
|
37
|
-
useFactory: () => testSubqueryProject(endpoint),
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
provide: api_service_ethereum_1.EthereumApiService,
|
|
41
|
-
useFactory: api_service_ethereum_1.EthereumApiService.init,
|
|
42
|
-
inject: [
|
|
43
|
-
'ISubqueryProject',
|
|
44
|
-
node_core_1.ConnectionPoolService,
|
|
45
|
-
event_emitter_1.EventEmitter2,
|
|
46
|
-
node_core_1.NodeConfig,
|
|
47
|
-
],
|
|
48
|
-
},
|
|
49
|
-
],
|
|
50
|
-
imports: [event_emitter_1.EventEmitterModule.forRoot()],
|
|
51
|
-
}).compile();
|
|
52
|
-
const app = module.createNestApplication();
|
|
53
|
-
await app.init();
|
|
54
|
-
const apiService = app.get(api_service_ethereum_1.EthereumApiService);
|
|
55
|
-
return [apiService, app];
|
|
56
|
-
};
|
|
57
|
-
jest.setTimeout(90000);
|
|
58
|
-
describe('ApiService', () => {
|
|
59
|
-
let apiService;
|
|
60
|
-
let app;
|
|
61
|
-
beforeEach(async () => {
|
|
62
|
-
[apiService, app] = await prepareApiService();
|
|
63
|
-
});
|
|
64
|
-
afterEach(async () => {
|
|
65
|
-
return app?.close();
|
|
66
|
-
});
|
|
67
|
-
it('can instantiate api', () => {
|
|
68
|
-
expect(apiService.api.getChainId()).toEqual(1);
|
|
69
|
-
});
|
|
70
|
-
it('can fetch blocks', async () => {
|
|
71
|
-
await expect(apiService.api.fetchBlocks((0, lodash_1.range)(12369621, 12369625))).resolves.toHaveLength(4);
|
|
72
|
-
});
|
|
73
|
-
it('can get the finalized height', async () => {
|
|
74
|
-
const height = (await apiService.api.getFinalizedBlock()).number;
|
|
75
|
-
console.log('Finalized height', height);
|
|
76
|
-
expect(height).toBeGreaterThan(16_000_000);
|
|
77
|
-
});
|
|
78
|
-
it('ensure api errorCode is exposed when throwing', async () => {
|
|
79
|
-
await expect(apiService
|
|
80
|
-
.safeApi(17520376)
|
|
81
|
-
.getCode('0x75F0398549C9fDEa03BbDde388361827cb376D5')).rejects.toHaveProperty('code', 'INVALID_ARGUMENT');
|
|
82
|
-
});
|
|
83
|
-
it('should not retry on any errors not in the retry list', async () => {
|
|
84
|
-
const callSpy = jest.spyOn(apiService.unsafeApi, 'getSafeApi');
|
|
85
|
-
await expect(apiService
|
|
86
|
-
.safeApi(17520376)
|
|
87
|
-
.getCode('0x75F0398549C9fDEa03BbDde388361827cb376D5')).rejects.toHaveProperty('code', 'INVALID_ARGUMENT');
|
|
88
|
-
expect(callSpy).toHaveBeenCalledTimes(1);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
//# sourceMappingURL=api.service.ethereum.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api.service.ethereum.test.js","sourceRoot":"","sources":["../../src/ethereum/api.service.ethereum.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { INestApplication } from '@nestjs/common';\nimport { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';\nimport { Test } from '@nestjs/testing';\nimport {\n ConnectionPoolService,\n ConnectionPoolStateManager,\n NodeConfig,\n} from '@subql/node-core';\nimport { GraphQLSchema } from 'graphql';\nimport { range } from 'lodash';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { EthereumApiService } from './api.service.ethereum';\n\n// Add api key to work\nconst HTTP_ENDPOINT = 'https://eth.llamarpc.com';\n\nfunction testSubqueryProject(endpoint: string): SubqueryProject {\n return {\n network: {\n endpoint: [endpoint],\n chainId: '1',\n },\n dataSources: [],\n id: 'test',\n root: './',\n schema: new GraphQLSchema({}),\n templates: [],\n } as any;\n}\n\nconst prepareApiService = async (\n endpoint: string = HTTP_ENDPOINT,\n): Promise<[EthereumApiService, INestApplication]> => {\n const module = await Test.createTestingModule({\n providers: [\n ConnectionPoolService,\n ConnectionPoolStateManager,\n {\n provide: NodeConfig,\n useFactory: () => ({}),\n },\n {\n provide: 'ISubqueryProject',\n useFactory: () => testSubqueryProject(endpoint),\n },\n {\n provide: EthereumApiService,\n useFactory: EthereumApiService.init,\n inject: [\n 'ISubqueryProject',\n ConnectionPoolService,\n EventEmitter2,\n NodeConfig,\n ],\n },\n ],\n imports: [EventEmitterModule.forRoot()],\n }).compile();\n\n const app = module.createNestApplication();\n await app.init();\n const apiService = app.get(EthereumApiService);\n return [apiService, app];\n};\n\njest.setTimeout(90000);\ndescribe('ApiService', () => {\n let apiService: EthereumApiService;\n let app: INestApplication;\n\n beforeEach(async () => {\n [apiService, app] = await prepareApiService();\n });\n\n afterEach(async () => {\n return app?.close();\n });\n\n it('can instantiate api', () => {\n expect(apiService.api.getChainId()).toEqual(1);\n });\n\n it('can fetch blocks', async () => {\n await expect(\n apiService.api.fetchBlocks(range(12369621, 12369625)),\n ).resolves.toHaveLength(4);\n });\n\n it('can get the finalized height', async () => {\n const height = (await apiService.api.getFinalizedBlock()).number;\n\n console.log('Finalized height', height);\n expect(height).toBeGreaterThan(16_000_000);\n });\n\n it('ensure api errorCode is exposed when throwing', async () => {\n await expect(\n apiService\n .safeApi(17520376)\n .getCode('0x75F0398549C9fDEa03BbDde388361827cb376D5'),\n ).rejects.toHaveProperty('code', 'INVALID_ARGUMENT');\n });\n it('should not retry on any errors not in the retry list', async () => {\n const callSpy = jest.spyOn(apiService.unsafeApi, 'getSafeApi');\n await expect(\n apiService\n .safeApi(17520376)\n .getCode('0x75F0398549C9fDEa03BbDde388361827cb376D5'),\n ).rejects.toHaveProperty('code', 'INVALID_ARGUMENT');\n\n expect(callSpy).toHaveBeenCalledTimes(1);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
const ethers_1 = require("ethers");
|
|
6
|
-
const utils_ethereum_1 = require("../../utils.ethereum");
|
|
7
|
-
const celo_provider_1 = require("./celo-provider");
|
|
8
|
-
const HTTP_ENDPOINT = 'https://forno.celo.org';
|
|
9
|
-
const TEST_BLOCK = 16068684;
|
|
10
|
-
describe('CeloRPCProviders', () => {
|
|
11
|
-
// For some reason defining this in before all fails
|
|
12
|
-
const providers = [
|
|
13
|
-
new celo_provider_1.CeloWsProvider('wss://forno.celo.org/ws'),
|
|
14
|
-
new celo_provider_1.CeloJsonRpcProvider(HTTP_ENDPOINT),
|
|
15
|
-
new celo_provider_1.CeloJsonRpcBatchProvider(HTTP_ENDPOINT),
|
|
16
|
-
];
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await Promise.all(providers.map((p) => p?.destroy?.()));
|
|
19
|
-
});
|
|
20
|
-
// This returns a value now, needs further investigation
|
|
21
|
-
it.skip.each(providers)('should set gasLimit to zero for blocks before the hard fork', async (provider) => {
|
|
22
|
-
const block = (0, utils_ethereum_1.formatBlock)(await provider.send('eth_getBlockByNumber', [
|
|
23
|
-
ethers_1.utils.hexValue(TEST_BLOCK),
|
|
24
|
-
true,
|
|
25
|
-
]));
|
|
26
|
-
expect(ethers_1.BigNumber.from(block.gasLimit)).toEqual(ethers_1.constants.Zero);
|
|
27
|
-
});
|
|
28
|
-
it.each(providers)('should not set gasLimit to zero for blocks after the hard fork', async (provider) => {
|
|
29
|
-
const block = (0, utils_ethereum_1.formatBlock)(await provider.send('eth_getBlockByNumber', ['latest', true]));
|
|
30
|
-
expect(ethers_1.BigNumber.from(block.gasLimit).gte(ethers_1.constants.Zero)).toBeTruthy();
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
//# sourceMappingURL=celo-ws-provider.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"celo-ws-provider.spec.js","sourceRoot":"","sources":["../../../../src/ethereum/ethers/celo/celo-ws-provider.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAGnC,mCAAqD;AACrD,yDAAmD;AACnD,mDAIyB;AAEzB,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC;AAE5B,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,oDAAoD;IACpD,MAAM,SAAS,GAAG;QAChB,IAAI,8BAAc,CAAC,yBAAyB,CAAC;QAC7C,IAAI,mCAAmB,CAAC,aAAa,CAAC;QACtC,IAAI,wCAAwB,CAAC,aAAa,CAAC;KAC5C,CAAC;IACF,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CACrB,6DAA6D,EAC7D,KAAK,EAAE,QAAQ,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,IAAA,4BAAW,EACvB,MAAM,QAAQ,CAAC,IAAI,CAAC,sBAAsB,EAAE;YAC1C,cAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC1B,IAAI;SACL,CAAC,CACH,CAAC;QACF,MAAM,CAAC,kBAAS,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAS,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC,CACF,CAAC;IAEF,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAChB,gEAAgE,EAChE,KAAK,EAAE,QAAQ,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,IAAA,4BAAW,EACvB,MAAM,QAAQ,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAC9D,CAAC;QACF,MAAM,CAAC,kBAAS,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,kBAAS,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IAC1E,CAAC,CACF,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { WebSocketProvider } from '@ethersproject/providers';\nimport { BigNumber, constants, utils } from 'ethers';\nimport { formatBlock } from '../../utils.ethereum';\nimport {\n CeloJsonRpcBatchProvider,\n CeloJsonRpcProvider,\n CeloWsProvider,\n} from './celo-provider';\n\nconst HTTP_ENDPOINT = 'https://forno.celo.org';\nconst TEST_BLOCK = 16068684;\n\ndescribe('CeloRPCProviders', () => {\n // For some reason defining this in before all fails\n const providers = [\n new CeloWsProvider('wss://forno.celo.org/ws'),\n new CeloJsonRpcProvider(HTTP_ENDPOINT),\n new CeloJsonRpcBatchProvider(HTTP_ENDPOINT),\n ];\n afterAll(async () => {\n await Promise.all(providers.map((p) => (p as any)?.destroy?.()));\n });\n\n // This returns a value now, needs further investigation\n it.skip.each(providers)(\n 'should set gasLimit to zero for blocks before the hard fork',\n async (provider) => {\n const block = formatBlock(\n await provider.send('eth_getBlockByNumber', [\n utils.hexValue(TEST_BLOCK),\n true,\n ]),\n );\n expect(BigNumber.from(block.gasLimit)).toEqual(constants.Zero);\n },\n );\n\n it.each(providers)(\n 'should not set gasLimit to zero for blocks after the hard fork',\n async (provider) => {\n const block = formatBlock(\n await provider.send('eth_getBlockByNumber', ['latest', true]),\n );\n expect(BigNumber.from(block.gasLimit).gte(constants.Zero)).toBeTruthy();\n },\n );\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|