@subql/node-ethereum 6.0.5 → 6.1.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.
@@ -12,7 +12,7 @@ const types_ethereum_1 = require("@subql/types-ethereum");
12
12
  const api_ethereum_1 = require("./api.ethereum");
13
13
  const block_ethereum_1 = require("./block.ethereum");
14
14
  // Add api key to work
15
- const HTTP_ENDPOINT = 'https://ethereum.rpc.subquery.network/public';
15
+ const HTTP_ENDPOINT = 'https://ethereum-rpc.publicnode.com';
16
16
  const BLOCK_CONFIRMATIONS = 20;
17
17
  const MOONBEAM_ENDPOINT = 'https://rpc.api.moonbeam.network';
18
18
  const ds = {
@@ -193,21 +193,26 @@ describe('Api.ethereum', () => {
193
193
  });
194
194
  expect(result.length).toBe(2);
195
195
  });
196
- it('Resolves the correct tags for finalization', async () => {
197
- // Ethereum
198
- expect(ethApi.supportsFinalization).toBeTruthy();
199
- // Moonbeam
200
- ethApi = new api_ethereum_1.EthereumApi(MOONBEAM_ENDPOINT, BLOCK_CONFIRMATIONS, eventEmitter);
201
- await ethApi.init();
202
- expect(ethApi.supportsFinalization).toBeTruthy();
203
- // BSC
204
- ethApi = new api_ethereum_1.EthereumApi('https://binance.llamarpc.com', BLOCK_CONFIRMATIONS, eventEmitter);
205
- await ethApi.init();
206
- expect(ethApi.supportsFinalized).toBeFalsy();
207
- // Polygon
208
- ethApi = new api_ethereum_1.EthereumApi('https://polygon.llamarpc.com', BLOCK_CONFIRMATIONS, eventEmitter);
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);
209
214
  await ethApi.init();
210
- expect(ethApi.supportsFinalized).toBeFalsy();
215
+ expect(ethApi.supportsFinalization).toEqual(finalization);
211
216
  });
212
217
  it('Assert blockHash on logs and block', async () => {
213
218
  ethApi = new api_ethereum_1.EthereumApi('https://rpc.ankr.com/xdc', BLOCK_CONFIRMATIONS, eventEmitter);
@@ -244,5 +249,18 @@ describe('Api.ethereum', () => {
244
249
  expect((0, block_ethereum_1.isFullBlock)(block10001)).toBeFalsy();
245
250
  expect((0, block_ethereum_1.isFullBlock)(lightBlock10001)).toBeFalsy();
246
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
+ });
247
265
  });
248
266
  //# sourceMappingURL=api.ethereum.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.ethereum.test.js","sourceRoot":"","sources":["../../src/ethereum/api.ethereum.test.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;AAEnC,gDAAwB;AACxB,yDAAsD;AACtD,4DAAyD;AACzD,0DAM+B;AAC/B,iDAA6C;AAC7C,qDAI0B;AAE1B,sBAAsB;AACtB,MAAM,aAAa,GAAG,8CAA8C,CAAC;AACrE,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAC/B,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AAE7D,MAAM,EAAE,GAA2B;IACjC,OAAO,EAAE;QACP,IAAI,EAAE,EAAE;QACR,QAAQ,EAAE;YACR;gBACE,OAAO,EAAE,MAAM;gBACf,IAAI,EAAE,oCAAmB,CAAC,IAAI;gBAC9B,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE;aACnC;SACF;KACF;IACD,IAAI,EAAE,uCAAsB,CAAC,OAAO;IACpC,UAAU,EAAE,QAAQ;IACpB,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;IAC1B,MAAM,EAAE,IAAI,GAAG,CAAC;QACd,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;KACrE,CAAC;CACH,CAAC;AAEF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACvB,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAI,MAAmB,CAAC;IACxB,MAAM,YAAY,GAAG,IAAI,6BAAa,EAAE,CAAC;IACzC,IAAI,SAAwB,CAAC;IAE7B,MAAM,UAAU,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE9C,OAAO,KAAK,CAAC,KAAsB,CAAC;IACtC,CAAC,CAAC;IAEF,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,GAAG,IAAI,0BAAW,CAAC,aAAa,EAAE,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAC3E,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxE,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrE,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC,IAAI,CACpE,QAAQ,CACT,CAAC;QACF,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAChE,QAAQ,CACT,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACrE,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACzE,MAAM,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CACzE,QAAQ,CACT,CAAC;QACF,MAAM,CACJ,OAAO,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAC/D,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,SAAS;QACT,MAAM,EAAE,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI;YACN,oEAAoE,CACvE,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,EAAG,EAAE,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,QAAQ,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,EAAE,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI;YACN,oEAAoE,CACvE,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,EAAG,EAAE,EAAE,CAAC,CAAC;QAExD,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,aAAa;QACb,MAAM,EAAE,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI;YACN,oEAAoE,CACvE,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAG,CAAC,IAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,qDAAqD;IACrD,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,GAAG,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI;YACN,oEAAoE,CACtE,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC;QAEZ,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClD,IACE,IAAA,4CAA2B,EACzB,EAAE,EACF,EAAE,EAAE,EAAE,IAAI,EAAE,EACZ,4CAA4C,CAC7C,EACD,CAAC;gBACD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACzB,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAsB;YAClC,MAAM,EAAE;gBACN,oEAAoE;gBACpE,SAAS;gBACT,SAAS;gBACT,iCAAe;aAChB;SACF,CAAC;QAEF,MAAM,QAAQ,GAAsB;YAClC,MAAM,EAAE;gBACN,oEAAoE;aACrE;SACF,CAAC;QAEF,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CAC7C,CAAC,EAAE,EAAE,EAAE,CACL,EAAE,CAAC,IAAI;YACP,oEAAoE,CACtE,CAAC;QAEH,MAAM,cAAc,GAAG,WAAW,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACtD,IAAA,oCAAmB,EAAC,GAAG,EAAE,QAAQ,CAAC,CACnC,CAAC;QACF,MAAM,eAAe,GAAG,WAAW,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACvD,IAAA,oCAAmB,EAAC,GAAG,EAAE,QAAQ,CAAC,CACnC,CAAC;QAEF,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,YAAY,GAAG,2BAA2B,CAAC;QACjD,MAAM,GAAG,IAAI,0BAAW,CAAC,YAAY,EAAE,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAC1E,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,4CAA4C;QAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClD,IAAI,IAAA,4CAA2B,EAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBACxD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACzB,oEAAoE,CACrE,CAAC;QAEF,MAAM,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YACnD,IAAI,IAAA,4CAA2B,EAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBACxD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAC1B,oEAAoE,CACrE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;QACzC,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClD,IACE,IAAA,4CAA2B,EACzB,EAAE,EACF,EAAE,EAAE,EAAE,IAAI,EAAE,EACZ,4CAA4C,CAC7C,EACD,CAAC;gBACD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACzB,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClD,IACE,IAAA,4CAA2B,EACzB,EAAE,EACF,SAAS,EACT,4CAA4C,CAC7C,EACD,CAAC;gBACD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClD,IACE,IAAA,4CAA2B,EACzB,EAAE,EACF,EAAE,EAAE,EAAE,SAAS,EAAE,EACjB,4CAA4C,CAC7C,EACD,CAAC;gBACD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClD,EAAE,CAAC,EAAE,GAAG,SAAS,CAAC;YAClB,IACE,IAAA,4CAA2B,EACzB,EAAE,EACF,EAAE,EAAE,EAAE,IAAI,EAAE,EACZ,4CAA4C,CAC7C,EACD,CAAC;gBACD,OAAO,EAAE,CAAC,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,WAAW;QACX,MAAM,CAAE,MAAc,CAAC,oBAAoB,CAAC,CAAC,UAAU,EAAE,CAAC;QAE1D,WAAW;QACX,MAAM,GAAG,IAAI,0BAAW,CACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAEpB,MAAM,CAAE,MAAc,CAAC,oBAAoB,CAAC,CAAC,UAAU,EAAE,CAAC;QAE1D,MAAM;QACN,MAAM,GAAG,IAAI,0BAAW,CACtB,8BAA8B,EAC9B,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAEpB,MAAM,CAAE,MAAc,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,CAAC;QAEtD,UAAU;QACV,MAAM,GAAG,IAAI,0BAAW,CACtB,8BAA8B,EAC9B,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAEpB,MAAM,CAAE,MAAc,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,GAAG,IAAI,0BAAW,CACtB,0BAA0B,EAC1B,mBAAmB,EACnB,YAAY,CACb,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAEpB,MAAM,eAAe,GAAG,QAAQ,CAAC;QACjC,MAAM,aAAa,GAAG,eAAe,CAAC;QACtC,MAAM,sBAAsB,GAAG,wBAAwB,CAAC;QAExD,IAAI,CAAC,KAAK,CAAC,MAAa,EAAE,iBAAiB,CAAC,CAAC,qBAAqB,CAAC;YACjE,IAAI,EAAE,aAAa;YACnB,YAAY,EAAE,EAAE;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAE,MAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,qBAAqB,CAAC;YAClE;gBACE,WAAW,EAAE,WAAW;gBACxB,SAAS,EAAE,sBAAsB;gBACjC,eAAe,EAAE,KAAK;gBACtB,QAAQ,EAAE,KAAK;aAChB;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC9D,kKAAkK,CACnK,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,0BAA0B;QAC1B,MAAM,UAAU,GAAG,CAAC,MAAO,MAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QAC3E,MAAM,CAAC,IAAA,4BAAW,EAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAA,4BAAW,EAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QAE5C,+CAA+C;QAC/C,MAAM,cAAc,GAAG,CAAC,MAAO,MAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QACzE,MAAM,CAAC,IAAA,4BAAW,EAAC,cAAc,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QAEjD,4BAA4B;QAC5B,MAAM,UAAU,GAAG,CAAC,MAAO,MAAc,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QACnE,MAAM,eAAe,GAAG,CAAC,MAAO,MAAc,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;aACnE,KAAK,CAAC;QACT,MAAM,CAAC,IAAA,4BAAW,EAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAA,4BAAW,EAAC,eAAe,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IACnD,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 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.subquery.network/public';\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('Resolves the correct tags for finalization', async () => {\n // Ethereum\n expect((ethApi as any).supportsFinalization).toBeTruthy();\n\n // Moonbeam\n ethApi = new EthereumApi(\n MOONBEAM_ENDPOINT,\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalization).toBeTruthy();\n\n // BSC\n ethApi = new EthereumApi(\n 'https://binance.llamarpc.com',\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalized).toBeFalsy();\n\n // Polygon\n ethApi = new EthereumApi(\n 'https://polygon.llamarpc.com',\n BLOCK_CONFIRMATIONS,\n eventEmitter,\n );\n await ethApi.init();\n\n expect((ethApi as any).supportsFinalized).toBeFalsy();\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"]}
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"]}
@@ -9,8 +9,7 @@ const graphql_1 = require("graphql");
9
9
  const lodash_1 = require("lodash");
10
10
  const api_service_ethereum_1 = require("./api.service.ethereum");
11
11
  // Add api key to work
12
- const WS_ENDPOINT = 'wss://eth.api.onfinality.io/ws?apikey=';
13
- const HTTP_ENDPOINT = 'https://ethereum.rpc.subquery.network/public';
12
+ const HTTP_ENDPOINT = 'https://eth.llamarpc.com';
14
13
  function testSubqueryProject(endpoint) {
15
14
  return {
16
15
  network: {
@@ -1 +1 @@
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 WS_ENDPOINT = 'wss://eth.api.onfinality.io/ws?apikey=';\nconst HTTP_ENDPOINT = 'https://ethereum.rpc.subquery.network/public';\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
+ {"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"]}
@@ -46,6 +46,11 @@ function filterTransactionsProcessor(transaction, filter, address) {
46
46
  transaction.input.indexOf((0, string_1.functionToSighash)(filter.function)) !== 0) {
47
47
  return false;
48
48
  }
49
+ if (filter.type) {
50
+ if (transaction.type !== filter.type) {
51
+ return false;
52
+ }
53
+ }
49
54
  return true;
50
55
  }
51
56
  function filterLogsProcessor(log, filter, address) {
@@ -1 +1 @@
1
- {"version":3,"file":"block.ethereum.js","sourceRoot":"","sources":["../../src/ethereum/block.ethereum.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { NOT_NULL_FILTER } from '@subql/common-ethereum';\nimport { filterBlockTimestamp } from '@subql/node-core';\nimport {\n EthereumBlock,\n EthereumTransactionFilter,\n EthereumLog,\n EthereumLogFilter,\n EthereumBlockFilter,\n EthereumTransaction,\n LightEthereumLog,\n} from '@subql/types-ethereum';\nimport { SubqlProjectBlockFilter } from '../configure/SubqueryProject';\nimport { BlockContent } from '../indexer/types';\nimport {\n eventToTopic,\n functionToSighash,\n hexStringEq,\n stringNormalizedEq,\n} from '../utils/string';\n\nexport function filterBlocksProcessor(\n block: EthereumBlock,\n filter: EthereumBlockFilter,\n address?: string,\n): boolean {\n if (filter?.modulo && block.number % filter.modulo !== 0) {\n return false;\n }\n // Multiply to add MS\n if (\n !filterBlockTimestamp(\n Number(block.timestamp) * 1000,\n filter as SubqlProjectBlockFilter,\n )\n ) {\n return false;\n }\n return true;\n}\n\nexport function filterTransactionsProcessor(\n transaction: EthereumTransaction,\n filter?: EthereumTransactionFilter,\n address?: string,\n): boolean {\n if (!filter) return true;\n\n if (\n filter.to === null &&\n !(transaction.to === null || transaction.to === undefined)\n ) {\n return false;\n }\n\n if (filter.to && !stringNormalizedEq(filter.to, transaction.to)) {\n return false;\n }\n if (filter.from && !stringNormalizedEq(filter.from, transaction.from)) {\n return false;\n }\n if (\n address &&\n filter.to === undefined &&\n !stringNormalizedEq(address, transaction.to)\n ) {\n return false;\n }\n if (filter.function === null || filter.function === '0x') {\n if (transaction.input !== '0x') {\n return false;\n }\n } else if (\n filter.function !== undefined &&\n transaction.input.indexOf(functionToSighash(filter.function)) !== 0\n ) {\n return false;\n }\n\n return true;\n}\n\nexport function filterLogsProcessor(\n log: EthereumLog | LightEthereumLog,\n filter: EthereumLogFilter,\n address?: string,\n): boolean {\n if (address && !stringNormalizedEq(address, log.address)) {\n return false;\n }\n\n if (!filter) return true;\n\n if (filter.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n\n if (!log.topics[i]) {\n return false;\n }\n\n if (topic === NOT_NULL_FILTER) {\n return true;\n }\n\n if (!hexStringEq(eventToTopic(topic), log.topics[i])) {\n return false;\n }\n }\n }\n return true;\n}\n\nexport function isFullBlock(block: BlockContent): block is EthereumBlock {\n // Light etherum block just contains transaction hashes for transactions.\n // If the block has no transactions then both types would be the same\n\n if (block.transactions.length) {\n return typeof (block as EthereumBlock).transactions[0] !== 'string';\n }\n return false;\n}\n"]}
1
+ {"version":3,"file":"block.ethereum.js","sourceRoot":"","sources":["../../src/ethereum/block.ethereum.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { NOT_NULL_FILTER } from '@subql/common-ethereum';\nimport { filterBlockTimestamp } from '@subql/node-core';\nimport {\n EthereumBlock,\n EthereumTransactionFilter,\n EthereumLog,\n EthereumLogFilter,\n EthereumBlockFilter,\n EthereumTransaction,\n LightEthereumLog,\n} from '@subql/types-ethereum';\nimport { SubqlProjectBlockFilter } from '../configure/SubqueryProject';\nimport { BlockContent } from '../indexer/types';\nimport {\n eventToTopic,\n functionToSighash,\n hexStringEq,\n stringNormalizedEq,\n} from '../utils/string';\n\nexport function filterBlocksProcessor(\n block: EthereumBlock,\n filter: EthereumBlockFilter,\n address?: string,\n): boolean {\n if (filter?.modulo && block.number % filter.modulo !== 0) {\n return false;\n }\n // Multiply to add MS\n if (\n !filterBlockTimestamp(\n Number(block.timestamp) * 1000,\n filter as SubqlProjectBlockFilter,\n )\n ) {\n return false;\n }\n return true;\n}\n\nexport function filterTransactionsProcessor(\n transaction: EthereumTransaction,\n filter?: EthereumTransactionFilter,\n address?: string,\n): boolean {\n if (!filter) return true;\n\n if (\n filter.to === null &&\n !(transaction.to === null || transaction.to === undefined)\n ) {\n return false;\n }\n\n if (filter.to && !stringNormalizedEq(filter.to, transaction.to)) {\n return false;\n }\n if (filter.from && !stringNormalizedEq(filter.from, transaction.from)) {\n return false;\n }\n if (\n address &&\n filter.to === undefined &&\n !stringNormalizedEq(address, transaction.to)\n ) {\n return false;\n }\n if (filter.function === null || filter.function === '0x') {\n if (transaction.input !== '0x') {\n return false;\n }\n } else if (\n filter.function !== undefined &&\n transaction.input.indexOf(functionToSighash(filter.function)) !== 0\n ) {\n return false;\n }\n\n if (filter.type) {\n if (transaction.type !== filter.type) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function filterLogsProcessor(\n log: EthereumLog | LightEthereumLog,\n filter: EthereumLogFilter,\n address?: string,\n): boolean {\n if (address && !stringNormalizedEq(address, log.address)) {\n return false;\n }\n\n if (!filter) return true;\n\n if (filter.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n\n if (!log.topics[i]) {\n return false;\n }\n\n if (topic === NOT_NULL_FILTER) {\n return true;\n }\n\n if (!hexStringEq(eventToTopic(topic), log.topics[i])) {\n return false;\n }\n }\n }\n return true;\n}\n\nexport function isFullBlock(block: BlockContent): block is EthereumBlock {\n // Light etherum block just contains transaction hashes for transactions.\n // If the block has no transactions then both types would be the same\n\n if (block.transactions.length) {\n return typeof (block as EthereumBlock).transactions[0] !== 'string';\n }\n return false;\n}\n"]}
@@ -52,7 +52,13 @@ function formatBlock(block) {
52
52
  blockGasCost: block.blockGasCost
53
53
  ? handleNumber(block.blockGasCost).toBigInt()
54
54
  : undefined,
55
- logs: [], // Filled in at AvalancheBlockWrapped constructor
55
+ blobGasUsed: block.blobGasUsed
56
+ ? handleNumber(block.blobGasUsed).toBigInt()
57
+ : undefined,
58
+ excessBlobGas: block.excessBlobGas
59
+ ? handleNumber(block.excessBlobGas).toBigInt()
60
+ : undefined,
61
+ logs: [],
56
62
  };
57
63
  }
58
64
  function formatBlockUtil(block) {
@@ -102,6 +108,9 @@ function formatTransaction(tx, block) {
102
108
  ? handleNumber(tx.maxPriorityFeePerGas).toBigInt()
103
109
  : undefined,
104
110
  receipt: undefined, // Filled in at Etheruem.fetchBlocks
111
+ maxFeePerBlobGas: tx.maxFeePerBlobGas
112
+ ? handleNumber(tx.maxFeePerBlobGas).toBigInt()
113
+ : undefined,
105
114
  toJSON() {
106
115
  return JSON.stringify((0, lodash_1.omit)(this, ['block', 'receipt', 'toJSON']));
107
116
  },
@@ -1 +1 @@
1
- {"version":3,"file":"utils.ethereum.js","sourceRoot":"","sources":["../../src/ethereum/utils.ethereum.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 { Block } from '@ethersproject/abstract-provider';\nimport { getAddress } from '@ethersproject/address';\nimport { BigNumber } from '@ethersproject/bignumber';\nimport { Zero } from '@ethersproject/constants';\nimport { Header, IBlock } from '@subql/node-core';\nimport {\n ApiWrapper,\n EthereumBlock,\n EthereumLog,\n EthereumReceipt,\n EthereumResult,\n EthereumTransaction,\n LightEthereumBlock,\n} from '@subql/types-ethereum';\nimport { omit } from 'lodash';\nimport { BlockContent } from '../indexer/types';\n\nexport function calcInterval(api: ApiWrapper): number {\n // TODO find a way to get this from the blockchain\n return 6000;\n}\n\nfunction handleAddress(value: string): string | null {\n if (!value || value === '0x') {\n return null;\n }\n return getAddress(value);\n}\n\nexport function handleNumber(value: string | number): BigNumber {\n if (value === undefined) {\n return Zero;\n }\n if (value === '0x') {\n return Zero;\n }\n if (value === null) {\n return Zero;\n }\n return BigNumber.from(value);\n}\n\nexport function formatBlock(block: any): EthereumBlock {\n return {\n ...block,\n difficulty: handleNumber(block.difficulty).toBigInt(),\n gasLimit: handleNumber(block.gasLimit).toBigInt(),\n gasUsed: handleNumber(block.gasUsed).toBigInt(),\n number: handleNumber(block.number).toNumber(),\n size: handleNumber(block.size).toBigInt(),\n timestamp: handleNumber(block.timestamp).toBigInt(),\n totalDifficulty: handleNumber(block.totalDifficulty).toBigInt(),\n baseFeePerGas: block.baseFeePerGas\n ? handleNumber(block.baseFeePerGas).toBigInt()\n : undefined,\n blockGasCost: block.blockGasCost\n ? handleNumber(block.blockGasCost).toBigInt()\n : undefined,\n logs: [], // Filled in at AvalancheBlockWrapped constructor\n } as EthereumBlock;\n}\n\nexport function formatBlockUtil<\n B extends EthereumBlock | LightEthereumBlock = EthereumBlock,\n>(block: B): IBlock<B> {\n return {\n block,\n getHeader: () => ethereumBlockToHeader(block),\n };\n}\n\nexport function formatLog(\n log: Omit<\n EthereumLog<EthereumResult> | EthereumLog,\n 'blockTimestamp' | 'block' | 'transaction'\n >,\n block: EthereumBlock,\n): EthereumLog<EthereumResult> | EthereumLog {\n const formattedLog = {\n ...log,\n address: handleAddress(log.address),\n blockNumber: handleNumber(log.blockNumber).toNumber(),\n transactionIndex: handleNumber(log.transactionIndex).toNumber(),\n logIndex: handleNumber(log.logIndex).toNumber(),\n block,\n toJSON(): string {\n return JSON.stringify(omit(this, ['transaction', 'block', 'toJSON']));\n },\n };\n\n // Define this afterwards as the spread on `...log` breaks defining a getter\n Object.defineProperty(formattedLog, 'transaction', {\n get: () => {\n const rawTransaction = block.transactions?.find(\n (tx) => tx.hash === log.transactionHash,\n );\n\n return rawTransaction;\n },\n });\n return formattedLog as unknown as EthereumLog<EthereumResult>;\n}\n\nexport function formatTransaction(\n tx: Record<string, any>,\n block: EthereumBlock,\n): Omit<EthereumTransaction, 'receipt'> {\n return {\n ...(tx as Partial<EthereumTransaction>),\n from: handleAddress(tx.from),\n to: handleAddress(tx.to),\n blockNumber: handleNumber(tx.blockNumber).toNumber(),\n blockTimestamp: block.timestamp,\n gas: handleNumber(tx.gas).toBigInt(),\n gasPrice: handleNumber(tx.gasPrice).toBigInt(),\n nonce: handleNumber(tx.nonce).toBigInt(),\n transactionIndex: handleNumber(tx.transactionIndex).toBigInt(),\n value: handleNumber(tx.value).toBigInt(),\n v: handleNumber(tx.v).toBigInt(),\n maxFeePerGas: tx.maxFeePerGas\n ? handleNumber(tx.maxFeePerGas).toBigInt()\n : undefined,\n maxPriorityFeePerGas: tx.maxPriorityFeePerGas\n ? handleNumber(tx.maxPriorityFeePerGas).toBigInt()\n : undefined,\n receipt: undefined, // Filled in at Etheruem.fetchBlocks\n toJSON(): string {\n return JSON.stringify(omit(this, ['block', 'receipt', 'toJSON']));\n },\n } as Omit<EthereumTransaction, 'receipt'>;\n}\n\nexport function formatReceipt<R extends EthereumReceipt = EthereumReceipt>(\n receipt: Record<string, any>,\n): R {\n return {\n ...receipt,\n from: handleAddress(receipt.from),\n to: handleAddress(receipt.to),\n blockNumber: handleNumber(receipt.blockNumber).toNumber(),\n cumulativeGasUsed: handleNumber(receipt.cumulativeGasUsed).toBigInt(),\n effectiveGasPrice: handleNumber(receipt.effectiveGasPrice).toBigInt(),\n gasUsed: handleNumber(receipt.gasUsed).toBigInt(),\n logs: receipt.logs.map(formatLog),\n status: Boolean(handleNumber(receipt.status).toNumber()),\n transactionIndex: handleNumber(receipt.transactionIndex).toNumber(),\n toJSON(): string {\n return JSON.stringify(omit(this, ['toJSON']));\n },\n } as unknown as R;\n}\n\nexport function ethereumBlockToHeader(block: BlockContent | Block): Header {\n return {\n blockHeight: block.number,\n blockHash: block.hash,\n parentHash: block.parentHash,\n timestamp: new Date(Number(block.timestamp) * 1000),\n };\n}\n"]}
1
+ {"version":3,"file":"utils.ethereum.js","sourceRoot":"","sources":["../../src/ethereum/utils.ethereum.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 { Block } from '@ethersproject/abstract-provider';\nimport { getAddress } from '@ethersproject/address';\nimport { BigNumber } from '@ethersproject/bignumber';\nimport { Zero } from '@ethersproject/constants';\nimport { Header, IBlock } from '@subql/node-core';\nimport {\n ApiWrapper,\n EthereumBlock,\n EthereumLog,\n EthereumReceipt,\n EthereumResult,\n EthereumTransaction,\n LightEthereumBlock,\n} from '@subql/types-ethereum';\nimport { omit } from 'lodash';\nimport { BlockContent } from '../indexer/types';\n\nexport function calcInterval(api: ApiWrapper): number {\n // TODO find a way to get this from the blockchain\n return 6000;\n}\n\nfunction handleAddress(value: string): string | null {\n if (!value || value === '0x') {\n return null;\n }\n return getAddress(value);\n}\n\nexport function handleNumber(value: string | number): BigNumber {\n if (value === undefined) {\n return Zero;\n }\n if (value === '0x') {\n return Zero;\n }\n if (value === null) {\n return Zero;\n }\n return BigNumber.from(value);\n}\n\nexport function formatBlock(block: any): EthereumBlock {\n return {\n ...block,\n difficulty: handleNumber(block.difficulty).toBigInt(),\n gasLimit: handleNumber(block.gasLimit).toBigInt(),\n gasUsed: handleNumber(block.gasUsed).toBigInt(),\n number: handleNumber(block.number).toNumber(),\n size: handleNumber(block.size).toBigInt(),\n timestamp: handleNumber(block.timestamp).toBigInt(),\n totalDifficulty: handleNumber(block.totalDifficulty).toBigInt(),\n baseFeePerGas: block.baseFeePerGas\n ? handleNumber(block.baseFeePerGas).toBigInt()\n : undefined,\n blockGasCost: block.blockGasCost\n ? handleNumber(block.blockGasCost).toBigInt()\n : undefined,\n blobGasUsed: block.blobGasUsed\n ? handleNumber(block.blobGasUsed).toBigInt()\n : undefined,\n excessBlobGas: block.excessBlobGas\n ? handleNumber(block.excessBlobGas).toBigInt()\n : undefined,\n logs: [],\n } as EthereumBlock;\n}\n\nexport function formatBlockUtil<\n B extends EthereumBlock | LightEthereumBlock = EthereumBlock,\n>(block: B): IBlock<B> {\n return {\n block,\n getHeader: () => ethereumBlockToHeader(block),\n };\n}\n\nexport function formatLog(\n log: Omit<\n EthereumLog<EthereumResult> | EthereumLog,\n 'blockTimestamp' | 'block' | 'transaction'\n >,\n block: EthereumBlock,\n): EthereumLog<EthereumResult> | EthereumLog {\n const formattedLog = {\n ...log,\n address: handleAddress(log.address),\n blockNumber: handleNumber(log.blockNumber).toNumber(),\n transactionIndex: handleNumber(log.transactionIndex).toNumber(),\n logIndex: handleNumber(log.logIndex).toNumber(),\n block,\n toJSON(): string {\n return JSON.stringify(omit(this, ['transaction', 'block', 'toJSON']));\n },\n };\n\n // Define this afterwards as the spread on `...log` breaks defining a getter\n Object.defineProperty(formattedLog, 'transaction', {\n get: () => {\n const rawTransaction = block.transactions?.find(\n (tx) => tx.hash === log.transactionHash,\n );\n\n return rawTransaction;\n },\n });\n return formattedLog as unknown as EthereumLog<EthereumResult>;\n}\n\nexport function formatTransaction(\n tx: Record<string, any>,\n block: EthereumBlock,\n): Omit<EthereumTransaction, 'receipt'> {\n return {\n ...(tx as Partial<EthereumTransaction>),\n from: handleAddress(tx.from),\n to: handleAddress(tx.to),\n blockNumber: handleNumber(tx.blockNumber).toNumber(),\n blockTimestamp: block.timestamp,\n gas: handleNumber(tx.gas).toBigInt(),\n gasPrice: handleNumber(tx.gasPrice).toBigInt(),\n nonce: handleNumber(tx.nonce).toBigInt(),\n transactionIndex: handleNumber(tx.transactionIndex).toBigInt(),\n value: handleNumber(tx.value).toBigInt(),\n v: handleNumber(tx.v).toBigInt(),\n maxFeePerGas: tx.maxFeePerGas\n ? handleNumber(tx.maxFeePerGas).toBigInt()\n : undefined,\n maxPriorityFeePerGas: tx.maxPriorityFeePerGas\n ? handleNumber(tx.maxPriorityFeePerGas).toBigInt()\n : undefined,\n receipt: undefined, // Filled in at Etheruem.fetchBlocks\n maxFeePerBlobGas: tx.maxFeePerBlobGas\n ? handleNumber(tx.maxFeePerBlobGas).toBigInt()\n : undefined,\n toJSON(): string {\n return JSON.stringify(omit(this, ['block', 'receipt', 'toJSON']));\n },\n } as Omit<EthereumTransaction, 'receipt'>;\n}\n\nexport function formatReceipt<R extends EthereumReceipt = EthereumReceipt>(\n receipt: Record<string, any>,\n): R {\n return {\n ...receipt,\n from: handleAddress(receipt.from),\n to: handleAddress(receipt.to),\n blockNumber: handleNumber(receipt.blockNumber).toNumber(),\n cumulativeGasUsed: handleNumber(receipt.cumulativeGasUsed).toBigInt(),\n effectiveGasPrice: handleNumber(receipt.effectiveGasPrice).toBigInt(),\n gasUsed: handleNumber(receipt.gasUsed).toBigInt(),\n logs: receipt.logs.map(formatLog),\n status: Boolean(handleNumber(receipt.status).toNumber()),\n transactionIndex: handleNumber(receipt.transactionIndex).toNumber(),\n toJSON(): string {\n return JSON.stringify(omit(this, ['toJSON']));\n },\n } as unknown as R;\n}\n\nexport function ethereumBlockToHeader(block: BlockContent | Block): Header {\n return {\n blockHeight: block.number,\n blockHash: block.hash,\n parentHash: block.parentHash,\n timestamp: new Date(Number(block.timestamp) * 1000),\n };\n}\n"]}
@@ -1,9 +1,9 @@
1
- import { NodeConfig, DictionaryV2, RawDictionaryResponseData, DictionaryResponse, IBlock } from '@subql/node-core';
1
+ import { NodeConfig, DictionaryV2, RawDictionaryResponseData, DictionaryResponse, IBlock, V2MetadataFilters } from '@subql/node-core';
2
2
  import { EthereumBlock, SubqlDatasource } from '@subql/types-ethereum';
3
3
  import { EthereumProjectDs, EthereumProjectDsTemplate, SubqueryProject } from '../../../configure/SubqueryProject';
4
4
  import { EthereumApi } from '../../../ethereum';
5
5
  import { RawEthBlock, EthDictionaryV2QueryEntry } from './types';
6
- export declare function buildDictionaryV2QueryEntry(dataSources: EthereumProjectDs[]): EthDictionaryV2QueryEntry;
6
+ export declare function buildDictionaryV2QueryEntry(dataSources: EthereumProjectDs[], availableFilters?: V2MetadataFilters): EthDictionaryV2QueryEntry;
7
7
  export declare class EthDictionaryV2 extends DictionaryV2<EthereumBlock, SubqlDatasource, EthDictionaryV2QueryEntry> {
8
8
  #private;
9
9
  private api;
@@ -26,7 +26,7 @@ function applyAddresses(addresses) {
26
26
  }
27
27
  return (0, utils_1.validAddresses)(addresses).map((a) => a.toLowerCase());
28
28
  }
29
- function callFilterToDictionaryCondition(filter, addresses) {
29
+ function callFilterToDictionaryCondition(filter, addresses, availableFilters) {
30
30
  const txConditions = {};
31
31
  const toArray = [];
32
32
  const fromArray = [];
@@ -55,20 +55,28 @@ function callFilterToDictionaryCondition(filter, addresses) {
55
55
  if (filter?.function) {
56
56
  funcArray.push((0, string_1.functionToSighash)(filter.function));
57
57
  }
58
- if (toArray.length !== 0) {
59
- txConditions.to = toArray;
60
- }
61
- if (fromArray.length !== 0) {
62
- txConditions.from = fromArray;
63
- }
64
- if (funcArray.length !== 0) {
65
- txConditions.data = funcArray;
58
+ const setValue = (key, value) => {
59
+ if (availableFilters && !availableFilters.includes(key)) {
60
+ return;
61
+ }
62
+ if (Array.isArray(value) && value.length === 0) {
63
+ return;
64
+ }
65
+ txConditions[key] = value;
66
+ };
67
+ setValue('to', toArray);
68
+ setValue('from', fromArray);
69
+ setValue('data', funcArray);
70
+ if (filter?.type) {
71
+ setValue('type', [filter.type]);
66
72
  }
67
73
  return txConditions;
68
74
  }
69
- function eventFilterToDictionaryCondition(filter, addresses) {
75
+ function eventFilterToDictionaryCondition(filter, addresses, availableFilters) {
70
76
  const logConditions = {};
71
- logConditions.address = applyAddresses(addresses);
77
+ if (!availableFilters || availableFilters.includes('address')) {
78
+ logConditions.address = applyAddresses(addresses);
79
+ }
72
80
  if (filter?.topics) {
73
81
  for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {
74
82
  const topic = filter.topics[i];
@@ -76,6 +84,9 @@ function eventFilterToDictionaryCondition(filter, addresses) {
76
84
  continue;
77
85
  }
78
86
  const field = `topics${i}`;
87
+ if (availableFilters && !availableFilters.includes(field)) {
88
+ continue;
89
+ }
79
90
  // Initialized
80
91
  if (!logConditions[field]) {
81
92
  logConditions[field] = [];
@@ -105,7 +116,7 @@ function sanitiseDictionaryConditions(dictionaryConditions) {
105
116
  }
106
117
  return dictionaryConditions;
107
118
  }
108
- function buildDictionaryV2QueryEntry(dataSources) {
119
+ function buildDictionaryV2QueryEntry(dataSources, availableFilters) {
109
120
  const dictionaryConditions = {
110
121
  logs: [],
111
122
  transactions: [],
@@ -127,7 +138,7 @@ function buildDictionaryV2QueryEntry(dataSources) {
127
138
  .length) ||
128
139
  (0, utils_1.validAddresses)(addresses).length) {
129
140
  dictionaryConditions.transactions ??= [];
130
- dictionaryConditions.transactions.push(callFilterToDictionaryCondition(handler.filter, addresses));
141
+ dictionaryConditions.transactions.push(callFilterToDictionaryCondition(handler.filter, addresses, availableFilters?.transactions));
131
142
  }
132
143
  break;
133
144
  }
@@ -135,7 +146,7 @@ function buildDictionaryV2QueryEntry(dataSources) {
135
146
  if (handler.filter?.topics?.length ||
136
147
  (0, utils_1.validAddresses)(addresses).length) {
137
148
  dictionaryConditions.logs ??= [];
138
- dictionaryConditions.logs.push(eventFilterToDictionaryCondition(handler.filter, addresses));
149
+ dictionaryConditions.logs.push(eventFilterToDictionaryCondition(handler.filter, addresses, availableFilters?.logs));
139
150
  }
140
151
  break;
141
152
  }
@@ -159,7 +170,7 @@ class EthDictionaryV2 extends node_core_1.DictionaryV2 {
159
170
  return dictionary;
160
171
  }
161
172
  buildDictionaryQueryEntries(dataSources) {
162
- return buildDictionaryV2QueryEntry(dataSources);
173
+ return buildDictionaryV2QueryEntry(dataSources, this._metadata?.filters);
163
174
  }
164
175
  // eslint-disable-next-line @typescript-eslint/require-await
165
176
  async getData(startBlock, endBlock, limit = MIN_FETCH_LIMIT) {
@@ -1 +1 @@
1
- {"version":3,"file":"ethDictionaryV2.js","sourceRoot":"","sources":["../../../../src/indexer/dictionary/v2/ethDictionaryV2.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 { NOT_NULL_FILTER } from '@subql/common-ethereum';\nimport {\n NodeConfig,\n DictionaryV2,\n RawDictionaryResponseData,\n DictionaryResponse,\n getLogger,\n IBlock,\n} from '@subql/node-core';\nimport {\n EthereumBlock,\n EthereumHandlerKind,\n EthereumLogFilter,\n EthereumTransactionFilter,\n SubqlDatasource,\n} from '@subql/types-ethereum';\nimport { uniqBy } from 'lodash';\nimport { EthereumNodeConfig } from '../../../configure/NodeConfig';\nimport {\n EthereumProjectDs,\n EthereumProjectDsTemplate,\n SubqueryProject,\n} from '../../../configure/SubqueryProject';\nimport { EthereumApi } from '../../../ethereum';\nimport { eventToTopic, functionToSighash } from '../../../utils/string';\nimport { yargsOptions } from '../../../yargs';\nimport { groupedDataSources, validAddresses } from '../utils';\nimport {\n RawEthBlock,\n EthDictionaryV2QueryEntry,\n EthDictionaryTxConditions,\n EthDictionaryLogConditions,\n} from './types';\nimport { rawBlockToEthBlock } from './utils';\n\nconst MIN_FETCH_LIMIT = 200;\n\nconst logger = getLogger('dictionary-v2');\n\nfunction applyAddresses(\n addresses?: (string | undefined | null)[],\n): string[] | undefined {\n const queryAddressLimit = yargsOptions.argv['query-address-limit'];\n if (\n !addresses ||\n !addresses.length ||\n addresses.length > queryAddressLimit ||\n addresses.filter((v) => !v).length // DONT use find because 'undefined' and 'null' as falsey\n ) {\n return [];\n }\n\n return validAddresses(addresses).map((a) => a.toLowerCase());\n}\n\nfunction callFilterToDictionaryCondition(\n filter?: EthereumTransactionFilter,\n addresses?: (string | undefined | null)[],\n): EthDictionaryTxConditions {\n const txConditions: EthDictionaryTxConditions = {};\n const toArray: (string | null)[] = [];\n const fromArray: string[] = [];\n const funcArray: string[] = [];\n\n if (filter?.from) {\n fromArray.push(filter.from.toLowerCase());\n }\n\n const assignTo = (value: string | null | undefined) => {\n if (value === null) {\n toArray.push(null);\n } else if (value !== undefined) {\n toArray.push(value.toLowerCase());\n }\n };\n\n const optionsAddresses = applyAddresses(addresses);\n if (!optionsAddresses?.length) {\n assignTo(filter?.to);\n } else {\n if (filter?.to || filter?.to === null) {\n logger.warn(\n `TransactionFilter 'to' conflicts with 'address' in data source options, using data source option`,\n );\n }\n optionsAddresses.forEach(assignTo);\n }\n\n if (filter?.function) {\n funcArray.push(functionToSighash(filter.function));\n }\n\n if (toArray.length !== 0) {\n txConditions.to = toArray;\n }\n if (fromArray.length !== 0) {\n txConditions.from = fromArray;\n }\n\n if (funcArray.length !== 0) {\n txConditions.data = funcArray;\n }\n\n return txConditions;\n}\n\nfunction eventFilterToDictionaryCondition(\n filter?: EthereumLogFilter,\n addresses?: (string | undefined | null)[],\n): EthDictionaryLogConditions {\n const logConditions: EthDictionaryLogConditions = {};\n logConditions.address = applyAddresses(addresses);\n if (filter?.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n const field = `topics${i}`;\n // Initialized\n if (!logConditions[field]) {\n logConditions[field] = [];\n }\n if (topic === NOT_NULL_FILTER) {\n logConditions[field] = []; // TODO, check if !null\n } else {\n logConditions[field].push(eventToTopic(topic));\n }\n }\n }\n return logConditions;\n}\n\nfunction sanitiseDictionaryConditions(\n dictionaryConditions: EthDictionaryV2QueryEntry,\n): EthDictionaryV2QueryEntry {\n if (!dictionaryConditions.logs?.length) {\n delete dictionaryConditions.logs;\n } else {\n dictionaryConditions.logs = uniqBy(dictionaryConditions.logs, (log) =>\n JSON.stringify(log),\n );\n }\n\n if (!dictionaryConditions.transactions?.length) {\n delete dictionaryConditions.transactions;\n } else {\n dictionaryConditions.transactions = uniqBy(\n dictionaryConditions.transactions,\n (tx) => JSON.stringify(tx),\n );\n }\n\n return dictionaryConditions;\n}\n\nexport function buildDictionaryV2QueryEntry(\n dataSources: EthereumProjectDs[],\n): EthDictionaryV2QueryEntry {\n const dictionaryConditions: EthDictionaryV2QueryEntry = {\n logs: [],\n transactions: [],\n };\n\n const groupedHandlers = groupedDataSources(dataSources);\n for (const [handler, addresses] of groupedHandlers) {\n // No filters, cant use dictionary\n if (!handler.filter && !addresses?.length) return {};\n\n switch (handler.kind) {\n case EthereumHandlerKind.Block:\n if (handler.filter?.modulo === undefined) {\n return {};\n }\n break;\n case EthereumHandlerKind.Call: {\n if (\n (handler.filter &&\n Object.values(handler.filter).filter((v) => v !== undefined)\n .length) ||\n validAddresses(addresses).length\n ) {\n dictionaryConditions.transactions ??= [];\n dictionaryConditions.transactions.push(\n callFilterToDictionaryCondition(handler.filter, addresses),\n );\n }\n break;\n }\n case EthereumHandlerKind.Event: {\n if (\n handler.filter?.topics?.length ||\n validAddresses(addresses).length\n ) {\n dictionaryConditions.logs ??= [];\n dictionaryConditions.logs.push(\n eventFilterToDictionaryCondition(handler.filter, addresses),\n );\n }\n\n break;\n }\n default:\n }\n }\n\n return sanitiseDictionaryConditions(dictionaryConditions);\n}\n\nexport class EthDictionaryV2 extends DictionaryV2<\n EthereumBlock,\n SubqlDatasource,\n EthDictionaryV2QueryEntry\n> {\n #skipTransactions: boolean;\n\n constructor(\n endpoint: string,\n nodeConfig: NodeConfig,\n project: SubqueryProject,\n private api: EthereumApi,\n ) {\n super(endpoint, project.network.chainId, nodeConfig);\n this.#skipTransactions = !!new EthereumNodeConfig(nodeConfig)\n .skipTransactions;\n }\n\n static async create(\n endpoint: string,\n nodeConfig: NodeConfig,\n project: SubqueryProject,\n api: EthereumApi,\n ): Promise<EthDictionaryV2> {\n const dictionary = new EthDictionaryV2(endpoint, nodeConfig, project, api);\n await dictionary.init();\n return dictionary;\n }\n\n buildDictionaryQueryEntries(\n dataSources: (EthereumProjectDs | EthereumProjectDsTemplate)[],\n ): EthDictionaryV2QueryEntry {\n return buildDictionaryV2QueryEntry(dataSources);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async getData(\n startBlock: number,\n endBlock: number,\n limit: number = MIN_FETCH_LIMIT,\n ): Promise<DictionaryResponse<IBlock<EthereumBlock> | number> | undefined> {\n return super.getData(startBlock, endBlock, limit, {\n blockHeader: true,\n logs: { transaction: !this.#skipTransactions },\n transactions: { log: true },\n });\n }\n\n convertResponseBlocks<RFB = RawEthBlock>(\n data: RawDictionaryResponseData<RFB>,\n ): DictionaryResponse<IBlock<EthereumBlock>> | undefined {\n try {\n const blocks: IBlock<EthereumBlock>[] = (\n (data.blocks as RawEthBlock[]) || []\n ).map((b) => rawBlockToEthBlock(b, this.api));\n\n if (!blocks.length) {\n return {\n batchBlocks: [],\n lastBufferedHeight: undefined, // This will get set to the request end block in the base class.\n } as any;\n }\n return {\n batchBlocks: blocks,\n lastBufferedHeight: blocks[blocks.length - 1].block.number,\n };\n } catch (e: any) {\n logger.error(e, `Failed to handle block response}`);\n throw e;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"ethDictionaryV2.js","sourceRoot":"","sources":["../../../../src/indexer/dictionary/v2/ethDictionaryV2.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 { NOT_NULL_FILTER } from '@subql/common-ethereum';\nimport {\n NodeConfig,\n DictionaryV2,\n RawDictionaryResponseData,\n DictionaryResponse,\n getLogger,\n IBlock,\n V2MetadataFilters,\n} from '@subql/node-core';\nimport {\n EthereumBlock,\n EthereumHandlerKind,\n EthereumLogFilter,\n EthereumTransactionFilter,\n SubqlDatasource,\n} from '@subql/types-ethereum';\nimport { uniqBy } from 'lodash';\nimport { EthereumNodeConfig } from '../../../configure/NodeConfig';\nimport {\n EthereumProjectDs,\n EthereumProjectDsTemplate,\n SubqueryProject,\n} from '../../../configure/SubqueryProject';\nimport { EthereumApi } from '../../../ethereum';\nimport { eventToTopic, functionToSighash } from '../../../utils/string';\nimport { yargsOptions } from '../../../yargs';\nimport { groupedDataSources, validAddresses } from '../utils';\nimport {\n RawEthBlock,\n EthDictionaryV2QueryEntry,\n EthDictionaryTxConditions,\n EthDictionaryLogConditions,\n} from './types';\nimport { rawBlockToEthBlock } from './utils';\n\nconst MIN_FETCH_LIMIT = 200;\n\nconst logger = getLogger('dictionary-v2');\n\nfunction applyAddresses(\n addresses?: (string | undefined | null)[],\n): string[] | undefined {\n const queryAddressLimit = yargsOptions.argv['query-address-limit'];\n if (\n !addresses ||\n !addresses.length ||\n addresses.length > queryAddressLimit ||\n addresses.filter((v) => !v).length // DONT use find because 'undefined' and 'null' as falsey\n ) {\n return [];\n }\n\n return validAddresses(addresses).map((a) => a.toLowerCase());\n}\n\nfunction callFilterToDictionaryCondition(\n filter?: EthereumTransactionFilter,\n addresses?: (string | undefined | null)[],\n availableFilters?: string[],\n): EthDictionaryTxConditions {\n const txConditions: EthDictionaryTxConditions = {};\n const toArray: (string | null)[] = [];\n const fromArray: string[] = [];\n const funcArray: string[] = [];\n\n if (filter?.from) {\n fromArray.push(filter.from.toLowerCase());\n }\n\n const assignTo = (value: string | null | undefined) => {\n if (value === null) {\n toArray.push(null);\n } else if (value !== undefined) {\n toArray.push(value.toLowerCase());\n }\n };\n\n const optionsAddresses = applyAddresses(addresses);\n if (!optionsAddresses?.length) {\n assignTo(filter?.to);\n } else {\n if (filter?.to || filter?.to === null) {\n logger.warn(\n `TransactionFilter 'to' conflicts with 'address' in data source options, using data source option`,\n );\n }\n optionsAddresses.forEach(assignTo);\n }\n\n if (filter?.function) {\n funcArray.push(functionToSighash(filter.function));\n }\n\n const setValue = <K extends keyof EthDictionaryTxConditions>(\n key: K,\n value: EthDictionaryTxConditions[K],\n ) => {\n if (availableFilters && !availableFilters.includes(key)) {\n return;\n }\n if (Array.isArray(value) && value.length === 0) {\n return;\n }\n txConditions[key] = value;\n };\n\n setValue('to', toArray);\n setValue('from', fromArray);\n setValue('data', funcArray);\n if (filter?.type) {\n setValue('type', [filter.type]);\n }\n\n return txConditions;\n}\n\nfunction eventFilterToDictionaryCondition(\n filter?: EthereumLogFilter,\n addresses?: (string | undefined | null)[],\n availableFilters?: string[],\n): EthDictionaryLogConditions {\n const logConditions: EthDictionaryLogConditions = {};\n\n if (!availableFilters || availableFilters.includes('address')) {\n logConditions.address = applyAddresses(addresses);\n }\n if (filter?.topics) {\n for (let i = 0; i < Math.min(filter.topics.length, 4); i++) {\n const topic = filter.topics[i];\n if (!topic) {\n continue;\n }\n const field = `topics${i}`;\n if (availableFilters && !availableFilters.includes(field)) {\n continue;\n }\n // Initialized\n if (!logConditions[field]) {\n logConditions[field] = [];\n }\n if (topic === NOT_NULL_FILTER) {\n logConditions[field] = []; // TODO, check if !null\n } else {\n logConditions[field].push(eventToTopic(topic));\n }\n }\n }\n return logConditions;\n}\n\nfunction sanitiseDictionaryConditions(\n dictionaryConditions: EthDictionaryV2QueryEntry,\n): EthDictionaryV2QueryEntry {\n if (!dictionaryConditions.logs?.length) {\n delete dictionaryConditions.logs;\n } else {\n dictionaryConditions.logs = uniqBy(dictionaryConditions.logs, (log) =>\n JSON.stringify(log),\n );\n }\n\n if (!dictionaryConditions.transactions?.length) {\n delete dictionaryConditions.transactions;\n } else {\n dictionaryConditions.transactions = uniqBy(\n dictionaryConditions.transactions,\n (tx) => JSON.stringify(tx),\n );\n }\n\n return dictionaryConditions;\n}\n\nexport function buildDictionaryV2QueryEntry(\n dataSources: EthereumProjectDs[],\n availableFilters?: V2MetadataFilters,\n): EthDictionaryV2QueryEntry {\n const dictionaryConditions: EthDictionaryV2QueryEntry = {\n logs: [],\n transactions: [],\n };\n\n const groupedHandlers = groupedDataSources(dataSources);\n for (const [handler, addresses] of groupedHandlers) {\n // No filters, cant use dictionary\n if (!handler.filter && !addresses?.length) return {};\n\n switch (handler.kind) {\n case EthereumHandlerKind.Block:\n if (handler.filter?.modulo === undefined) {\n return {};\n }\n break;\n case EthereumHandlerKind.Call: {\n if (\n (handler.filter &&\n Object.values(handler.filter).filter((v) => v !== undefined)\n .length) ||\n validAddresses(addresses).length\n ) {\n dictionaryConditions.transactions ??= [];\n dictionaryConditions.transactions.push(\n callFilterToDictionaryCondition(\n handler.filter,\n addresses,\n availableFilters?.transactions,\n ),\n );\n }\n break;\n }\n case EthereumHandlerKind.Event: {\n if (\n handler.filter?.topics?.length ||\n validAddresses(addresses).length\n ) {\n dictionaryConditions.logs ??= [];\n dictionaryConditions.logs.push(\n eventFilterToDictionaryCondition(\n handler.filter,\n addresses,\n availableFilters?.logs,\n ),\n );\n }\n\n break;\n }\n default:\n }\n }\n\n return sanitiseDictionaryConditions(dictionaryConditions);\n}\n\nexport class EthDictionaryV2 extends DictionaryV2<\n EthereumBlock,\n SubqlDatasource,\n EthDictionaryV2QueryEntry\n> {\n #skipTransactions: boolean;\n\n constructor(\n endpoint: string,\n nodeConfig: NodeConfig,\n project: SubqueryProject,\n private api: EthereumApi,\n ) {\n super(endpoint, project.network.chainId, nodeConfig);\n this.#skipTransactions = !!new EthereumNodeConfig(nodeConfig)\n .skipTransactions;\n }\n\n static async create(\n endpoint: string,\n nodeConfig: NodeConfig,\n project: SubqueryProject,\n api: EthereumApi,\n ): Promise<EthDictionaryV2> {\n const dictionary = new EthDictionaryV2(endpoint, nodeConfig, project, api);\n await dictionary.init();\n return dictionary;\n }\n\n buildDictionaryQueryEntries(\n dataSources: (EthereumProjectDs | EthereumProjectDsTemplate)[],\n ): EthDictionaryV2QueryEntry {\n return buildDictionaryV2QueryEntry(dataSources, this._metadata?.filters);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async getData(\n startBlock: number,\n endBlock: number,\n limit: number = MIN_FETCH_LIMIT,\n ): Promise<DictionaryResponse<IBlock<EthereumBlock> | number> | undefined> {\n return super.getData(startBlock, endBlock, limit, {\n blockHeader: true,\n logs: { transaction: !this.#skipTransactions },\n transactions: { log: true },\n });\n }\n\n convertResponseBlocks<RFB = RawEthBlock>(\n data: RawDictionaryResponseData<RFB>,\n ): DictionaryResponse<IBlock<EthereumBlock>> | undefined {\n try {\n const blocks: IBlock<EthereumBlock>[] = (\n (data.blocks as RawEthBlock[]) || []\n ).map((b) => rawBlockToEthBlock(b, this.api));\n\n if (!blocks.length) {\n return {\n batchBlocks: [],\n lastBufferedHeight: undefined, // This will get set to the request end block in the base class.\n } as any;\n }\n return {\n batchBlocks: blocks,\n lastBufferedHeight: blocks[blocks.length - 1].block.number,\n };\n } catch (e: any) {\n logger.error(e, `Failed to handle block response}`);\n throw e;\n }\n }\n}\n"]}
@@ -101,9 +101,11 @@ function makeBlockHeightMap(mockDs) {
101
101
  // enable this once dictionary v2 is online
102
102
  describe('eth dictionary v2', () => {
103
103
  let ethDictionaryV2;
104
+ let ethApi;
104
105
  const dsMap = makeBlockHeightMap(mockDs);
105
106
  beforeAll(async () => {
106
- ethDictionaryV2 = await ethDictionaryV2_1.EthDictionaryV2.create(DEFAULT_DICTIONARY, nodeConfig, { network: { chainId: '1' } }, new ethereum_1.EthereumApi(HTTP_ENDPOINT, 1, new eventemitter2_1.default()));
107
+ ethApi = new ethereum_1.EthereumApi(HTTP_ENDPOINT, 1, new eventemitter2_1.default());
108
+ ethDictionaryV2 = await ethDictionaryV2_1.EthDictionaryV2.create(DEFAULT_DICTIONARY, nodeConfig, { network: { chainId: '1' } }, ethApi);
107
109
  }, 10000);
108
110
  beforeEach(() => {
109
111
  ethDictionaryV2.updateQueriesMap(dsMap);
@@ -124,7 +126,16 @@ describe('eth dictionary v2', () => {
124
126
  expect(ethBlock19217804.number).toBe(19217804);
125
127
  // Sighash of approval tx
126
128
  expect(ethBlock19217803.transactions.filter((tx) => tx.input.indexOf('0x095ea7b3') === 0).length).toBe(4);
127
- expect(ethBlock19217804.logs.length).toBe(233);
129
+ // Run the same filters on an RPC block to compare results
130
+ const rpcBlock19217804 = await ethApi.fetchBlock(19217804);
131
+ const rpcLogs19217804 = [
132
+ ...rpcBlock19217804.block.transactions
133
+ .filter((tx) => tx.input.indexOf('0x095ea7b3') === 0)
134
+ .flatMap((tx) => tx.logs),
135
+ ...rpcBlock19217804.block.logs.filter((l) => l.topics[0] ===
136
+ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'),
137
+ ];
138
+ expect(ethBlock19217804.logs.length).toBe(rpcLogs19217804.length);
128
139
  // This matches with dictionaryQueryEntries[0].topics
129
140
  expect(ethBlock19217804.logs[0].topics).toContain('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef');
130
141
  }, 10000);
@@ -222,7 +233,7 @@ describe('eth dictionary v2', () => {
222
233
  const res = await ethDictionaryV2.getData(18723210, 18733210, 100);
223
234
  expect(res?.batchBlocks.length).toEqual(0);
224
235
  expect(res?.lastBufferedHeight).toEqual(18733210);
225
- });
236
+ }, 10_000);
226
237
  });
227
238
  describe('buildDictionaryV2QueryEntry', () => {
228
239
  it('Build filter for !null', () => {