@subql/node-ethereum 6.2.1 → 6.2.2-1
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 +3 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/configure/SubqueryProject.js +7 -0
- package/dist/configure/SubqueryProject.js.map +1 -1
- package/dist/utils/project.d.ts +14 -1
- package/dist/utils/project.js +100 -0
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/string.d.ts +8 -0
- package/dist/utils/string.js +202 -1
- package/dist/utils/string.js.map +1 -1
- package/package.json +4 -3
- 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
|
@@ -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 {};
|
|
@@ -1,63 +0,0 @@
|
|
|
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 {
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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,GAAmB,EAAE,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;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,GAAmB,EAAE,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACzD,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;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: Promise<any>[] = [];\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: Promise<any>[] = [];\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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,32 +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 op_provider_1 = require("./op-provider");
|
|
8
|
-
const HTTP_ENDPOINT = 'https://mainnet.optimism.io';
|
|
9
|
-
describe('OPRPCProviders', () => {
|
|
10
|
-
let provider;
|
|
11
|
-
// For some reason defining this in before all fails
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
provider = new op_provider_1.OPJsonRpcProvider(HTTP_ENDPOINT);
|
|
14
|
-
});
|
|
15
|
-
// This returns a value now, needs further investigation
|
|
16
|
-
it('should have extra fields in transactions', async () => {
|
|
17
|
-
const receipt = (0, utils_ethereum_1.formatReceipt)(await provider.getTransactionReceipt('0x5496af6ad1d619279d82b8f4c94cf3f8da8c02f22481c66a840ae9dd3f5e1a23'));
|
|
18
|
-
expect(receipt.l1Fee).toEqual(ethers_1.BigNumber.from('0x1375ad1b756e'));
|
|
19
|
-
expect(receipt.l1FeeScalar).toEqual(0.684);
|
|
20
|
-
expect(receipt.l1GasPrice).toEqual(ethers_1.BigNumber.from('0x02fae225ae'));
|
|
21
|
-
expect(receipt.l1GasUsed).toEqual(ethers_1.BigNumber.from('0x098c'));
|
|
22
|
-
});
|
|
23
|
-
it('should work with a network that isnt OP based', async () => {
|
|
24
|
-
const provider = new op_provider_1.OPJsonRpcProvider('https://eth.llamarpc.com');
|
|
25
|
-
const receipt = (0, utils_ethereum_1.formatReceipt)(await provider.getTransactionReceipt('0x7c20ced906264f81929802ee6b642d003a236c542c5de6298ede5b2a4f7f9bb9'));
|
|
26
|
-
expect(receipt.l1Fee).toBeUndefined();
|
|
27
|
-
expect(receipt.l1FeeScalar).toBeUndefined();
|
|
28
|
-
expect(receipt.l1GasPrice).toBeUndefined();
|
|
29
|
-
expect(receipt.l1GasUsed).toBeUndefined();
|
|
30
|
-
}, 10000);
|
|
31
|
-
});
|
|
32
|
-
//# sourceMappingURL=op-provider.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"op-provider.spec.js","sourceRoot":"","sources":["../../../../src/ethereum/ethers/op/op-provider.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAGnC,mCAAmC;AACnC,yDAAqD;AAErD,+CAAkD;AAElD,MAAM,aAAa,GAAG,6BAA6B,CAAC;AASpD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,QAAyB,CAAC;IAE9B,oDAAoD;IACpD,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,+BAAiB,CAAC,aAAa,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,OAAO,GAAG,IAAA,8BAAa,EAC3B,MAAM,QAAQ,CAAC,qBAAqB,CAClC,oEAAoE,CACrE,CACF,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,kBAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,kBAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,kBAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,QAAQ,GAAG,IAAI,+BAAiB,CAAC,0BAA0B,CAAC,CAAC;QAEnE,MAAM,OAAO,GAAG,IAAA,8BAAa,EAC3B,MAAM,QAAQ,CAAC,qBAAqB,CAClC,oEAAoE,CACrE,CACF,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC;IAC5C,CAAC,EAAE,KAAK,CAAC,CAAC;AACZ,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EthereumReceipt } from '@subql/types-ethereum';\nimport { BigNumber } from 'ethers';\nimport { formatReceipt } from '../../utils.ethereum';\nimport { JsonRpcProvider } from '../json-rpc-provider';\nimport { OPJsonRpcProvider } from './op-provider';\n\nconst HTTP_ENDPOINT = 'https://mainnet.optimism.io';\n\ntype OPReceiptFields = {\n l1Fee: BigNumber;\n l1FeeScalar: number;\n l1GasPrice: BigNumber;\n l1GasUsed: BigNumber;\n};\n\ndescribe('OPRPCProviders', () => {\n let provider: JsonRpcProvider;\n\n // For some reason defining this in before all fails\n beforeEach(() => {\n provider = new OPJsonRpcProvider(HTTP_ENDPOINT);\n });\n\n // This returns a value now, needs further investigation\n it('should have extra fields in transactions', async () => {\n const receipt = formatReceipt<EthereumReceipt & OPReceiptFields>(\n await provider.getTransactionReceipt(\n '0x5496af6ad1d619279d82b8f4c94cf3f8da8c02f22481c66a840ae9dd3f5e1a23',\n ),\n );\n\n expect(receipt.l1Fee).toEqual(BigNumber.from('0x1375ad1b756e'));\n expect(receipt.l1FeeScalar).toEqual(0.684);\n expect(receipt.l1GasPrice).toEqual(BigNumber.from('0x02fae225ae'));\n expect(receipt.l1GasUsed).toEqual(BigNumber.from('0x098c'));\n });\n\n it('should work with a network that isnt OP based', async () => {\n const provider = new OPJsonRpcProvider('https://eth.llamarpc.com');\n\n const receipt = formatReceipt<EthereumReceipt & OPReceiptFields>(\n await provider.getTransactionReceipt(\n '0x7c20ced906264f81929802ee6b642d003a236c542c5de6298ede5b2a4f7f9bb9',\n ),\n );\n\n expect(receipt.l1Fee).toBeUndefined();\n expect(receipt.l1FeeScalar).toBeUndefined();\n expect(receipt.l1GasPrice).toBeUndefined();\n expect(receipt.l1GasUsed).toBeUndefined();\n }, 10000);\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|