@apibara/protocol 2.1.0-beta.53 → 2.1.0-beta.55

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/dist/index.cjs CHANGED
@@ -6,7 +6,7 @@ const assert = require('node:assert');
6
6
  const consola = require('consola');
7
7
  const niceGrpc = require('nice-grpc');
8
8
  require('protobufjs/minimal.js');
9
- const rpc_index = require('./shared/protocol.27cb7b14.cjs');
9
+ const rpc_index = require('./shared/protocol.6ea6c882.cjs');
10
10
  require('viem');
11
11
  require('long');
12
12
 
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { s as stream } from './shared/protocol.0e734e33.cjs';
2
2
  export { B as Bytes, b as BytesFromUint8Array, w as Client, u as ClientCallOptions, x as CreateClientOptions, C as Cursor, e as CursorFromBytes, c as CursorProto, q as Data, g as DataFinality, h as DataProduction, D as DnaStreamClient, a as DnaStreamDefinition, k as Duration, j as DurationCodec, F as Finalize, G as GrpcClient, H as Heartbeat, I as Invalidate, R as ResponseWithoutData, S as StatusRequest, f as StatusResponse, o as StdErr, m as StdOut, t as StreamConfig, A as StreamDataIterable, v as StreamDataOptions, l as StreamDataRequest, r as StreamDataResponse, p as SystemMessage, T as TimeoutError, z as createAuthenticatedClient, y as createClient, d as createCursor, i as isCursor, n as normalizeCursor } from './shared/protocol.0e734e33.cjs';
3
3
  import _m0 from 'protobufjs/minimal.js';
4
- export { i as rpc } from './shared/protocol.d99fa7ff.cjs';
4
+ export { i as rpc } from './shared/protocol.5dc2fc0d.cjs';
5
5
  export { ClientError, Metadata, ServerError, Status } from 'nice-grpc';
6
6
  import './codec.cjs';
7
7
  import 'nice-grpc-common';
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { s as stream } from './shared/protocol.21e66b9e.mjs';
2
2
  export { B as Bytes, b as BytesFromUint8Array, w as Client, u as ClientCallOptions, x as CreateClientOptions, C as Cursor, e as CursorFromBytes, c as CursorProto, q as Data, g as DataFinality, h as DataProduction, D as DnaStreamClient, a as DnaStreamDefinition, k as Duration, j as DurationCodec, F as Finalize, G as GrpcClient, H as Heartbeat, I as Invalidate, R as ResponseWithoutData, S as StatusRequest, f as StatusResponse, o as StdErr, m as StdOut, t as StreamConfig, A as StreamDataIterable, v as StreamDataOptions, l as StreamDataRequest, r as StreamDataResponse, p as SystemMessage, T as TimeoutError, z as createAuthenticatedClient, y as createClient, d as createCursor, i as isCursor, n as normalizeCursor } from './shared/protocol.21e66b9e.mjs';
3
3
  import _m0 from 'protobufjs/minimal.js';
4
- export { i as rpc } from './shared/protocol.e53aa437.mjs';
4
+ export { i as rpc } from './shared/protocol.1a69a01d.mjs';
5
5
  export { ClientError, Metadata, ServerError, Status } from 'nice-grpc';
6
6
  import './codec.mjs';
7
7
  import 'nice-grpc-common';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { s as stream } from './shared/protocol.8fb09325.js';
2
2
  export { B as Bytes, b as BytesFromUint8Array, w as Client, u as ClientCallOptions, x as CreateClientOptions, C as Cursor, e as CursorFromBytes, c as CursorProto, q as Data, g as DataFinality, h as DataProduction, D as DnaStreamClient, a as DnaStreamDefinition, k as Duration, j as DurationCodec, F as Finalize, G as GrpcClient, H as Heartbeat, I as Invalidate, R as ResponseWithoutData, S as StatusRequest, f as StatusResponse, o as StdErr, m as StdOut, t as StreamConfig, A as StreamDataIterable, v as StreamDataOptions, l as StreamDataRequest, r as StreamDataResponse, p as SystemMessage, T as TimeoutError, z as createAuthenticatedClient, y as createClient, d as createCursor, i as isCursor, n as normalizeCursor } from './shared/protocol.8fb09325.js';
3
3
  import _m0 from 'protobufjs/minimal.js';
4
- export { i as rpc } from './shared/protocol.f900827e.js';
4
+ export { i as rpc } from './shared/protocol.1b2e5598.js';
5
5
  export { ClientError, Metadata, ServerError, Status } from 'nice-grpc';
6
6
  import './codec.js';
7
7
  import 'nice-grpc-common';
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import consola from 'consola';
6
6
  import { createChannel, createClient as createClient$1, Metadata } from 'nice-grpc';
7
7
  export { ClientError, Metadata, ServerError, Status } from 'nice-grpc';
8
8
  import 'protobufjs/minimal.js';
9
- export { i as rpc } from './shared/protocol.05fab89c.mjs';
9
+ export { i as rpc } from './shared/protocol.431c3863.mjs';
10
10
  import 'viem';
11
11
  import 'long';
12
12
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const rpc_index = require('../shared/protocol.27cb7b14.cjs');
3
+ const rpc_index = require('../shared/protocol.6ea6c882.cjs');
4
4
  require('viem');
5
5
 
6
6
 
@@ -1,4 +1,4 @@
1
- export { B as BlockInfo, c as FetchBlockByNumberArgs, d as FetchBlockByNumberResult, F as FetchBlockRangeArgs, b as FetchBlockRangeResult, a as FetchBlockResult, e as FetchCursorArgs, f as FetchCursorRangeArgs, g as RpcClient, j as RpcDataStream, R as RpcStreamConfig, V as ValidateFilterResult, h as createRpcClient } from '../shared/protocol.d99fa7ff.cjs';
1
+ export { B as BlockInfo, c as FetchBlockByHashArgs, d as FetchBlockByHashResult, F as FetchBlockRangeArgs, b as FetchBlockRangeResult, a as FetchBlockResult, e as FetchCursorArgs, f as FetchCursorRangeArgs, g as RpcClient, j as RpcDataStream, R as RpcStreamConfig, V as ValidateFilterResult, h as createRpcClient } from '../shared/protocol.5dc2fc0d.cjs';
2
2
  import '../shared/protocol.0e734e33.cjs';
3
3
  import '../codec.cjs';
4
4
  import 'nice-grpc-common';
@@ -1,4 +1,4 @@
1
- export { B as BlockInfo, c as FetchBlockByNumberArgs, d as FetchBlockByNumberResult, F as FetchBlockRangeArgs, b as FetchBlockRangeResult, a as FetchBlockResult, e as FetchCursorArgs, f as FetchCursorRangeArgs, g as RpcClient, j as RpcDataStream, R as RpcStreamConfig, V as ValidateFilterResult, h as createRpcClient } from '../shared/protocol.e53aa437.mjs';
1
+ export { B as BlockInfo, c as FetchBlockByHashArgs, d as FetchBlockByHashResult, F as FetchBlockRangeArgs, b as FetchBlockRangeResult, a as FetchBlockResult, e as FetchCursorArgs, f as FetchCursorRangeArgs, g as RpcClient, j as RpcDataStream, R as RpcStreamConfig, V as ValidateFilterResult, h as createRpcClient } from '../shared/protocol.1a69a01d.mjs';
2
2
  import '../shared/protocol.21e66b9e.mjs';
3
3
  import '../codec.mjs';
4
4
  import 'nice-grpc-common';
@@ -1,4 +1,4 @@
1
- export { B as BlockInfo, c as FetchBlockByNumberArgs, d as FetchBlockByNumberResult, F as FetchBlockRangeArgs, b as FetchBlockRangeResult, a as FetchBlockResult, e as FetchCursorArgs, f as FetchCursorRangeArgs, g as RpcClient, j as RpcDataStream, R as RpcStreamConfig, V as ValidateFilterResult, h as createRpcClient } from '../shared/protocol.f900827e.js';
1
+ export { B as BlockInfo, c as FetchBlockByHashArgs, d as FetchBlockByHashResult, F as FetchBlockRangeArgs, b as FetchBlockRangeResult, a as FetchBlockResult, e as FetchCursorArgs, f as FetchCursorRangeArgs, g as RpcClient, j as RpcDataStream, R as RpcStreamConfig, V as ValidateFilterResult, h as createRpcClient } from '../shared/protocol.1b2e5598.js';
2
2
  import '../shared/protocol.8fb09325.js';
3
3
  import '../codec.js';
4
4
  import 'nice-grpc-common';
@@ -1,3 +1,3 @@
1
- export { a as RpcClient, b as RpcDataStream, R as RpcStreamConfig, c as createRpcClient } from '../shared/protocol.05fab89c.mjs';
1
+ export { a as RpcClient, b as RpcDataStream, R as RpcStreamConfig, c as createRpcClient } from '../shared/protocol.431c3863.mjs';
2
2
  import 'viem';
3
3
  //# sourceMappingURL=index.mjs.map
@@ -21,19 +21,14 @@ type BlockInfo = {
21
21
  blockHash: Bytes;
22
22
  parentBlockHash: Bytes;
23
23
  };
24
- type FetchBlockByNumberArgs<TFilter> = {
25
- blockNumber: bigint;
26
- expectedParentBlockHash: Bytes;
24
+ type FetchBlockByHashArgs<TFilter> = {
25
+ blockHash: Bytes;
27
26
  isAtHead: boolean;
28
27
  filter: TFilter;
29
28
  };
30
- type FetchBlockByNumberResult<TBlock> = {
31
- status: "success";
29
+ type FetchBlockByHashResult<TBlock> = {
32
30
  data: FetchBlockResult<TBlock>;
33
31
  blockInfo: BlockInfo;
34
- } | {
35
- status: "reorg";
36
- blockInfo: BlockInfo;
37
32
  };
38
33
  type FetchCursorRangeArgs = {
39
34
  startBlockNumber: bigint;
@@ -66,7 +61,7 @@ declare abstract class RpcStreamConfig<TFilter, TBlock> {
66
61
  abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;
67
62
  abstract validateFilter(filter: TFilter): ValidateFilterResult;
68
63
  abstract fetchBlockRange(args: FetchBlockRangeArgs<TFilter>): Promise<FetchBlockRangeResult<TBlock>>;
69
- abstract fetchBlockByNumber(args: FetchBlockByNumberArgs<TFilter>): Promise<FetchBlockByNumberResult<TBlock>>;
64
+ abstract fetchBlockByHash(args: FetchBlockByHashArgs<TFilter>): Promise<FetchBlockByHashResult<TBlock>>;
70
65
  }
71
66
 
72
67
  declare class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {
@@ -88,8 +83,8 @@ declare class RpcDataStream<TFilter, TBlock> {
88
83
  }
89
84
 
90
85
  type index_BlockInfo = BlockInfo;
91
- type index_FetchBlockByNumberArgs<TFilter> = FetchBlockByNumberArgs<TFilter>;
92
- type index_FetchBlockByNumberResult<TBlock> = FetchBlockByNumberResult<TBlock>;
86
+ type index_FetchBlockByHashArgs<TFilter> = FetchBlockByHashArgs<TFilter>;
87
+ type index_FetchBlockByHashResult<TBlock> = FetchBlockByHashResult<TBlock>;
93
88
  type index_FetchBlockRangeArgs<TFilter> = FetchBlockRangeArgs<TFilter>;
94
89
  type index_FetchBlockRangeResult<TBlock> = FetchBlockRangeResult<TBlock>;
95
90
  type index_FetchBlockResult<TBlock> = FetchBlockResult<TBlock>;
@@ -104,7 +99,7 @@ declare const index_RpcStreamConfig: typeof RpcStreamConfig;
104
99
  type index_ValidateFilterResult = ValidateFilterResult;
105
100
  declare const index_createRpcClient: typeof createRpcClient;
106
101
  declare namespace index {
107
- export { type index_BlockInfo as BlockInfo, type index_FetchBlockByNumberArgs as FetchBlockByNumberArgs, type index_FetchBlockByNumberResult as FetchBlockByNumberResult, type index_FetchBlockRangeArgs as FetchBlockRangeArgs, type index_FetchBlockRangeResult as FetchBlockRangeResult, type index_FetchBlockResult as FetchBlockResult, type index_FetchCursorArgs as FetchCursorArgs, type index_FetchCursorRangeArgs as FetchCursorRangeArgs, index_RpcClient as RpcClient, index_RpcDataStream as RpcDataStream, index_RpcStreamConfig as RpcStreamConfig, type index_ValidateFilterResult as ValidateFilterResult, index_createRpcClient as createRpcClient };
102
+ export { type index_BlockInfo as BlockInfo, type index_FetchBlockByHashArgs as FetchBlockByHashArgs, type index_FetchBlockByHashResult as FetchBlockByHashResult, type index_FetchBlockRangeArgs as FetchBlockRangeArgs, type index_FetchBlockRangeResult as FetchBlockRangeResult, type index_FetchBlockResult as FetchBlockResult, type index_FetchCursorArgs as FetchCursorArgs, type index_FetchCursorRangeArgs as FetchCursorRangeArgs, index_RpcClient as RpcClient, index_RpcDataStream as RpcDataStream, index_RpcStreamConfig as RpcStreamConfig, type index_ValidateFilterResult as ValidateFilterResult, index_createRpcClient as createRpcClient };
108
103
  }
109
104
 
110
- export { type BlockInfo as B, type FetchBlockRangeArgs as F, RpcStreamConfig as R, type ValidateFilterResult as V, type FetchBlockResult as a, type FetchBlockRangeResult as b, type FetchBlockByNumberArgs as c, type FetchBlockByNumberResult as d, type FetchCursorArgs as e, type FetchCursorRangeArgs as f, RpcClient as g, createRpcClient as h, index as i, RpcDataStream as j };
105
+ export { type BlockInfo as B, type FetchBlockRangeArgs as F, RpcStreamConfig as R, type ValidateFilterResult as V, type FetchBlockResult as a, type FetchBlockRangeResult as b, type FetchBlockByHashArgs as c, type FetchBlockByHashResult as d, type FetchCursorArgs as e, type FetchCursorRangeArgs as f, RpcClient as g, createRpcClient as h, index as i, RpcDataStream as j };
@@ -21,19 +21,14 @@ type BlockInfo = {
21
21
  blockHash: Bytes;
22
22
  parentBlockHash: Bytes;
23
23
  };
24
- type FetchBlockByNumberArgs<TFilter> = {
25
- blockNumber: bigint;
26
- expectedParentBlockHash: Bytes;
24
+ type FetchBlockByHashArgs<TFilter> = {
25
+ blockHash: Bytes;
27
26
  isAtHead: boolean;
28
27
  filter: TFilter;
29
28
  };
30
- type FetchBlockByNumberResult<TBlock> = {
31
- status: "success";
29
+ type FetchBlockByHashResult<TBlock> = {
32
30
  data: FetchBlockResult<TBlock>;
33
31
  blockInfo: BlockInfo;
34
- } | {
35
- status: "reorg";
36
- blockInfo: BlockInfo;
37
32
  };
38
33
  type FetchCursorRangeArgs = {
39
34
  startBlockNumber: bigint;
@@ -66,7 +61,7 @@ declare abstract class RpcStreamConfig<TFilter, TBlock> {
66
61
  abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;
67
62
  abstract validateFilter(filter: TFilter): ValidateFilterResult;
68
63
  abstract fetchBlockRange(args: FetchBlockRangeArgs<TFilter>): Promise<FetchBlockRangeResult<TBlock>>;
69
- abstract fetchBlockByNumber(args: FetchBlockByNumberArgs<TFilter>): Promise<FetchBlockByNumberResult<TBlock>>;
64
+ abstract fetchBlockByHash(args: FetchBlockByHashArgs<TFilter>): Promise<FetchBlockByHashResult<TBlock>>;
70
65
  }
71
66
 
72
67
  declare class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {
@@ -88,8 +83,8 @@ declare class RpcDataStream<TFilter, TBlock> {
88
83
  }
89
84
 
90
85
  type index_BlockInfo = BlockInfo;
91
- type index_FetchBlockByNumberArgs<TFilter> = FetchBlockByNumberArgs<TFilter>;
92
- type index_FetchBlockByNumberResult<TBlock> = FetchBlockByNumberResult<TBlock>;
86
+ type index_FetchBlockByHashArgs<TFilter> = FetchBlockByHashArgs<TFilter>;
87
+ type index_FetchBlockByHashResult<TBlock> = FetchBlockByHashResult<TBlock>;
93
88
  type index_FetchBlockRangeArgs<TFilter> = FetchBlockRangeArgs<TFilter>;
94
89
  type index_FetchBlockRangeResult<TBlock> = FetchBlockRangeResult<TBlock>;
95
90
  type index_FetchBlockResult<TBlock> = FetchBlockResult<TBlock>;
@@ -104,7 +99,7 @@ declare const index_RpcStreamConfig: typeof RpcStreamConfig;
104
99
  type index_ValidateFilterResult = ValidateFilterResult;
105
100
  declare const index_createRpcClient: typeof createRpcClient;
106
101
  declare namespace index {
107
- export { type index_BlockInfo as BlockInfo, type index_FetchBlockByNumberArgs as FetchBlockByNumberArgs, type index_FetchBlockByNumberResult as FetchBlockByNumberResult, type index_FetchBlockRangeArgs as FetchBlockRangeArgs, type index_FetchBlockRangeResult as FetchBlockRangeResult, type index_FetchBlockResult as FetchBlockResult, type index_FetchCursorArgs as FetchCursorArgs, type index_FetchCursorRangeArgs as FetchCursorRangeArgs, index_RpcClient as RpcClient, index_RpcDataStream as RpcDataStream, index_RpcStreamConfig as RpcStreamConfig, type index_ValidateFilterResult as ValidateFilterResult, index_createRpcClient as createRpcClient };
102
+ export { type index_BlockInfo as BlockInfo, type index_FetchBlockByHashArgs as FetchBlockByHashArgs, type index_FetchBlockByHashResult as FetchBlockByHashResult, type index_FetchBlockRangeArgs as FetchBlockRangeArgs, type index_FetchBlockRangeResult as FetchBlockRangeResult, type index_FetchBlockResult as FetchBlockResult, type index_FetchCursorArgs as FetchCursorArgs, type index_FetchCursorRangeArgs as FetchCursorRangeArgs, index_RpcClient as RpcClient, index_RpcDataStream as RpcDataStream, index_RpcStreamConfig as RpcStreamConfig, type index_ValidateFilterResult as ValidateFilterResult, index_createRpcClient as createRpcClient };
108
103
  }
109
104
 
110
- export { type BlockInfo as B, type FetchBlockRangeArgs as F, RpcStreamConfig as R, type ValidateFilterResult as V, type FetchBlockResult as a, type FetchBlockRangeResult as b, type FetchBlockByNumberArgs as c, type FetchBlockByNumberResult as d, type FetchCursorArgs as e, type FetchCursorRangeArgs as f, RpcClient as g, createRpcClient as h, index as i, RpcDataStream as j };
105
+ export { type BlockInfo as B, type FetchBlockRangeArgs as F, RpcStreamConfig as R, type ValidateFilterResult as V, type FetchBlockResult as a, type FetchBlockRangeResult as b, type FetchBlockByHashArgs as c, type FetchBlockByHashResult as d, type FetchCursorArgs as e, type FetchCursorRangeArgs as f, RpcClient as g, createRpcClient as h, index as i, RpcDataStream as j };
@@ -54,6 +54,9 @@ class ChainTracker {
54
54
  return blockInfoToCursor(__privateGet(this, _finalized));
55
55
  }
56
56
  updateFinalized(newFinalized) {
57
+ console.log(
58
+ `[CT] updateFinalized: new=${newFinalized.blockNumber} old=${__privateGet(this, _finalized).blockNumber}`
59
+ );
57
60
  if (newFinalized.blockNumber < __privateGet(this, _finalized).blockNumber) {
58
61
  throw new Error("Finalized cursor moved backwards");
59
62
  }
@@ -71,6 +74,7 @@ class ChainTracker {
71
74
  return true;
72
75
  }
73
76
  addToCanonicalChain({ blockInfo }) {
77
+ console.log(`[CT] addToCanonicalChain: block=${blockInfo.blockNumber}`);
74
78
  const existing = __privateGet(this, _canonical).get(blockInfo.blockNumber);
75
79
  if (existing) {
76
80
  if (existing.blockHash !== blockInfo.blockHash) {
@@ -94,6 +98,9 @@ class ChainTracker {
94
98
  fetchCursorByHash,
95
99
  fetchCursorRange
96
100
  }) {
101
+ console.log(
102
+ `[CT] updateHead: new=${newHead.blockNumber} old=${__privateGet(this, _head).blockNumber}`
103
+ );
97
104
  if (newHead.blockNumber === __privateGet(this, _head).blockNumber && newHead.blockHash === __privateGet(this, _head).blockHash) {
98
105
  return { status: "unchanged" };
99
106
  }
@@ -142,6 +149,9 @@ class ChainTracker {
142
149
  }
143
150
  throw new Error("Cannot reconcile new head with canonical chain.");
144
151
  }
152
+ console.log(
153
+ `[CT] moving from ${__privateGet(this, _head).blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - __privateGet(this, _head).blockNumber} blocks)`
154
+ );
145
155
  let currentBlockNumber = __privateGet(this, _head).blockNumber + 1n;
146
156
  while (true) {
147
157
  let endBlockNumber = currentBlockNumber + __privateGet(this, _batchSize);
@@ -302,6 +312,7 @@ class RpcDataStream {
302
312
  lastFinalizedRefresh: Date.now(),
303
313
  lastHeadRefresh: Date.now(),
304
314
  lastBackfillMessage: Date.now(),
315
+ lastEmptyBlockNumber: void 0,
305
316
  chainTracker,
306
317
  config: this.config,
307
318
  heartbeatIntervalMs: this.heartbeatIntervalMs,
@@ -332,6 +343,9 @@ async function* dataStreamLoop(state) {
332
343
  state.lastFinalizedRefresh = Date.now();
333
344
  }
334
345
  const finalized = chainTracker.finalized();
346
+ console.log(
347
+ `[DS] RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`
348
+ );
335
349
  if (cursor.orderKey < finalized.orderKey) {
336
350
  yield* backfillFinalizedBlocks(state);
337
351
  } else {
@@ -393,7 +407,7 @@ async function* produceLiveBlocks(state) {
393
407
  state.lastHeadRefresh = Date.now();
394
408
  if (result.status === "reorg") {
395
409
  const { cursor: cursor2 } = result;
396
- if (cursor2.orderKey < state.cursor.orderKey) {
410
+ if (cursor2.orderKey < state.cursor.orderKey || state.lastEmptyBlockNumber !== void 0 && cursor2.orderKey < state.lastEmptyBlockNumber) {
397
411
  state.cursor = cursor2;
398
412
  yield {
399
413
  _tag: "invalidate",
@@ -410,6 +424,26 @@ async function* produceLiveBlocks(state) {
410
424
  force: false,
411
425
  filter
412
426
  });
427
+ if (filterData.data.length === 0 && head.uniqueKey !== void 0) {
428
+ if (state.lastEmptyBlockNumber === void 0 || head.orderKey > state.lastEmptyBlockNumber) {
429
+ const { data } = await config.fetchBlockByHash({
430
+ blockHash: head.uniqueKey,
431
+ isAtHead: true,
432
+ filter
433
+ });
434
+ yield {
435
+ _tag: "data",
436
+ data: {
437
+ cursor: data.cursor,
438
+ endCursor: data.endCursor,
439
+ data: [data.block],
440
+ finality: "accepted",
441
+ production: "live"
442
+ }
443
+ };
444
+ state.lastEmptyBlockNumber = head.orderKey;
445
+ }
446
+ }
413
447
  for (const { cursor: cursor2, endCursor, block } of filterData.data) {
414
448
  if (!chainTracker.isCanonical(endCursor)) {
415
449
  throw new Error("Trying to process non-canonical block");
@@ -557,4 +591,4 @@ const index = {
557
591
  };
558
592
 
559
593
  export { RpcStreamConfig as R, RpcClient as a, RpcDataStream as b, createRpcClient as c, index as i };
560
- //# sourceMappingURL=protocol.05fab89c.mjs.map
594
+ //# sourceMappingURL=protocol.431c3863.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.431c3863.mjs","sources":["../../src/rpc/config.ts","../../src/rpc/helpers.ts","../../src/rpc/chain-tracker.ts","../../src/rpc/data-stream.ts","../../src/rpc/client.ts"],"sourcesContent":["import type { Bytes, Cursor } from \"../common\";\n\nexport type FetchBlockRangeArgs<TFilter> = {\n startBlock: bigint;\n maxBlock: bigint;\n force: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockRangeResult<TBlock> = {\n startBlock: bigint;\n endBlock: bigint;\n data: FetchBlockResult<TBlock>[];\n};\n\nexport type FetchBlockResult<TBlock> = {\n block: TBlock | null;\n cursor: Cursor | undefined;\n endCursor: Cursor;\n};\n\nexport type BlockInfo = {\n blockNumber: bigint;\n blockHash: Bytes;\n parentBlockHash: Bytes;\n};\n\nexport type FetchBlockByHashArgs<TFilter> = {\n blockHash: Bytes;\n isAtHead: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockByHashResult<TBlock> = {\n data: FetchBlockResult<TBlock>;\n blockInfo: BlockInfo;\n};\n\nexport type FetchCursorRangeArgs = {\n startBlockNumber: bigint;\n endBlockNumber: bigint;\n};\n\nexport type FetchCursorArgs =\n | {\n blockTag: \"latest\" | \"finalized\";\n blockNumber?: undefined;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber: bigint;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber?: undefined;\n blockHash: Bytes;\n };\n\nexport type ValidateFilterResult =\n | {\n valid: true;\n error?: undefined;\n }\n | {\n valid: false;\n error: string;\n };\n\nexport abstract class RpcStreamConfig<TFilter, TBlock> {\n abstract headRefreshIntervalMs(): number;\n abstract finalizedRefreshIntervalMs(): number;\n\n abstract fetchCursorRange(args: FetchCursorRangeArgs): Promise<BlockInfo[]>;\n abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;\n\n abstract validateFilter(filter: TFilter): ValidateFilterResult;\n\n abstract fetchBlockRange(\n args: FetchBlockRangeArgs<TFilter>,\n ): Promise<FetchBlockRangeResult<TBlock>>;\n\n abstract fetchBlockByHash(\n args: FetchBlockByHashArgs<TFilter>,\n ): Promise<FetchBlockByHashResult<TBlock>>;\n}\n","import type { Cursor } from \"../common\";\nimport type { BlockInfo } from \"./config\";\n\nexport function blockInfoToCursor(blockInfo: BlockInfo): Cursor {\n return {\n orderKey: blockInfo.blockNumber,\n uniqueKey: blockInfo.blockHash,\n };\n}\n","import { fromHex } from \"viem\";\nimport type { Bytes, Cursor } from \"../common\";\nimport type { BlockInfo, FetchCursorRangeArgs } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\ntype UpdateHeadArgs = {\n newHead: BlockInfo;\n fetchCursorByHash: (hash: Bytes) => Promise<BlockInfo | null>;\n fetchCursorRange: (args: FetchCursorRangeArgs) => Promise<BlockInfo[]>;\n};\n\ntype UpdateHeadResult =\n | {\n status: \"unchanged\";\n }\n | {\n status: \"success\";\n }\n | {\n status: \"reorg\";\n cursor: Cursor;\n };\n\nexport class ChainTracker {\n #finalized: BlockInfo;\n #head: BlockInfo;\n #canonical: Map<bigint, BlockInfo>;\n #batchSize: bigint;\n\n constructor({\n head,\n finalized,\n batchSize,\n }: {\n finalized: BlockInfo;\n head: BlockInfo;\n batchSize: bigint;\n }) {\n this.#finalized = finalized;\n this.#head = head;\n this.#batchSize = batchSize;\n\n this.#canonical = new Map([\n [finalized.blockNumber, finalized],\n [head.blockNumber, head],\n ]);\n }\n\n head(): Cursor {\n return blockInfoToCursor(this.#head);\n }\n\n finalized(): Cursor {\n return blockInfoToCursor(this.#finalized);\n }\n\n updateFinalized(newFinalized: BlockInfo) {\n console.log(\n `[CT] updateFinalized: new=${newFinalized.blockNumber} old=${this.#finalized.blockNumber}`,\n );\n\n if (newFinalized.blockNumber < this.#finalized.blockNumber) {\n throw new Error(\"Finalized cursor moved backwards\");\n }\n\n if (newFinalized.blockNumber === this.#finalized.blockNumber) {\n if (newFinalized.blockHash !== this.#finalized.blockHash) {\n throw new Error(\"Received a different finalized cursor\");\n }\n\n return false;\n }\n\n // Delete all blocks that are now finalized.\n for (\n let bn = this.#finalized.blockNumber;\n bn < newFinalized.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n this.#canonical.set(newFinalized.blockNumber, newFinalized);\n this.#finalized = newFinalized;\n\n return true;\n }\n\n addToCanonicalChain({ blockInfo }: { blockInfo: BlockInfo }) {\n console.log(`[CT] addToCanonicalChain: block=${blockInfo.blockNumber}`);\n\n const existing = this.#canonical.get(blockInfo.blockNumber);\n\n if (existing) {\n if (existing.blockHash !== blockInfo.blockHash) {\n throw new Error(\n `Block already exists in canonical chain: previous ${existing.blockHash}, new ${blockInfo.blockHash}`,\n );\n }\n }\n\n const parent = this.#canonical.get(blockInfo.blockNumber - 1n);\n if (!parent) {\n throw new Error(\"Parent block not in canonical chain\");\n }\n\n if (parent.blockHash !== blockInfo.parentBlockHash) {\n throw new Error(\"Parent block hash mismatch.\");\n }\n\n this.#canonical.set(blockInfo.blockNumber, blockInfo);\n\n // console.log(\"Canon updated: \", canonical);\n\n return { status: \"success\" };\n }\n\n async updateHead({\n newHead,\n fetchCursorByHash,\n fetchCursorRange,\n }: UpdateHeadArgs): Promise<UpdateHeadResult> {\n console.log(\n `[CT] updateHead: new=${newHead.blockNumber} old=${this.#head.blockNumber}`,\n );\n\n // No changes to the chain.\n if (\n newHead.blockNumber === this.#head.blockNumber &&\n newHead.blockHash === this.#head.blockHash\n ) {\n return { status: \"unchanged\" };\n }\n\n // Most common case: the new head is the block after the current head.\n if (\n newHead.blockNumber === this.#head.blockNumber + 1n &&\n newHead.parentBlockHash === this.#head.blockHash\n ) {\n this.#canonical.set(newHead.blockNumber, newHead);\n this.#head = newHead;\n return { status: \"success\" };\n }\n\n // The new chain is not longer.\n if (newHead.blockNumber <= this.#head.blockNumber) {\n // console.log(\"head=\", this.#head, \"newhead=\", newHead);\n let currentNewHead = newHead;\n // Delete all blocks from canonical chain after the new head.\n for (\n let bn = newHead.blockNumber + 1n;\n bn <= this.#head.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n // Check if the chain was simply shrunk to this block.\n const existing = this.#canonical.get(currentNewHead.blockNumber);\n if (existing && existing.blockHash === currentNewHead.blockHash) {\n this.#head = existing;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(existing),\n };\n }\n\n while (currentNewHead.blockNumber > this.#finalized.blockNumber) {\n this.#canonical.delete(currentNewHead.blockNumber);\n\n const canonicalParent = this.#canonical.get(\n currentNewHead.blockNumber - 1n,\n );\n\n if (!canonicalParent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: missing parent in canonical chain\",\n );\n }\n\n // We found the common ancestor.\n if (canonicalParent.blockHash === currentNewHead.parentBlockHash) {\n this.#head = canonicalParent;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(canonicalParent),\n };\n }\n\n const parent = await fetchCursorByHash(currentNewHead.parentBlockHash);\n\n if (!parent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: failed to fetch parent\",\n );\n }\n\n currentNewHead = parent;\n }\n\n throw new Error(\"Cannot reconcile new head with canonical chain.\");\n }\n\n // In all other cases we need to \"join\" the new head with the existing chain.\n // The new chain is longer and we need the missing blocks.\n // This may result in reorgs.\n\n console.log(\n `[CT] moving from ${this.#head.blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - this.#head.blockNumber} blocks)`,\n );\n\n let currentBlockNumber = this.#head.blockNumber + 1n;\n\n while (true) {\n let endBlockNumber = currentBlockNumber + this.#batchSize;\n if (endBlockNumber > newHead.blockNumber) {\n endBlockNumber = newHead.blockNumber;\n }\n\n const missing = await fetchCursorRange({\n startBlockNumber: currentBlockNumber,\n endBlockNumber,\n });\n\n for (const block of missing) {\n const canonicalParent = this.#canonical.get(block.blockNumber - 1n);\n if (\n !canonicalParent ||\n canonicalParent.blockHash !== block.parentBlockHash\n ) {\n throw new Error(\n \"Chain reorganization detected. Recovery not implemented\",\n );\n }\n\n this.#canonical.set(block.blockNumber, block);\n }\n\n if (endBlockNumber === newHead.blockNumber) {\n break;\n }\n\n currentBlockNumber = endBlockNumber + 1n;\n }\n\n this.#head = newHead;\n\n return { status: \"success\" };\n }\n\n isCanonical({ orderKey, uniqueKey }: Cursor) {\n if (!uniqueKey) {\n return true;\n }\n\n const block = this.#canonical.get(orderKey);\n if (!block) {\n return true;\n }\n\n return block.blockHash === uniqueKey;\n }\n\n async initializeStartingCursor({\n cursor,\n fetchCursor,\n }: {\n cursor: Cursor;\n fetchCursor: (blockNumber: bigint) => Promise<BlockInfo | null>;\n }): Promise<\n | { canonical: true; reason?: undefined; fullCursor: Cursor }\n | { canonical: false; reason: string; fullCursor?: undefined }\n > {\n const head = this.head();\n const finalized = this.finalized();\n\n if (cursor.orderKey > head.orderKey) {\n return { canonical: false, reason: \"cursor is ahead of head\" };\n }\n\n const expectedInfo = await fetchCursor(cursor.orderKey);\n if (!cursor.uniqueKey) {\n if (expectedInfo === null) {\n throw new Error(\"Failed to initialize canonical cursor\");\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: blockInfoToCursor(expectedInfo) };\n }\n\n if (expectedInfo === null) {\n return {\n canonical: false,\n reason: \"expected block does not exist\",\n };\n }\n\n const expectedCursor = blockInfoToCursor(expectedInfo);\n\n // These two checks are redundant, but they are kept to avoid issues with bad config implementations.\n if (!expectedCursor.uniqueKey) {\n return {\n canonical: false,\n reason: \"expected cursor has no unique key (hash)\",\n };\n }\n\n if (expectedCursor.orderKey !== cursor.orderKey) {\n return {\n canonical: false,\n reason: \"cursor order key does not match expected order key\",\n };\n }\n\n if (\n fromHex(expectedCursor.uniqueKey, \"bigint\") !==\n fromHex(cursor.uniqueKey, \"bigint\")\n ) {\n return {\n canonical: false,\n reason: `cursor hash does not match expected hash: ${cursor.uniqueKey} !== ${expectedCursor.uniqueKey}`,\n };\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: expectedCursor };\n }\n}\n\nexport function createChainTracker({\n head,\n finalized,\n batchSize,\n}: {\n head: BlockInfo;\n finalized: BlockInfo;\n batchSize: bigint;\n}): ChainTracker {\n return new ChainTracker({ finalized, head, batchSize });\n}\n","import type { StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport { type ChainTracker, createChainTracker } from \"./chain-tracker\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\n\ntype State<TFilter, TBlock> = {\n // The network-specific config.\n config: RpcStreamConfig<TFilter, TBlock>;\n // The current cursor, that is the last block that was filtered.\n cursor: Cursor;\n // When the finalized block was last refreshed.\n lastFinalizedRefresh: number;\n // When the head was last refreshed.\n lastHeadRefresh: number;\n // When the last heartbeat was sent.\n lastHeartbeat: number;\n // When the last backfill message was sent.\n lastBackfillMessage: number;\n // The last empty header sent.\n lastEmptyBlockNumber: bigint | undefined;\n // Track the chain's state.\n chainTracker: ChainTracker;\n // Heartbeat interval in milliseconds.\n heartbeatIntervalMs: number;\n // The request filter.\n filter: TFilter;\n // The request options.\n options?: StreamDataOptions;\n};\n\nexport class RpcDataStream<TFilter, TBlock> {\n private heartbeatIntervalMs: number;\n\n constructor(\n private config: RpcStreamConfig<TFilter, TBlock>,\n private request: StreamDataRequest<TFilter>,\n private options?: StreamDataOptions,\n ) {\n this.heartbeatIntervalMs = request.heartbeatInterval\n ? Number(request.heartbeatInterval.seconds) * 1000\n : DEFAULT_HEARTBEAT_INTERVAL_MS;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamDataResponse<TBlock>> {\n const startingState = await this.initialize();\n yield* dataStreamLoop(startingState);\n }\n\n private async initialize(): Promise<State<TFilter, TBlock>> {\n if (this.request.filter.length === 0) {\n throw new Error(\"Request.filter: empty.\");\n }\n\n if (this.request.filter.length > 1) {\n throw new Error(\"Request.filter: only one filter is supported.\");\n }\n\n const [head, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n if (finalized === null) {\n throw new Error(\"EvmRpcStream requires a finalized block\");\n }\n\n if (head === null) {\n throw new Error(\"EvmRpcStream requires a chain with blocks.\");\n }\n\n const chainTracker = createChainTracker({\n head,\n finalized,\n batchSize: 20n,\n });\n\n let cursor: Cursor;\n if (this.request.startingCursor) {\n cursor = this.request.startingCursor;\n\n const { canonical, reason, fullCursor } =\n await chainTracker.initializeStartingCursor({\n cursor,\n fetchCursor: (blockNumber) =>\n this.config.fetchCursor({ blockNumber }),\n });\n\n if (!canonical) {\n throw new Error(`Starting cursor is not canonical: ${reason}`);\n }\n\n cursor = fullCursor;\n } else {\n cursor = { orderKey: -1n };\n }\n\n return {\n cursor,\n lastHeartbeat: Date.now(),\n lastFinalizedRefresh: Date.now(),\n lastHeadRefresh: Date.now(),\n lastBackfillMessage: Date.now(),\n lastEmptyBlockNumber: undefined,\n chainTracker,\n config: this.config,\n heartbeatIntervalMs: this.heartbeatIntervalMs,\n filter: this.request.filter[0],\n options: this.options,\n };\n }\n}\n\nasync function* dataStreamLoop<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n while (shouldContinue(state)) {\n const { cursor, chainTracker } = state;\n\n // Always check for heartbeats first to ensure we don't miss any.\n if (shouldSendHeartbeat(state)) {\n state.lastHeartbeat = Date.now();\n yield { _tag: \"heartbeat\" };\n }\n\n if (shouldRefreshFinalized(state)) {\n const finalizedInfo = await state.config.fetchCursor({\n blockTag: \"finalized\",\n });\n\n if (finalizedInfo === null) {\n throw new Error(\"Failed to fetch finalized cursor\");\n }\n\n const finalized = blockInfoToCursor(finalizedInfo);\n const finalizedChanged =\n state.chainTracker.updateFinalized(finalizedInfo);\n\n // Only send finalized if it's needed.\n if (finalizedChanged && state.cursor.orderKey > finalized.orderKey) {\n yield { _tag: \"finalize\", finalize: { cursor: finalized } };\n }\n\n state.lastFinalizedRefresh = Date.now();\n }\n\n const finalized = chainTracker.finalized();\n\n console.log(\n `[DS] RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`,\n );\n\n if (cursor.orderKey < finalized.orderKey) {\n yield* backfillFinalizedBlocks(state);\n } else {\n // If we're at the head, wait for a change.\n //\n // We don't want to produce a block immediately, but re-run the loop so\n // that it's like any other iteration.\n if (isAtHead(state)) {\n yield* waitForHeadChange(state);\n } else {\n yield* produceLiveBlocks(state);\n }\n }\n }\n}\n\nasync function* backfillFinalizedBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { cursor, chainTracker, config, filter } = state;\n const finalized = chainTracker.finalized();\n\n // While backfilling we want to regularly send some blocks (even if empty) so\n // that the client can store the cursor.\n const force = shouldForceBackfill(state);\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: finalized.orderKey,\n force,\n filter,\n });\n\n if (filterData.endBlock > finalized.orderKey) {\n throw new Error(\n \"Network-specific stream returned invalid data, crossing the finalized block.\",\n );\n }\n\n for (const data of filterData.data) {\n state.lastHeartbeat = Date.now();\n state.lastBackfillMessage = Date.now();\n yield {\n _tag: \"data\",\n data: {\n cursor: data.cursor,\n endCursor: data.endCursor,\n data: [data.block],\n finality: \"finalized\",\n production: \"backfill\",\n },\n };\n }\n\n // Notice that we check that filteredData.endBlock <= finalized.orderKey above.\n if (filterData.endBlock === finalized.orderKey) {\n // Prepare for transition to non-finalized data.\n state.cursor = finalized;\n } else {\n state.cursor = { orderKey: filterData.endBlock };\n }\n}\n\n// This is a generator to possibly produce data for live blocks.\n//\n// It's a generator because it's not guaranteed to produce data for the next block.\nasync function* produceLiveBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { config, cursor, chainTracker, filter } = state;\n\n if (shouldRefreshHead(state)) {\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n state.lastHeadRefresh = Date.now();\n\n if (result.status === \"reorg\") {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (\n cursor.orderKey < state.cursor.orderKey ||\n (state.lastEmptyBlockNumber !== undefined &&\n cursor.orderKey < state.lastEmptyBlockNumber)\n ) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n\n return;\n }\n }\n }\n\n const head = chainTracker.head();\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: head.orderKey,\n force: false,\n filter,\n });\n\n if (filterData.data.length === 0 && head.uniqueKey !== undefined) {\n // Send an empty block if we reached the head, but don't update the cursor.\n if (\n state.lastEmptyBlockNumber === undefined ||\n head.orderKey > state.lastEmptyBlockNumber\n ) {\n const { data } = await config.fetchBlockByHash({\n blockHash: head.uniqueKey,\n isAtHead: true,\n filter,\n });\n\n yield {\n _tag: \"data\",\n data: {\n cursor: data.cursor,\n endCursor: data.endCursor,\n data: [data.block],\n finality: \"accepted\",\n production: \"live\",\n },\n };\n\n state.lastEmptyBlockNumber = head.orderKey;\n }\n }\n\n for (const { cursor, endCursor, block } of filterData.data) {\n if (!chainTracker.isCanonical(endCursor)) {\n throw new Error(\"Trying to process non-canonical block\");\n }\n\n if (block !== null) {\n state.lastHeartbeat = Date.now();\n const production = isAtHead(state) ? \"live\" : \"backfill\";\n\n yield {\n _tag: \"data\",\n data: {\n cursor,\n endCursor,\n data: [block],\n finality: \"accepted\",\n production,\n },\n };\n }\n\n state.cursor = {\n orderKey: endCursor.orderKey,\n uniqueKey: endCursor.uniqueKey,\n };\n }\n}\n\nasync function* waitForHeadChange<TBlock>(\n state: State<unknown, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { chainTracker, config } = state;\n\n const heartbeatDeadline = state.lastHeartbeat + state.heartbeatIntervalMs;\n const finalizedRefreshDeadline =\n state.lastFinalizedRefresh + config.finalizedRefreshIntervalMs();\n\n while (true) {\n const now = Date.now();\n // Allow the outer loop to send the heartbeat message or refresh finalized blocks.\n if (now >= heartbeatDeadline || now >= finalizedRefreshDeadline) {\n return;\n }\n\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n switch (result.status) {\n case \"unchanged\": {\n const heartbeatTimeout = heartbeatDeadline - now;\n const finalizedTimeout = finalizedRefreshDeadline - now;\n\n // Wait until whatever happens next.\n await sleep(\n Math.min(\n heartbeatTimeout,\n finalizedTimeout,\n config.headRefreshIntervalMs(),\n ),\n );\n\n break;\n }\n case \"reorg\": {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (cursor.orderKey < state.cursor.orderKey) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n }\n\n break;\n }\n case \"success\": {\n // Chain grew without any issues. Go back to the top-level loop to produce data.\n return;\n }\n }\n }\n}\n\nfunction shouldSendHeartbeat(state: State<unknown, unknown>): boolean {\n const { heartbeatIntervalMs, lastHeartbeat } = state;\n const now = Date.now();\n return now - lastHeartbeat >= heartbeatIntervalMs;\n}\n\nfunction shouldForceBackfill(state: State<unknown, unknown>): boolean {\n const { lastBackfillMessage, heartbeatIntervalMs } = state;\n const now = Date.now();\n return now - lastBackfillMessage >= heartbeatIntervalMs;\n}\n\nfunction shouldContinue(state: State<unknown, unknown>): boolean {\n const { endingCursor } = state.options || {};\n if (endingCursor === undefined) return true;\n\n return state.cursor.orderKey < endingCursor.orderKey;\n}\n\nfunction shouldRefreshFinalized(state: State<unknown, unknown>): boolean {\n const { lastFinalizedRefresh, config } = state;\n const now = Date.now();\n return now - lastFinalizedRefresh >= config.finalizedRefreshIntervalMs();\n}\n\nfunction shouldRefreshHead(state: State<unknown, unknown>): boolean {\n const { lastHeadRefresh, config } = state;\n const now = Date.now();\n return now - lastHeadRefresh >= config.headRefreshIntervalMs();\n}\n\nfunction isAtHead(state: State<unknown, unknown>): boolean {\n const head = state.chainTracker.head();\n return state.cursor.orderKey === head.orderKey;\n}\n\nfunction sleep(duration: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, duration));\n}\n","import type { Client, ClientCallOptions, StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StatusRequest, StatusResponse } from \"../status\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { RpcDataStream } from \"./data-stream\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nexport class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {\n constructor(private config: RpcStreamConfig<TFilter, TBlock>) {}\n\n async status(\n _request?: StatusRequest,\n _options?: ClientCallOptions,\n ): Promise<StatusResponse> {\n const [currentHead, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n const starting: Cursor = { orderKey: 0n };\n\n return {\n currentHead: currentHead ? blockInfoToCursor(currentHead) : undefined,\n lastIngested: currentHead ? blockInfoToCursor(currentHead) : undefined,\n finalized: finalized ? blockInfoToCursor(finalized) : undefined,\n starting,\n };\n }\n\n streamData(\n request: StreamDataRequest<TFilter>,\n options?: StreamDataOptions,\n ): AsyncIterable<StreamDataResponse<TBlock>> {\n const index = 0;\n for (const filter of request.filter) {\n const { valid, error } = this.config.validateFilter(filter);\n if (!valid) {\n throw new Error(`Filter at position ${index} is invalid: ${error}`);\n }\n }\n\n return new RpcDataStream(this.config, request, options);\n }\n}\n\nexport function createRpcClient<TFilter, TBlock>(\n config: RpcStreamConfig<TFilter, TBlock>,\n): RpcClient<TFilter, TBlock> {\n return new RpcClient(config);\n}\n"],"names":["finalized","cursor"],"mappings":"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"}
@@ -21,19 +21,14 @@ type BlockInfo = {
21
21
  blockHash: Bytes;
22
22
  parentBlockHash: Bytes;
23
23
  };
24
- type FetchBlockByNumberArgs<TFilter> = {
25
- blockNumber: bigint;
26
- expectedParentBlockHash: Bytes;
24
+ type FetchBlockByHashArgs<TFilter> = {
25
+ blockHash: Bytes;
27
26
  isAtHead: boolean;
28
27
  filter: TFilter;
29
28
  };
30
- type FetchBlockByNumberResult<TBlock> = {
31
- status: "success";
29
+ type FetchBlockByHashResult<TBlock> = {
32
30
  data: FetchBlockResult<TBlock>;
33
31
  blockInfo: BlockInfo;
34
- } | {
35
- status: "reorg";
36
- blockInfo: BlockInfo;
37
32
  };
38
33
  type FetchCursorRangeArgs = {
39
34
  startBlockNumber: bigint;
@@ -66,7 +61,7 @@ declare abstract class RpcStreamConfig<TFilter, TBlock> {
66
61
  abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;
67
62
  abstract validateFilter(filter: TFilter): ValidateFilterResult;
68
63
  abstract fetchBlockRange(args: FetchBlockRangeArgs<TFilter>): Promise<FetchBlockRangeResult<TBlock>>;
69
- abstract fetchBlockByNumber(args: FetchBlockByNumberArgs<TFilter>): Promise<FetchBlockByNumberResult<TBlock>>;
64
+ abstract fetchBlockByHash(args: FetchBlockByHashArgs<TFilter>): Promise<FetchBlockByHashResult<TBlock>>;
70
65
  }
71
66
 
72
67
  declare class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {
@@ -88,8 +83,8 @@ declare class RpcDataStream<TFilter, TBlock> {
88
83
  }
89
84
 
90
85
  type index_BlockInfo = BlockInfo;
91
- type index_FetchBlockByNumberArgs<TFilter> = FetchBlockByNumberArgs<TFilter>;
92
- type index_FetchBlockByNumberResult<TBlock> = FetchBlockByNumberResult<TBlock>;
86
+ type index_FetchBlockByHashArgs<TFilter> = FetchBlockByHashArgs<TFilter>;
87
+ type index_FetchBlockByHashResult<TBlock> = FetchBlockByHashResult<TBlock>;
93
88
  type index_FetchBlockRangeArgs<TFilter> = FetchBlockRangeArgs<TFilter>;
94
89
  type index_FetchBlockRangeResult<TBlock> = FetchBlockRangeResult<TBlock>;
95
90
  type index_FetchBlockResult<TBlock> = FetchBlockResult<TBlock>;
@@ -104,7 +99,7 @@ declare const index_RpcStreamConfig: typeof RpcStreamConfig;
104
99
  type index_ValidateFilterResult = ValidateFilterResult;
105
100
  declare const index_createRpcClient: typeof createRpcClient;
106
101
  declare namespace index {
107
- export { type index_BlockInfo as BlockInfo, type index_FetchBlockByNumberArgs as FetchBlockByNumberArgs, type index_FetchBlockByNumberResult as FetchBlockByNumberResult, type index_FetchBlockRangeArgs as FetchBlockRangeArgs, type index_FetchBlockRangeResult as FetchBlockRangeResult, type index_FetchBlockResult as FetchBlockResult, type index_FetchCursorArgs as FetchCursorArgs, type index_FetchCursorRangeArgs as FetchCursorRangeArgs, index_RpcClient as RpcClient, index_RpcDataStream as RpcDataStream, index_RpcStreamConfig as RpcStreamConfig, type index_ValidateFilterResult as ValidateFilterResult, index_createRpcClient as createRpcClient };
102
+ export { type index_BlockInfo as BlockInfo, type index_FetchBlockByHashArgs as FetchBlockByHashArgs, type index_FetchBlockByHashResult as FetchBlockByHashResult, type index_FetchBlockRangeArgs as FetchBlockRangeArgs, type index_FetchBlockRangeResult as FetchBlockRangeResult, type index_FetchBlockResult as FetchBlockResult, type index_FetchCursorArgs as FetchCursorArgs, type index_FetchCursorRangeArgs as FetchCursorRangeArgs, index_RpcClient as RpcClient, index_RpcDataStream as RpcDataStream, index_RpcStreamConfig as RpcStreamConfig, type index_ValidateFilterResult as ValidateFilterResult, index_createRpcClient as createRpcClient };
108
103
  }
109
104
 
110
- export { type BlockInfo as B, type FetchBlockRangeArgs as F, RpcStreamConfig as R, type ValidateFilterResult as V, type FetchBlockResult as a, type FetchBlockRangeResult as b, type FetchBlockByNumberArgs as c, type FetchBlockByNumberResult as d, type FetchCursorArgs as e, type FetchCursorRangeArgs as f, RpcClient as g, createRpcClient as h, index as i, RpcDataStream as j };
105
+ export { type BlockInfo as B, type FetchBlockRangeArgs as F, RpcStreamConfig as R, type ValidateFilterResult as V, type FetchBlockResult as a, type FetchBlockRangeResult as b, type FetchBlockByHashArgs as c, type FetchBlockByHashResult as d, type FetchCursorArgs as e, type FetchCursorRangeArgs as f, RpcClient as g, createRpcClient as h, index as i, RpcDataStream as j };
@@ -56,6 +56,9 @@ class ChainTracker {
56
56
  return blockInfoToCursor(__privateGet(this, _finalized));
57
57
  }
58
58
  updateFinalized(newFinalized) {
59
+ console.log(
60
+ `[CT] updateFinalized: new=${newFinalized.blockNumber} old=${__privateGet(this, _finalized).blockNumber}`
61
+ );
59
62
  if (newFinalized.blockNumber < __privateGet(this, _finalized).blockNumber) {
60
63
  throw new Error("Finalized cursor moved backwards");
61
64
  }
@@ -73,6 +76,7 @@ class ChainTracker {
73
76
  return true;
74
77
  }
75
78
  addToCanonicalChain({ blockInfo }) {
79
+ console.log(`[CT] addToCanonicalChain: block=${blockInfo.blockNumber}`);
76
80
  const existing = __privateGet(this, _canonical).get(blockInfo.blockNumber);
77
81
  if (existing) {
78
82
  if (existing.blockHash !== blockInfo.blockHash) {
@@ -96,6 +100,9 @@ class ChainTracker {
96
100
  fetchCursorByHash,
97
101
  fetchCursorRange
98
102
  }) {
103
+ console.log(
104
+ `[CT] updateHead: new=${newHead.blockNumber} old=${__privateGet(this, _head).blockNumber}`
105
+ );
99
106
  if (newHead.blockNumber === __privateGet(this, _head).blockNumber && newHead.blockHash === __privateGet(this, _head).blockHash) {
100
107
  return { status: "unchanged" };
101
108
  }
@@ -144,6 +151,9 @@ class ChainTracker {
144
151
  }
145
152
  throw new Error("Cannot reconcile new head with canonical chain.");
146
153
  }
154
+ console.log(
155
+ `[CT] moving from ${__privateGet(this, _head).blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - __privateGet(this, _head).blockNumber} blocks)`
156
+ );
147
157
  let currentBlockNumber = __privateGet(this, _head).blockNumber + 1n;
148
158
  while (true) {
149
159
  let endBlockNumber = currentBlockNumber + __privateGet(this, _batchSize);
@@ -304,6 +314,7 @@ class RpcDataStream {
304
314
  lastFinalizedRefresh: Date.now(),
305
315
  lastHeadRefresh: Date.now(),
306
316
  lastBackfillMessage: Date.now(),
317
+ lastEmptyBlockNumber: void 0,
307
318
  chainTracker,
308
319
  config: this.config,
309
320
  heartbeatIntervalMs: this.heartbeatIntervalMs,
@@ -334,6 +345,9 @@ async function* dataStreamLoop(state) {
334
345
  state.lastFinalizedRefresh = Date.now();
335
346
  }
336
347
  const finalized = chainTracker.finalized();
348
+ console.log(
349
+ `[DS] RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`
350
+ );
337
351
  if (cursor.orderKey < finalized.orderKey) {
338
352
  yield* backfillFinalizedBlocks(state);
339
353
  } else {
@@ -395,7 +409,7 @@ async function* produceLiveBlocks(state) {
395
409
  state.lastHeadRefresh = Date.now();
396
410
  if (result.status === "reorg") {
397
411
  const { cursor: cursor2 } = result;
398
- if (cursor2.orderKey < state.cursor.orderKey) {
412
+ if (cursor2.orderKey < state.cursor.orderKey || state.lastEmptyBlockNumber !== void 0 && cursor2.orderKey < state.lastEmptyBlockNumber) {
399
413
  state.cursor = cursor2;
400
414
  yield {
401
415
  _tag: "invalidate",
@@ -412,6 +426,26 @@ async function* produceLiveBlocks(state) {
412
426
  force: false,
413
427
  filter
414
428
  });
429
+ if (filterData.data.length === 0 && head.uniqueKey !== void 0) {
430
+ if (state.lastEmptyBlockNumber === void 0 || head.orderKey > state.lastEmptyBlockNumber) {
431
+ const { data } = await config.fetchBlockByHash({
432
+ blockHash: head.uniqueKey,
433
+ isAtHead: true,
434
+ filter
435
+ });
436
+ yield {
437
+ _tag: "data",
438
+ data: {
439
+ cursor: data.cursor,
440
+ endCursor: data.endCursor,
441
+ data: [data.block],
442
+ finality: "accepted",
443
+ production: "live"
444
+ }
445
+ };
446
+ state.lastEmptyBlockNumber = head.orderKey;
447
+ }
448
+ }
415
449
  for (const { cursor: cursor2, endCursor, block } of filterData.data) {
416
450
  if (!chainTracker.isCanonical(endCursor)) {
417
451
  throw new Error("Trying to process non-canonical block");
@@ -563,4 +597,4 @@ exports.RpcDataStream = RpcDataStream;
563
597
  exports.RpcStreamConfig = RpcStreamConfig;
564
598
  exports.createRpcClient = createRpcClient;
565
599
  exports.index = index;
566
- //# sourceMappingURL=protocol.27cb7b14.cjs.map
600
+ //# sourceMappingURL=protocol.6ea6c882.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.6ea6c882.cjs","sources":["../../src/rpc/config.ts","../../src/rpc/helpers.ts","../../src/rpc/chain-tracker.ts","../../src/rpc/data-stream.ts","../../src/rpc/client.ts"],"sourcesContent":["import type { Bytes, Cursor } from \"../common\";\n\nexport type FetchBlockRangeArgs<TFilter> = {\n startBlock: bigint;\n maxBlock: bigint;\n force: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockRangeResult<TBlock> = {\n startBlock: bigint;\n endBlock: bigint;\n data: FetchBlockResult<TBlock>[];\n};\n\nexport type FetchBlockResult<TBlock> = {\n block: TBlock | null;\n cursor: Cursor | undefined;\n endCursor: Cursor;\n};\n\nexport type BlockInfo = {\n blockNumber: bigint;\n blockHash: Bytes;\n parentBlockHash: Bytes;\n};\n\nexport type FetchBlockByHashArgs<TFilter> = {\n blockHash: Bytes;\n isAtHead: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockByHashResult<TBlock> = {\n data: FetchBlockResult<TBlock>;\n blockInfo: BlockInfo;\n};\n\nexport type FetchCursorRangeArgs = {\n startBlockNumber: bigint;\n endBlockNumber: bigint;\n};\n\nexport type FetchCursorArgs =\n | {\n blockTag: \"latest\" | \"finalized\";\n blockNumber?: undefined;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber: bigint;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber?: undefined;\n blockHash: Bytes;\n };\n\nexport type ValidateFilterResult =\n | {\n valid: true;\n error?: undefined;\n }\n | {\n valid: false;\n error: string;\n };\n\nexport abstract class RpcStreamConfig<TFilter, TBlock> {\n abstract headRefreshIntervalMs(): number;\n abstract finalizedRefreshIntervalMs(): number;\n\n abstract fetchCursorRange(args: FetchCursorRangeArgs): Promise<BlockInfo[]>;\n abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;\n\n abstract validateFilter(filter: TFilter): ValidateFilterResult;\n\n abstract fetchBlockRange(\n args: FetchBlockRangeArgs<TFilter>,\n ): Promise<FetchBlockRangeResult<TBlock>>;\n\n abstract fetchBlockByHash(\n args: FetchBlockByHashArgs<TFilter>,\n ): Promise<FetchBlockByHashResult<TBlock>>;\n}\n","import type { Cursor } from \"../common\";\nimport type { BlockInfo } from \"./config\";\n\nexport function blockInfoToCursor(blockInfo: BlockInfo): Cursor {\n return {\n orderKey: blockInfo.blockNumber,\n uniqueKey: blockInfo.blockHash,\n };\n}\n","import { fromHex } from \"viem\";\nimport type { Bytes, Cursor } from \"../common\";\nimport type { BlockInfo, FetchCursorRangeArgs } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\ntype UpdateHeadArgs = {\n newHead: BlockInfo;\n fetchCursorByHash: (hash: Bytes) => Promise<BlockInfo | null>;\n fetchCursorRange: (args: FetchCursorRangeArgs) => Promise<BlockInfo[]>;\n};\n\ntype UpdateHeadResult =\n | {\n status: \"unchanged\";\n }\n | {\n status: \"success\";\n }\n | {\n status: \"reorg\";\n cursor: Cursor;\n };\n\nexport class ChainTracker {\n #finalized: BlockInfo;\n #head: BlockInfo;\n #canonical: Map<bigint, BlockInfo>;\n #batchSize: bigint;\n\n constructor({\n head,\n finalized,\n batchSize,\n }: {\n finalized: BlockInfo;\n head: BlockInfo;\n batchSize: bigint;\n }) {\n this.#finalized = finalized;\n this.#head = head;\n this.#batchSize = batchSize;\n\n this.#canonical = new Map([\n [finalized.blockNumber, finalized],\n [head.blockNumber, head],\n ]);\n }\n\n head(): Cursor {\n return blockInfoToCursor(this.#head);\n }\n\n finalized(): Cursor {\n return blockInfoToCursor(this.#finalized);\n }\n\n updateFinalized(newFinalized: BlockInfo) {\n console.log(\n `[CT] updateFinalized: new=${newFinalized.blockNumber} old=${this.#finalized.blockNumber}`,\n );\n\n if (newFinalized.blockNumber < this.#finalized.blockNumber) {\n throw new Error(\"Finalized cursor moved backwards\");\n }\n\n if (newFinalized.blockNumber === this.#finalized.blockNumber) {\n if (newFinalized.blockHash !== this.#finalized.blockHash) {\n throw new Error(\"Received a different finalized cursor\");\n }\n\n return false;\n }\n\n // Delete all blocks that are now finalized.\n for (\n let bn = this.#finalized.blockNumber;\n bn < newFinalized.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n this.#canonical.set(newFinalized.blockNumber, newFinalized);\n this.#finalized = newFinalized;\n\n return true;\n }\n\n addToCanonicalChain({ blockInfo }: { blockInfo: BlockInfo }) {\n console.log(`[CT] addToCanonicalChain: block=${blockInfo.blockNumber}`);\n\n const existing = this.#canonical.get(blockInfo.blockNumber);\n\n if (existing) {\n if (existing.blockHash !== blockInfo.blockHash) {\n throw new Error(\n `Block already exists in canonical chain: previous ${existing.blockHash}, new ${blockInfo.blockHash}`,\n );\n }\n }\n\n const parent = this.#canonical.get(blockInfo.blockNumber - 1n);\n if (!parent) {\n throw new Error(\"Parent block not in canonical chain\");\n }\n\n if (parent.blockHash !== blockInfo.parentBlockHash) {\n throw new Error(\"Parent block hash mismatch.\");\n }\n\n this.#canonical.set(blockInfo.blockNumber, blockInfo);\n\n // console.log(\"Canon updated: \", canonical);\n\n return { status: \"success\" };\n }\n\n async updateHead({\n newHead,\n fetchCursorByHash,\n fetchCursorRange,\n }: UpdateHeadArgs): Promise<UpdateHeadResult> {\n console.log(\n `[CT] updateHead: new=${newHead.blockNumber} old=${this.#head.blockNumber}`,\n );\n\n // No changes to the chain.\n if (\n newHead.blockNumber === this.#head.blockNumber &&\n newHead.blockHash === this.#head.blockHash\n ) {\n return { status: \"unchanged\" };\n }\n\n // Most common case: the new head is the block after the current head.\n if (\n newHead.blockNumber === this.#head.blockNumber + 1n &&\n newHead.parentBlockHash === this.#head.blockHash\n ) {\n this.#canonical.set(newHead.blockNumber, newHead);\n this.#head = newHead;\n return { status: \"success\" };\n }\n\n // The new chain is not longer.\n if (newHead.blockNumber <= this.#head.blockNumber) {\n // console.log(\"head=\", this.#head, \"newhead=\", newHead);\n let currentNewHead = newHead;\n // Delete all blocks from canonical chain after the new head.\n for (\n let bn = newHead.blockNumber + 1n;\n bn <= this.#head.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n // Check if the chain was simply shrunk to this block.\n const existing = this.#canonical.get(currentNewHead.blockNumber);\n if (existing && existing.blockHash === currentNewHead.blockHash) {\n this.#head = existing;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(existing),\n };\n }\n\n while (currentNewHead.blockNumber > this.#finalized.blockNumber) {\n this.#canonical.delete(currentNewHead.blockNumber);\n\n const canonicalParent = this.#canonical.get(\n currentNewHead.blockNumber - 1n,\n );\n\n if (!canonicalParent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: missing parent in canonical chain\",\n );\n }\n\n // We found the common ancestor.\n if (canonicalParent.blockHash === currentNewHead.parentBlockHash) {\n this.#head = canonicalParent;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(canonicalParent),\n };\n }\n\n const parent = await fetchCursorByHash(currentNewHead.parentBlockHash);\n\n if (!parent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: failed to fetch parent\",\n );\n }\n\n currentNewHead = parent;\n }\n\n throw new Error(\"Cannot reconcile new head with canonical chain.\");\n }\n\n // In all other cases we need to \"join\" the new head with the existing chain.\n // The new chain is longer and we need the missing blocks.\n // This may result in reorgs.\n\n console.log(\n `[CT] moving from ${this.#head.blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - this.#head.blockNumber} blocks)`,\n );\n\n let currentBlockNumber = this.#head.blockNumber + 1n;\n\n while (true) {\n let endBlockNumber = currentBlockNumber + this.#batchSize;\n if (endBlockNumber > newHead.blockNumber) {\n endBlockNumber = newHead.blockNumber;\n }\n\n const missing = await fetchCursorRange({\n startBlockNumber: currentBlockNumber,\n endBlockNumber,\n });\n\n for (const block of missing) {\n const canonicalParent = this.#canonical.get(block.blockNumber - 1n);\n if (\n !canonicalParent ||\n canonicalParent.blockHash !== block.parentBlockHash\n ) {\n throw new Error(\n \"Chain reorganization detected. Recovery not implemented\",\n );\n }\n\n this.#canonical.set(block.blockNumber, block);\n }\n\n if (endBlockNumber === newHead.blockNumber) {\n break;\n }\n\n currentBlockNumber = endBlockNumber + 1n;\n }\n\n this.#head = newHead;\n\n return { status: \"success\" };\n }\n\n isCanonical({ orderKey, uniqueKey }: Cursor) {\n if (!uniqueKey) {\n return true;\n }\n\n const block = this.#canonical.get(orderKey);\n if (!block) {\n return true;\n }\n\n return block.blockHash === uniqueKey;\n }\n\n async initializeStartingCursor({\n cursor,\n fetchCursor,\n }: {\n cursor: Cursor;\n fetchCursor: (blockNumber: bigint) => Promise<BlockInfo | null>;\n }): Promise<\n | { canonical: true; reason?: undefined; fullCursor: Cursor }\n | { canonical: false; reason: string; fullCursor?: undefined }\n > {\n const head = this.head();\n const finalized = this.finalized();\n\n if (cursor.orderKey > head.orderKey) {\n return { canonical: false, reason: \"cursor is ahead of head\" };\n }\n\n const expectedInfo = await fetchCursor(cursor.orderKey);\n if (!cursor.uniqueKey) {\n if (expectedInfo === null) {\n throw new Error(\"Failed to initialize canonical cursor\");\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: blockInfoToCursor(expectedInfo) };\n }\n\n if (expectedInfo === null) {\n return {\n canonical: false,\n reason: \"expected block does not exist\",\n };\n }\n\n const expectedCursor = blockInfoToCursor(expectedInfo);\n\n // These two checks are redundant, but they are kept to avoid issues with bad config implementations.\n if (!expectedCursor.uniqueKey) {\n return {\n canonical: false,\n reason: \"expected cursor has no unique key (hash)\",\n };\n }\n\n if (expectedCursor.orderKey !== cursor.orderKey) {\n return {\n canonical: false,\n reason: \"cursor order key does not match expected order key\",\n };\n }\n\n if (\n fromHex(expectedCursor.uniqueKey, \"bigint\") !==\n fromHex(cursor.uniqueKey, \"bigint\")\n ) {\n return {\n canonical: false,\n reason: `cursor hash does not match expected hash: ${cursor.uniqueKey} !== ${expectedCursor.uniqueKey}`,\n };\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: expectedCursor };\n }\n}\n\nexport function createChainTracker({\n head,\n finalized,\n batchSize,\n}: {\n head: BlockInfo;\n finalized: BlockInfo;\n batchSize: bigint;\n}): ChainTracker {\n return new ChainTracker({ finalized, head, batchSize });\n}\n","import type { StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport { type ChainTracker, createChainTracker } from \"./chain-tracker\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\n\ntype State<TFilter, TBlock> = {\n // The network-specific config.\n config: RpcStreamConfig<TFilter, TBlock>;\n // The current cursor, that is the last block that was filtered.\n cursor: Cursor;\n // When the finalized block was last refreshed.\n lastFinalizedRefresh: number;\n // When the head was last refreshed.\n lastHeadRefresh: number;\n // When the last heartbeat was sent.\n lastHeartbeat: number;\n // When the last backfill message was sent.\n lastBackfillMessage: number;\n // The last empty header sent.\n lastEmptyBlockNumber: bigint | undefined;\n // Track the chain's state.\n chainTracker: ChainTracker;\n // Heartbeat interval in milliseconds.\n heartbeatIntervalMs: number;\n // The request filter.\n filter: TFilter;\n // The request options.\n options?: StreamDataOptions;\n};\n\nexport class RpcDataStream<TFilter, TBlock> {\n private heartbeatIntervalMs: number;\n\n constructor(\n private config: RpcStreamConfig<TFilter, TBlock>,\n private request: StreamDataRequest<TFilter>,\n private options?: StreamDataOptions,\n ) {\n this.heartbeatIntervalMs = request.heartbeatInterval\n ? Number(request.heartbeatInterval.seconds) * 1000\n : DEFAULT_HEARTBEAT_INTERVAL_MS;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamDataResponse<TBlock>> {\n const startingState = await this.initialize();\n yield* dataStreamLoop(startingState);\n }\n\n private async initialize(): Promise<State<TFilter, TBlock>> {\n if (this.request.filter.length === 0) {\n throw new Error(\"Request.filter: empty.\");\n }\n\n if (this.request.filter.length > 1) {\n throw new Error(\"Request.filter: only one filter is supported.\");\n }\n\n const [head, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n if (finalized === null) {\n throw new Error(\"EvmRpcStream requires a finalized block\");\n }\n\n if (head === null) {\n throw new Error(\"EvmRpcStream requires a chain with blocks.\");\n }\n\n const chainTracker = createChainTracker({\n head,\n finalized,\n batchSize: 20n,\n });\n\n let cursor: Cursor;\n if (this.request.startingCursor) {\n cursor = this.request.startingCursor;\n\n const { canonical, reason, fullCursor } =\n await chainTracker.initializeStartingCursor({\n cursor,\n fetchCursor: (blockNumber) =>\n this.config.fetchCursor({ blockNumber }),\n });\n\n if (!canonical) {\n throw new Error(`Starting cursor is not canonical: ${reason}`);\n }\n\n cursor = fullCursor;\n } else {\n cursor = { orderKey: -1n };\n }\n\n return {\n cursor,\n lastHeartbeat: Date.now(),\n lastFinalizedRefresh: Date.now(),\n lastHeadRefresh: Date.now(),\n lastBackfillMessage: Date.now(),\n lastEmptyBlockNumber: undefined,\n chainTracker,\n config: this.config,\n heartbeatIntervalMs: this.heartbeatIntervalMs,\n filter: this.request.filter[0],\n options: this.options,\n };\n }\n}\n\nasync function* dataStreamLoop<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n while (shouldContinue(state)) {\n const { cursor, chainTracker } = state;\n\n // Always check for heartbeats first to ensure we don't miss any.\n if (shouldSendHeartbeat(state)) {\n state.lastHeartbeat = Date.now();\n yield { _tag: \"heartbeat\" };\n }\n\n if (shouldRefreshFinalized(state)) {\n const finalizedInfo = await state.config.fetchCursor({\n blockTag: \"finalized\",\n });\n\n if (finalizedInfo === null) {\n throw new Error(\"Failed to fetch finalized cursor\");\n }\n\n const finalized = blockInfoToCursor(finalizedInfo);\n const finalizedChanged =\n state.chainTracker.updateFinalized(finalizedInfo);\n\n // Only send finalized if it's needed.\n if (finalizedChanged && state.cursor.orderKey > finalized.orderKey) {\n yield { _tag: \"finalize\", finalize: { cursor: finalized } };\n }\n\n state.lastFinalizedRefresh = Date.now();\n }\n\n const finalized = chainTracker.finalized();\n\n console.log(\n `[DS] RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`,\n );\n\n if (cursor.orderKey < finalized.orderKey) {\n yield* backfillFinalizedBlocks(state);\n } else {\n // If we're at the head, wait for a change.\n //\n // We don't want to produce a block immediately, but re-run the loop so\n // that it's like any other iteration.\n if (isAtHead(state)) {\n yield* waitForHeadChange(state);\n } else {\n yield* produceLiveBlocks(state);\n }\n }\n }\n}\n\nasync function* backfillFinalizedBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { cursor, chainTracker, config, filter } = state;\n const finalized = chainTracker.finalized();\n\n // While backfilling we want to regularly send some blocks (even if empty) so\n // that the client can store the cursor.\n const force = shouldForceBackfill(state);\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: finalized.orderKey,\n force,\n filter,\n });\n\n if (filterData.endBlock > finalized.orderKey) {\n throw new Error(\n \"Network-specific stream returned invalid data, crossing the finalized block.\",\n );\n }\n\n for (const data of filterData.data) {\n state.lastHeartbeat = Date.now();\n state.lastBackfillMessage = Date.now();\n yield {\n _tag: \"data\",\n data: {\n cursor: data.cursor,\n endCursor: data.endCursor,\n data: [data.block],\n finality: \"finalized\",\n production: \"backfill\",\n },\n };\n }\n\n // Notice that we check that filteredData.endBlock <= finalized.orderKey above.\n if (filterData.endBlock === finalized.orderKey) {\n // Prepare for transition to non-finalized data.\n state.cursor = finalized;\n } else {\n state.cursor = { orderKey: filterData.endBlock };\n }\n}\n\n// This is a generator to possibly produce data for live blocks.\n//\n// It's a generator because it's not guaranteed to produce data for the next block.\nasync function* produceLiveBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { config, cursor, chainTracker, filter } = state;\n\n if (shouldRefreshHead(state)) {\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n state.lastHeadRefresh = Date.now();\n\n if (result.status === \"reorg\") {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (\n cursor.orderKey < state.cursor.orderKey ||\n (state.lastEmptyBlockNumber !== undefined &&\n cursor.orderKey < state.lastEmptyBlockNumber)\n ) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n\n return;\n }\n }\n }\n\n const head = chainTracker.head();\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: head.orderKey,\n force: false,\n filter,\n });\n\n if (filterData.data.length === 0 && head.uniqueKey !== undefined) {\n // Send an empty block if we reached the head, but don't update the cursor.\n if (\n state.lastEmptyBlockNumber === undefined ||\n head.orderKey > state.lastEmptyBlockNumber\n ) {\n const { data } = await config.fetchBlockByHash({\n blockHash: head.uniqueKey,\n isAtHead: true,\n filter,\n });\n\n yield {\n _tag: \"data\",\n data: {\n cursor: data.cursor,\n endCursor: data.endCursor,\n data: [data.block],\n finality: \"accepted\",\n production: \"live\",\n },\n };\n\n state.lastEmptyBlockNumber = head.orderKey;\n }\n }\n\n for (const { cursor, endCursor, block } of filterData.data) {\n if (!chainTracker.isCanonical(endCursor)) {\n throw new Error(\"Trying to process non-canonical block\");\n }\n\n if (block !== null) {\n state.lastHeartbeat = Date.now();\n const production = isAtHead(state) ? \"live\" : \"backfill\";\n\n yield {\n _tag: \"data\",\n data: {\n cursor,\n endCursor,\n data: [block],\n finality: \"accepted\",\n production,\n },\n };\n }\n\n state.cursor = {\n orderKey: endCursor.orderKey,\n uniqueKey: endCursor.uniqueKey,\n };\n }\n}\n\nasync function* waitForHeadChange<TBlock>(\n state: State<unknown, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { chainTracker, config } = state;\n\n const heartbeatDeadline = state.lastHeartbeat + state.heartbeatIntervalMs;\n const finalizedRefreshDeadline =\n state.lastFinalizedRefresh + config.finalizedRefreshIntervalMs();\n\n while (true) {\n const now = Date.now();\n // Allow the outer loop to send the heartbeat message or refresh finalized blocks.\n if (now >= heartbeatDeadline || now >= finalizedRefreshDeadline) {\n return;\n }\n\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n switch (result.status) {\n case \"unchanged\": {\n const heartbeatTimeout = heartbeatDeadline - now;\n const finalizedTimeout = finalizedRefreshDeadline - now;\n\n // Wait until whatever happens next.\n await sleep(\n Math.min(\n heartbeatTimeout,\n finalizedTimeout,\n config.headRefreshIntervalMs(),\n ),\n );\n\n break;\n }\n case \"reorg\": {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (cursor.orderKey < state.cursor.orderKey) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n }\n\n break;\n }\n case \"success\": {\n // Chain grew without any issues. Go back to the top-level loop to produce data.\n return;\n }\n }\n }\n}\n\nfunction shouldSendHeartbeat(state: State<unknown, unknown>): boolean {\n const { heartbeatIntervalMs, lastHeartbeat } = state;\n const now = Date.now();\n return now - lastHeartbeat >= heartbeatIntervalMs;\n}\n\nfunction shouldForceBackfill(state: State<unknown, unknown>): boolean {\n const { lastBackfillMessage, heartbeatIntervalMs } = state;\n const now = Date.now();\n return now - lastBackfillMessage >= heartbeatIntervalMs;\n}\n\nfunction shouldContinue(state: State<unknown, unknown>): boolean {\n const { endingCursor } = state.options || {};\n if (endingCursor === undefined) return true;\n\n return state.cursor.orderKey < endingCursor.orderKey;\n}\n\nfunction shouldRefreshFinalized(state: State<unknown, unknown>): boolean {\n const { lastFinalizedRefresh, config } = state;\n const now = Date.now();\n return now - lastFinalizedRefresh >= config.finalizedRefreshIntervalMs();\n}\n\nfunction shouldRefreshHead(state: State<unknown, unknown>): boolean {\n const { lastHeadRefresh, config } = state;\n const now = Date.now();\n return now - lastHeadRefresh >= config.headRefreshIntervalMs();\n}\n\nfunction isAtHead(state: State<unknown, unknown>): boolean {\n const head = state.chainTracker.head();\n return state.cursor.orderKey === head.orderKey;\n}\n\nfunction sleep(duration: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, duration));\n}\n","import type { Client, ClientCallOptions, StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StatusRequest, StatusResponse } from \"../status\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { RpcDataStream } from \"./data-stream\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nexport class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {\n constructor(private config: RpcStreamConfig<TFilter, TBlock>) {}\n\n async status(\n _request?: StatusRequest,\n _options?: ClientCallOptions,\n ): Promise<StatusResponse> {\n const [currentHead, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n const starting: Cursor = { orderKey: 0n };\n\n return {\n currentHead: currentHead ? blockInfoToCursor(currentHead) : undefined,\n lastIngested: currentHead ? blockInfoToCursor(currentHead) : undefined,\n finalized: finalized ? blockInfoToCursor(finalized) : undefined,\n starting,\n };\n }\n\n streamData(\n request: StreamDataRequest<TFilter>,\n options?: StreamDataOptions,\n ): AsyncIterable<StreamDataResponse<TBlock>> {\n const index = 0;\n for (const filter of request.filter) {\n const { valid, error } = this.config.validateFilter(filter);\n if (!valid) {\n throw new Error(`Filter at position ${index} is invalid: ${error}`);\n }\n }\n\n return new RpcDataStream(this.config, request, options);\n }\n}\n\nexport function createRpcClient<TFilter, TBlock>(\n config: RpcStreamConfig<TFilter, TBlock>,\n): RpcClient<TFilter, TBlock> {\n return new RpcClient(config);\n}\n"],"names":["fromHex","finalized","cursor"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apibara/protocol",
3
- "version": "2.1.0-beta.53",
3
+ "version": "2.1.0-beta.55",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -55,9 +55,9 @@ export class ChainTracker {
55
55
  }
56
56
 
57
57
  updateFinalized(newFinalized: BlockInfo) {
58
- // console.debug(
59
- // `updateFinalized: new=${newFinalized.blockNumber} old=${this.#finalized.blockNumber}`,
60
- // );
58
+ console.log(
59
+ `[CT] updateFinalized: new=${newFinalized.blockNumber} old=${this.#finalized.blockNumber}`,
60
+ );
61
61
 
62
62
  if (newFinalized.blockNumber < this.#finalized.blockNumber) {
63
63
  throw new Error("Finalized cursor moved backwards");
@@ -87,7 +87,7 @@ export class ChainTracker {
87
87
  }
88
88
 
89
89
  addToCanonicalChain({ blockInfo }: { blockInfo: BlockInfo }) {
90
- // console.debug(`addToCanonicalChain: block=${blockInfo.blockNumber}`);
90
+ console.log(`[CT] addToCanonicalChain: block=${blockInfo.blockNumber}`);
91
91
 
92
92
  const existing = this.#canonical.get(blockInfo.blockNumber);
93
93
 
@@ -120,9 +120,9 @@ export class ChainTracker {
120
120
  fetchCursorByHash,
121
121
  fetchCursorRange,
122
122
  }: UpdateHeadArgs): Promise<UpdateHeadResult> {
123
- // console.debug(
124
- // `updateHead: new=${newHead.blockNumber} old=${this.#head.blockNumber}`,
125
- // );
123
+ console.log(
124
+ `[CT] updateHead: new=${newHead.blockNumber} old=${this.#head.blockNumber}`,
125
+ );
126
126
 
127
127
  // No changes to the chain.
128
128
  if (
@@ -205,9 +205,9 @@ export class ChainTracker {
205
205
  // The new chain is longer and we need the missing blocks.
206
206
  // This may result in reorgs.
207
207
 
208
- // console.log(
209
- // `Moving from ${this.#head.blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - this.#head.blockNumber} blocks)`,
210
- // );
208
+ console.log(
209
+ `[CT] moving from ${this.#head.blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - this.#head.blockNumber} blocks)`,
210
+ );
211
211
 
212
212
  let currentBlockNumber = this.#head.blockNumber + 1n;
213
213
 
@@ -234,8 +234,6 @@ export class ChainTracker {
234
234
  }
235
235
 
236
236
  this.#canonical.set(block.blockNumber, block);
237
-
238
- // console.log(`Applied block ${block.blockNumber}`);
239
237
  }
240
238
 
241
239
  if (endBlockNumber === newHead.blockNumber) {
@@ -245,54 +243,8 @@ export class ChainTracker {
245
243
  currentBlockNumber = endBlockNumber + 1n;
246
244
  }
247
245
 
248
- /*
249
- while (true) {
250
- const parent = await fetchCursorByHash(current.parentBlockHash);
251
-
252
- if (!parent) {
253
- throw new Error(
254
- "Cannot reconcile new head with canonical chain: failed to fetch parent",
255
- );
256
- }
257
-
258
- if (parent.blockNumber === this.#head.blockNumber) {
259
- if (parent.blockHash === this.#head.blockHash) {
260
- break;
261
- }
262
-
263
- const headParent = this.#canonical.get(this.#head.blockNumber - 1n);
264
- if (!headParent) {
265
- throw new Error(
266
- "Cannot reconcile new head with canonical chain: missing parent in canonical chain",
267
- );
268
- }
269
-
270
- // Update current head.
271
- this.#canonical.delete(this.#head.blockNumber);
272
- this.#head = headParent;
273
- reorgDetected = true;
274
- }
275
-
276
- blocksToApply.push(parent);
277
- current = parent;
278
- }
279
- */
280
- // throw new Error("FUCK IT");
281
-
282
- // for (const block of blocksToApply.reverse()) {
283
- // this.#canonical.set(block.blockNumber, block);
284
- // }
285
-
286
- // const previousHead = this.#head;
287
246
  this.#head = newHead;
288
247
 
289
- // if (reorgDetected) {
290
- // return {
291
- // status: "reorg",
292
- // cursor: blockInfoToCursor(previousHead),
293
- // };
294
- // }
295
-
296
248
  return { status: "success" };
297
249
  }
298
250
 
package/src/rpc/config.ts CHANGED
@@ -25,23 +25,16 @@ export type BlockInfo = {
25
25
  parentBlockHash: Bytes;
26
26
  };
27
27
 
28
- export type FetchBlockByNumberArgs<TFilter> = {
29
- blockNumber: bigint;
30
- expectedParentBlockHash: Bytes;
28
+ export type FetchBlockByHashArgs<TFilter> = {
29
+ blockHash: Bytes;
31
30
  isAtHead: boolean;
32
31
  filter: TFilter;
33
32
  };
34
33
 
35
- export type FetchBlockByNumberResult<TBlock> =
36
- | {
37
- status: "success";
38
- data: FetchBlockResult<TBlock>;
39
- blockInfo: BlockInfo;
40
- }
41
- | {
42
- status: "reorg";
43
- blockInfo: BlockInfo;
44
- };
34
+ export type FetchBlockByHashResult<TBlock> = {
35
+ data: FetchBlockResult<TBlock>;
36
+ blockInfo: BlockInfo;
37
+ };
45
38
 
46
39
  export type FetchCursorRangeArgs = {
47
40
  startBlockNumber: bigint;
@@ -88,7 +81,7 @@ export abstract class RpcStreamConfig<TFilter, TBlock> {
88
81
  args: FetchBlockRangeArgs<TFilter>,
89
82
  ): Promise<FetchBlockRangeResult<TBlock>>;
90
83
 
91
- abstract fetchBlockByNumber(
92
- args: FetchBlockByNumberArgs<TFilter>,
93
- ): Promise<FetchBlockByNumberResult<TBlock>>;
84
+ abstract fetchBlockByHash(
85
+ args: FetchBlockByHashArgs<TFilter>,
86
+ ): Promise<FetchBlockByHashResult<TBlock>>;
94
87
  }
@@ -20,6 +20,8 @@ type State<TFilter, TBlock> = {
20
20
  lastHeartbeat: number;
21
21
  // When the last backfill message was sent.
22
22
  lastBackfillMessage: number;
23
+ // The last empty header sent.
24
+ lastEmptyBlockNumber: bigint | undefined;
23
25
  // Track the chain's state.
24
26
  chainTracker: ChainTracker;
25
27
  // Heartbeat interval in milliseconds.
@@ -102,6 +104,7 @@ export class RpcDataStream<TFilter, TBlock> {
102
104
  lastFinalizedRefresh: Date.now(),
103
105
  lastHeadRefresh: Date.now(),
104
106
  lastBackfillMessage: Date.now(),
107
+ lastEmptyBlockNumber: undefined,
105
108
  chainTracker,
106
109
  config: this.config,
107
110
  heartbeatIntervalMs: this.heartbeatIntervalMs,
@@ -146,9 +149,9 @@ async function* dataStreamLoop<TFilter, TBlock>(
146
149
 
147
150
  const finalized = chainTracker.finalized();
148
151
 
149
- // console.debug(
150
- // `RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`,
151
- // );
152
+ console.log(
153
+ `[DS] RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`,
154
+ );
152
155
 
153
156
  if (cursor.orderKey < finalized.orderKey) {
154
157
  yield* backfillFinalizedBlocks(state);
@@ -238,7 +241,11 @@ async function* produceLiveBlocks<TFilter, TBlock>(
238
241
  if (result.status === "reorg") {
239
242
  const { cursor } = result;
240
243
  // Only handle reorgs if they involve blocks already processed.
241
- if (cursor.orderKey < state.cursor.orderKey) {
244
+ if (
245
+ cursor.orderKey < state.cursor.orderKey ||
246
+ (state.lastEmptyBlockNumber !== undefined &&
247
+ cursor.orderKey < state.lastEmptyBlockNumber)
248
+ ) {
242
249
  state.cursor = cursor;
243
250
 
244
251
  yield {
@@ -260,6 +267,33 @@ async function* produceLiveBlocks<TFilter, TBlock>(
260
267
  filter,
261
268
  });
262
269
 
270
+ if (filterData.data.length === 0 && head.uniqueKey !== undefined) {
271
+ // Send an empty block if we reached the head, but don't update the cursor.
272
+ if (
273
+ state.lastEmptyBlockNumber === undefined ||
274
+ head.orderKey > state.lastEmptyBlockNumber
275
+ ) {
276
+ const { data } = await config.fetchBlockByHash({
277
+ blockHash: head.uniqueKey,
278
+ isAtHead: true,
279
+ filter,
280
+ });
281
+
282
+ yield {
283
+ _tag: "data",
284
+ data: {
285
+ cursor: data.cursor,
286
+ endCursor: data.endCursor,
287
+ data: [data.block],
288
+ finality: "accepted",
289
+ production: "live",
290
+ },
291
+ };
292
+
293
+ state.lastEmptyBlockNumber = head.orderKey;
294
+ }
295
+ }
296
+
263
297
  for (const { cursor, endCursor, block } of filterData.data) {
264
298
  if (!chainTracker.isCanonical(endCursor)) {
265
299
  throw new Error("Trying to process non-canonical block");
package/src/rpc/index.ts CHANGED
@@ -3,8 +3,8 @@ export {
3
3
  type FetchBlockRangeArgs,
4
4
  type FetchBlockResult,
5
5
  type FetchBlockRangeResult,
6
- type FetchBlockByNumberArgs,
7
- type FetchBlockByNumberResult,
6
+ type FetchBlockByHashArgs,
7
+ type FetchBlockByHashResult,
8
8
  type ValidateFilterResult,
9
9
  type FetchCursorArgs,
10
10
  type FetchCursorRangeArgs,
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.05fab89c.mjs","sources":["../../src/rpc/config.ts","../../src/rpc/helpers.ts","../../src/rpc/chain-tracker.ts","../../src/rpc/data-stream.ts","../../src/rpc/client.ts"],"sourcesContent":["import type { Bytes, Cursor } from \"../common\";\n\nexport type FetchBlockRangeArgs<TFilter> = {\n startBlock: bigint;\n maxBlock: bigint;\n force: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockRangeResult<TBlock> = {\n startBlock: bigint;\n endBlock: bigint;\n data: FetchBlockResult<TBlock>[];\n};\n\nexport type FetchBlockResult<TBlock> = {\n block: TBlock | null;\n cursor: Cursor | undefined;\n endCursor: Cursor;\n};\n\nexport type BlockInfo = {\n blockNumber: bigint;\n blockHash: Bytes;\n parentBlockHash: Bytes;\n};\n\nexport type FetchBlockByNumberArgs<TFilter> = {\n blockNumber: bigint;\n expectedParentBlockHash: Bytes;\n isAtHead: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockByNumberResult<TBlock> =\n | {\n status: \"success\";\n data: FetchBlockResult<TBlock>;\n blockInfo: BlockInfo;\n }\n | {\n status: \"reorg\";\n blockInfo: BlockInfo;\n };\n\nexport type FetchCursorRangeArgs = {\n startBlockNumber: bigint;\n endBlockNumber: bigint;\n};\n\nexport type FetchCursorArgs =\n | {\n blockTag: \"latest\" | \"finalized\";\n blockNumber?: undefined;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber: bigint;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber?: undefined;\n blockHash: Bytes;\n };\n\nexport type ValidateFilterResult =\n | {\n valid: true;\n error?: undefined;\n }\n | {\n valid: false;\n error: string;\n };\n\nexport abstract class RpcStreamConfig<TFilter, TBlock> {\n abstract headRefreshIntervalMs(): number;\n abstract finalizedRefreshIntervalMs(): number;\n\n abstract fetchCursorRange(args: FetchCursorRangeArgs): Promise<BlockInfo[]>;\n abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;\n\n abstract validateFilter(filter: TFilter): ValidateFilterResult;\n\n abstract fetchBlockRange(\n args: FetchBlockRangeArgs<TFilter>,\n ): Promise<FetchBlockRangeResult<TBlock>>;\n\n abstract fetchBlockByNumber(\n args: FetchBlockByNumberArgs<TFilter>,\n ): Promise<FetchBlockByNumberResult<TBlock>>;\n}\n","import type { Cursor } from \"../common\";\nimport type { BlockInfo } from \"./config\";\n\nexport function blockInfoToCursor(blockInfo: BlockInfo): Cursor {\n return {\n orderKey: blockInfo.blockNumber,\n uniqueKey: blockInfo.blockHash,\n };\n}\n","import { fromHex } from \"viem\";\nimport type { Bytes, Cursor } from \"../common\";\nimport type { BlockInfo, FetchCursorRangeArgs } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\ntype UpdateHeadArgs = {\n newHead: BlockInfo;\n fetchCursorByHash: (hash: Bytes) => Promise<BlockInfo | null>;\n fetchCursorRange: (args: FetchCursorRangeArgs) => Promise<BlockInfo[]>;\n};\n\ntype UpdateHeadResult =\n | {\n status: \"unchanged\";\n }\n | {\n status: \"success\";\n }\n | {\n status: \"reorg\";\n cursor: Cursor;\n };\n\nexport class ChainTracker {\n #finalized: BlockInfo;\n #head: BlockInfo;\n #canonical: Map<bigint, BlockInfo>;\n #batchSize: bigint;\n\n constructor({\n head,\n finalized,\n batchSize,\n }: {\n finalized: BlockInfo;\n head: BlockInfo;\n batchSize: bigint;\n }) {\n this.#finalized = finalized;\n this.#head = head;\n this.#batchSize = batchSize;\n\n this.#canonical = new Map([\n [finalized.blockNumber, finalized],\n [head.blockNumber, head],\n ]);\n }\n\n head(): Cursor {\n return blockInfoToCursor(this.#head);\n }\n\n finalized(): Cursor {\n return blockInfoToCursor(this.#finalized);\n }\n\n updateFinalized(newFinalized: BlockInfo) {\n // console.debug(\n // `updateFinalized: new=${newFinalized.blockNumber} old=${this.#finalized.blockNumber}`,\n // );\n\n if (newFinalized.blockNumber < this.#finalized.blockNumber) {\n throw new Error(\"Finalized cursor moved backwards\");\n }\n\n if (newFinalized.blockNumber === this.#finalized.blockNumber) {\n if (newFinalized.blockHash !== this.#finalized.blockHash) {\n throw new Error(\"Received a different finalized cursor\");\n }\n\n return false;\n }\n\n // Delete all blocks that are now finalized.\n for (\n let bn = this.#finalized.blockNumber;\n bn < newFinalized.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n this.#canonical.set(newFinalized.blockNumber, newFinalized);\n this.#finalized = newFinalized;\n\n return true;\n }\n\n addToCanonicalChain({ blockInfo }: { blockInfo: BlockInfo }) {\n // console.debug(`addToCanonicalChain: block=${blockInfo.blockNumber}`);\n\n const existing = this.#canonical.get(blockInfo.blockNumber);\n\n if (existing) {\n if (existing.blockHash !== blockInfo.blockHash) {\n throw new Error(\n `Block already exists in canonical chain: previous ${existing.blockHash}, new ${blockInfo.blockHash}`,\n );\n }\n }\n\n const parent = this.#canonical.get(blockInfo.blockNumber - 1n);\n if (!parent) {\n throw new Error(\"Parent block not in canonical chain\");\n }\n\n if (parent.blockHash !== blockInfo.parentBlockHash) {\n throw new Error(\"Parent block hash mismatch.\");\n }\n\n this.#canonical.set(blockInfo.blockNumber, blockInfo);\n\n // console.log(\"Canon updated: \", canonical);\n\n return { status: \"success\" };\n }\n\n async updateHead({\n newHead,\n fetchCursorByHash,\n fetchCursorRange,\n }: UpdateHeadArgs): Promise<UpdateHeadResult> {\n // console.debug(\n // `updateHead: new=${newHead.blockNumber} old=${this.#head.blockNumber}`,\n // );\n\n // No changes to the chain.\n if (\n newHead.blockNumber === this.#head.blockNumber &&\n newHead.blockHash === this.#head.blockHash\n ) {\n return { status: \"unchanged\" };\n }\n\n // Most common case: the new head is the block after the current head.\n if (\n newHead.blockNumber === this.#head.blockNumber + 1n &&\n newHead.parentBlockHash === this.#head.blockHash\n ) {\n this.#canonical.set(newHead.blockNumber, newHead);\n this.#head = newHead;\n return { status: \"success\" };\n }\n\n // The new chain is not longer.\n if (newHead.blockNumber <= this.#head.blockNumber) {\n // console.log(\"head=\", this.#head, \"newhead=\", newHead);\n let currentNewHead = newHead;\n // Delete all blocks from canonical chain after the new head.\n for (\n let bn = newHead.blockNumber + 1n;\n bn <= this.#head.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n // Check if the chain was simply shrunk to this block.\n const existing = this.#canonical.get(currentNewHead.blockNumber);\n if (existing && existing.blockHash === currentNewHead.blockHash) {\n this.#head = existing;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(existing),\n };\n }\n\n while (currentNewHead.blockNumber > this.#finalized.blockNumber) {\n this.#canonical.delete(currentNewHead.blockNumber);\n\n const canonicalParent = this.#canonical.get(\n currentNewHead.blockNumber - 1n,\n );\n\n if (!canonicalParent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: missing parent in canonical chain\",\n );\n }\n\n // We found the common ancestor.\n if (canonicalParent.blockHash === currentNewHead.parentBlockHash) {\n this.#head = canonicalParent;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(canonicalParent),\n };\n }\n\n const parent = await fetchCursorByHash(currentNewHead.parentBlockHash);\n\n if (!parent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: failed to fetch parent\",\n );\n }\n\n currentNewHead = parent;\n }\n\n throw new Error(\"Cannot reconcile new head with canonical chain.\");\n }\n\n // In all other cases we need to \"join\" the new head with the existing chain.\n // The new chain is longer and we need the missing blocks.\n // This may result in reorgs.\n\n // console.log(\n // `Moving from ${this.#head.blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - this.#head.blockNumber} blocks)`,\n // );\n\n let currentBlockNumber = this.#head.blockNumber + 1n;\n\n while (true) {\n let endBlockNumber = currentBlockNumber + this.#batchSize;\n if (endBlockNumber > newHead.blockNumber) {\n endBlockNumber = newHead.blockNumber;\n }\n\n const missing = await fetchCursorRange({\n startBlockNumber: currentBlockNumber,\n endBlockNumber,\n });\n\n for (const block of missing) {\n const canonicalParent = this.#canonical.get(block.blockNumber - 1n);\n if (\n !canonicalParent ||\n canonicalParent.blockHash !== block.parentBlockHash\n ) {\n throw new Error(\n \"Chain reorganization detected. Recovery not implemented\",\n );\n }\n\n this.#canonical.set(block.blockNumber, block);\n\n // console.log(`Applied block ${block.blockNumber}`);\n }\n\n if (endBlockNumber === newHead.blockNumber) {\n break;\n }\n\n currentBlockNumber = endBlockNumber + 1n;\n }\n\n /*\n while (true) {\n const parent = await fetchCursorByHash(current.parentBlockHash);\n\n if (!parent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: failed to fetch parent\",\n );\n }\n\n if (parent.blockNumber === this.#head.blockNumber) {\n if (parent.blockHash === this.#head.blockHash) {\n break;\n }\n\n const headParent = this.#canonical.get(this.#head.blockNumber - 1n);\n if (!headParent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: missing parent in canonical chain\",\n );\n }\n\n // Update current head.\n this.#canonical.delete(this.#head.blockNumber);\n this.#head = headParent;\n reorgDetected = true;\n }\n\n blocksToApply.push(parent);\n current = parent;\n }\n */\n // throw new Error(\"FUCK IT\");\n\n // for (const block of blocksToApply.reverse()) {\n // this.#canonical.set(block.blockNumber, block);\n // }\n\n // const previousHead = this.#head;\n this.#head = newHead;\n\n // if (reorgDetected) {\n // return {\n // status: \"reorg\",\n // cursor: blockInfoToCursor(previousHead),\n // };\n // }\n\n return { status: \"success\" };\n }\n\n isCanonical({ orderKey, uniqueKey }: Cursor) {\n if (!uniqueKey) {\n return true;\n }\n\n const block = this.#canonical.get(orderKey);\n if (!block) {\n return true;\n }\n\n return block.blockHash === uniqueKey;\n }\n\n async initializeStartingCursor({\n cursor,\n fetchCursor,\n }: {\n cursor: Cursor;\n fetchCursor: (blockNumber: bigint) => Promise<BlockInfo | null>;\n }): Promise<\n | { canonical: true; reason?: undefined; fullCursor: Cursor }\n | { canonical: false; reason: string; fullCursor?: undefined }\n > {\n const head = this.head();\n const finalized = this.finalized();\n\n if (cursor.orderKey > head.orderKey) {\n return { canonical: false, reason: \"cursor is ahead of head\" };\n }\n\n const expectedInfo = await fetchCursor(cursor.orderKey);\n if (!cursor.uniqueKey) {\n if (expectedInfo === null) {\n throw new Error(\"Failed to initialize canonical cursor\");\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: blockInfoToCursor(expectedInfo) };\n }\n\n if (expectedInfo === null) {\n return {\n canonical: false,\n reason: \"expected block does not exist\",\n };\n }\n\n const expectedCursor = blockInfoToCursor(expectedInfo);\n\n // These two checks are redundant, but they are kept to avoid issues with bad config implementations.\n if (!expectedCursor.uniqueKey) {\n return {\n canonical: false,\n reason: \"expected cursor has no unique key (hash)\",\n };\n }\n\n if (expectedCursor.orderKey !== cursor.orderKey) {\n return {\n canonical: false,\n reason: \"cursor order key does not match expected order key\",\n };\n }\n\n if (\n fromHex(expectedCursor.uniqueKey, \"bigint\") !==\n fromHex(cursor.uniqueKey, \"bigint\")\n ) {\n return {\n canonical: false,\n reason: `cursor hash does not match expected hash: ${cursor.uniqueKey} !== ${expectedCursor.uniqueKey}`,\n };\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: expectedCursor };\n }\n}\n\nexport function createChainTracker({\n head,\n finalized,\n batchSize,\n}: {\n head: BlockInfo;\n finalized: BlockInfo;\n batchSize: bigint;\n}): ChainTracker {\n return new ChainTracker({ finalized, head, batchSize });\n}\n","import type { StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport { type ChainTracker, createChainTracker } from \"./chain-tracker\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\n\ntype State<TFilter, TBlock> = {\n // The network-specific config.\n config: RpcStreamConfig<TFilter, TBlock>;\n // The current cursor, that is the last block that was filtered.\n cursor: Cursor;\n // When the finalized block was last refreshed.\n lastFinalizedRefresh: number;\n // When the head was last refreshed.\n lastHeadRefresh: number;\n // When the last heartbeat was sent.\n lastHeartbeat: number;\n // When the last backfill message was sent.\n lastBackfillMessage: number;\n // Track the chain's state.\n chainTracker: ChainTracker;\n // Heartbeat interval in milliseconds.\n heartbeatIntervalMs: number;\n // The request filter.\n filter: TFilter;\n // The request options.\n options?: StreamDataOptions;\n};\n\nexport class RpcDataStream<TFilter, TBlock> {\n private heartbeatIntervalMs: number;\n\n constructor(\n private config: RpcStreamConfig<TFilter, TBlock>,\n private request: StreamDataRequest<TFilter>,\n private options?: StreamDataOptions,\n ) {\n this.heartbeatIntervalMs = request.heartbeatInterval\n ? Number(request.heartbeatInterval.seconds) * 1000\n : DEFAULT_HEARTBEAT_INTERVAL_MS;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamDataResponse<TBlock>> {\n const startingState = await this.initialize();\n yield* dataStreamLoop(startingState);\n }\n\n private async initialize(): Promise<State<TFilter, TBlock>> {\n if (this.request.filter.length === 0) {\n throw new Error(\"Request.filter: empty.\");\n }\n\n if (this.request.filter.length > 1) {\n throw new Error(\"Request.filter: only one filter is supported.\");\n }\n\n const [head, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n if (finalized === null) {\n throw new Error(\"EvmRpcStream requires a finalized block\");\n }\n\n if (head === null) {\n throw new Error(\"EvmRpcStream requires a chain with blocks.\");\n }\n\n const chainTracker = createChainTracker({\n head,\n finalized,\n batchSize: 20n,\n });\n\n let cursor: Cursor;\n if (this.request.startingCursor) {\n cursor = this.request.startingCursor;\n\n const { canonical, reason, fullCursor } =\n await chainTracker.initializeStartingCursor({\n cursor,\n fetchCursor: (blockNumber) =>\n this.config.fetchCursor({ blockNumber }),\n });\n\n if (!canonical) {\n throw new Error(`Starting cursor is not canonical: ${reason}`);\n }\n\n cursor = fullCursor;\n } else {\n cursor = { orderKey: -1n };\n }\n\n return {\n cursor,\n lastHeartbeat: Date.now(),\n lastFinalizedRefresh: Date.now(),\n lastHeadRefresh: Date.now(),\n lastBackfillMessage: Date.now(),\n chainTracker,\n config: this.config,\n heartbeatIntervalMs: this.heartbeatIntervalMs,\n filter: this.request.filter[0],\n options: this.options,\n };\n }\n}\n\nasync function* dataStreamLoop<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n while (shouldContinue(state)) {\n const { cursor, chainTracker } = state;\n\n // Always check for heartbeats first to ensure we don't miss any.\n if (shouldSendHeartbeat(state)) {\n state.lastHeartbeat = Date.now();\n yield { _tag: \"heartbeat\" };\n }\n\n if (shouldRefreshFinalized(state)) {\n const finalizedInfo = await state.config.fetchCursor({\n blockTag: \"finalized\",\n });\n\n if (finalizedInfo === null) {\n throw new Error(\"Failed to fetch finalized cursor\");\n }\n\n const finalized = blockInfoToCursor(finalizedInfo);\n const finalizedChanged =\n state.chainTracker.updateFinalized(finalizedInfo);\n\n // Only send finalized if it's needed.\n if (finalizedChanged && state.cursor.orderKey > finalized.orderKey) {\n yield { _tag: \"finalize\", finalize: { cursor: finalized } };\n }\n\n state.lastFinalizedRefresh = Date.now();\n }\n\n const finalized = chainTracker.finalized();\n\n // console.debug(\n // `RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`,\n // );\n\n if (cursor.orderKey < finalized.orderKey) {\n yield* backfillFinalizedBlocks(state);\n } else {\n // If we're at the head, wait for a change.\n //\n // We don't want to produce a block immediately, but re-run the loop so\n // that it's like any other iteration.\n if (isAtHead(state)) {\n yield* waitForHeadChange(state);\n } else {\n yield* produceLiveBlocks(state);\n }\n }\n }\n}\n\nasync function* backfillFinalizedBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { cursor, chainTracker, config, filter } = state;\n const finalized = chainTracker.finalized();\n\n // While backfilling we want to regularly send some blocks (even if empty) so\n // that the client can store the cursor.\n const force = shouldForceBackfill(state);\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: finalized.orderKey,\n force,\n filter,\n });\n\n if (filterData.endBlock > finalized.orderKey) {\n throw new Error(\n \"Network-specific stream returned invalid data, crossing the finalized block.\",\n );\n }\n\n for (const data of filterData.data) {\n state.lastHeartbeat = Date.now();\n state.lastBackfillMessage = Date.now();\n yield {\n _tag: \"data\",\n data: {\n cursor: data.cursor,\n endCursor: data.endCursor,\n data: [data.block],\n finality: \"finalized\",\n production: \"backfill\",\n },\n };\n }\n\n // Notice that we check that filteredData.endBlock <= finalized.orderKey above.\n if (filterData.endBlock === finalized.orderKey) {\n // Prepare for transition to non-finalized data.\n state.cursor = finalized;\n } else {\n state.cursor = { orderKey: filterData.endBlock };\n }\n}\n\n// This is a generator to possibly produce data for live blocks.\n//\n// It's a generator because it's not guaranteed to produce data for the next block.\nasync function* produceLiveBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { config, cursor, chainTracker, filter } = state;\n\n if (shouldRefreshHead(state)) {\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n state.lastHeadRefresh = Date.now();\n\n if (result.status === \"reorg\") {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (cursor.orderKey < state.cursor.orderKey) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n\n return;\n }\n }\n }\n\n const head = chainTracker.head();\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: head.orderKey,\n force: false,\n filter,\n });\n\n for (const { cursor, endCursor, block } of filterData.data) {\n if (!chainTracker.isCanonical(endCursor)) {\n throw new Error(\"Trying to process non-canonical block\");\n }\n\n if (block !== null) {\n state.lastHeartbeat = Date.now();\n const production = isAtHead(state) ? \"live\" : \"backfill\";\n\n yield {\n _tag: \"data\",\n data: {\n cursor,\n endCursor,\n data: [block],\n finality: \"accepted\",\n production,\n },\n };\n }\n\n state.cursor = {\n orderKey: endCursor.orderKey,\n uniqueKey: endCursor.uniqueKey,\n };\n }\n}\n\nasync function* waitForHeadChange<TBlock>(\n state: State<unknown, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { chainTracker, config } = state;\n\n const heartbeatDeadline = state.lastHeartbeat + state.heartbeatIntervalMs;\n const finalizedRefreshDeadline =\n state.lastFinalizedRefresh + config.finalizedRefreshIntervalMs();\n\n while (true) {\n const now = Date.now();\n // Allow the outer loop to send the heartbeat message or refresh finalized blocks.\n if (now >= heartbeatDeadline || now >= finalizedRefreshDeadline) {\n return;\n }\n\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n switch (result.status) {\n case \"unchanged\": {\n const heartbeatTimeout = heartbeatDeadline - now;\n const finalizedTimeout = finalizedRefreshDeadline - now;\n\n // Wait until whatever happens next.\n await sleep(\n Math.min(\n heartbeatTimeout,\n finalizedTimeout,\n config.headRefreshIntervalMs(),\n ),\n );\n\n break;\n }\n case \"reorg\": {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (cursor.orderKey < state.cursor.orderKey) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n }\n\n break;\n }\n case \"success\": {\n // Chain grew without any issues. Go back to the top-level loop to produce data.\n return;\n }\n }\n }\n}\n\nfunction shouldSendHeartbeat(state: State<unknown, unknown>): boolean {\n const { heartbeatIntervalMs, lastHeartbeat } = state;\n const now = Date.now();\n return now - lastHeartbeat >= heartbeatIntervalMs;\n}\n\nfunction shouldForceBackfill(state: State<unknown, unknown>): boolean {\n const { lastBackfillMessage, heartbeatIntervalMs } = state;\n const now = Date.now();\n return now - lastBackfillMessage >= heartbeatIntervalMs;\n}\n\nfunction shouldContinue(state: State<unknown, unknown>): boolean {\n const { endingCursor } = state.options || {};\n if (endingCursor === undefined) return true;\n\n return state.cursor.orderKey < endingCursor.orderKey;\n}\n\nfunction shouldRefreshFinalized(state: State<unknown, unknown>): boolean {\n const { lastFinalizedRefresh, config } = state;\n const now = Date.now();\n return now - lastFinalizedRefresh >= config.finalizedRefreshIntervalMs();\n}\n\nfunction shouldRefreshHead(state: State<unknown, unknown>): boolean {\n const { lastHeadRefresh, config } = state;\n const now = Date.now();\n return now - lastHeadRefresh >= config.headRefreshIntervalMs();\n}\n\nfunction isAtHead(state: State<unknown, unknown>): boolean {\n const head = state.chainTracker.head();\n return state.cursor.orderKey === head.orderKey;\n}\n\nfunction sleep(duration: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, duration));\n}\n","import type { Client, ClientCallOptions, StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StatusRequest, StatusResponse } from \"../status\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { RpcDataStream } from \"./data-stream\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nexport class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {\n constructor(private config: RpcStreamConfig<TFilter, TBlock>) {}\n\n async status(\n _request?: StatusRequest,\n _options?: ClientCallOptions,\n ): Promise<StatusResponse> {\n const [currentHead, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n const starting: Cursor = { orderKey: 0n };\n\n return {\n currentHead: currentHead ? blockInfoToCursor(currentHead) : undefined,\n lastIngested: currentHead ? blockInfoToCursor(currentHead) : undefined,\n finalized: finalized ? blockInfoToCursor(finalized) : undefined,\n starting,\n };\n }\n\n streamData(\n request: StreamDataRequest<TFilter>,\n options?: StreamDataOptions,\n ): AsyncIterable<StreamDataResponse<TBlock>> {\n const index = 0;\n for (const filter of request.filter) {\n const { valid, error } = this.config.validateFilter(filter);\n if (!valid) {\n throw new Error(`Filter at position ${index} is invalid: ${error}`);\n }\n }\n\n return new RpcDataStream(this.config, request, options);\n }\n}\n\nexport function createRpcClient<TFilter, TBlock>(\n config: RpcStreamConfig<TFilter, TBlock>,\n): RpcClient<TFilter, TBlock> {\n return new RpcClient(config);\n}\n"],"names":["finalized","cursor"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.27cb7b14.cjs","sources":["../../src/rpc/config.ts","../../src/rpc/helpers.ts","../../src/rpc/chain-tracker.ts","../../src/rpc/data-stream.ts","../../src/rpc/client.ts"],"sourcesContent":["import type { Bytes, Cursor } from \"../common\";\n\nexport type FetchBlockRangeArgs<TFilter> = {\n startBlock: bigint;\n maxBlock: bigint;\n force: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockRangeResult<TBlock> = {\n startBlock: bigint;\n endBlock: bigint;\n data: FetchBlockResult<TBlock>[];\n};\n\nexport type FetchBlockResult<TBlock> = {\n block: TBlock | null;\n cursor: Cursor | undefined;\n endCursor: Cursor;\n};\n\nexport type BlockInfo = {\n blockNumber: bigint;\n blockHash: Bytes;\n parentBlockHash: Bytes;\n};\n\nexport type FetchBlockByNumberArgs<TFilter> = {\n blockNumber: bigint;\n expectedParentBlockHash: Bytes;\n isAtHead: boolean;\n filter: TFilter;\n};\n\nexport type FetchBlockByNumberResult<TBlock> =\n | {\n status: \"success\";\n data: FetchBlockResult<TBlock>;\n blockInfo: BlockInfo;\n }\n | {\n status: \"reorg\";\n blockInfo: BlockInfo;\n };\n\nexport type FetchCursorRangeArgs = {\n startBlockNumber: bigint;\n endBlockNumber: bigint;\n};\n\nexport type FetchCursorArgs =\n | {\n blockTag: \"latest\" | \"finalized\";\n blockNumber?: undefined;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber: bigint;\n blockHash?: undefined;\n }\n | {\n blockTag?: undefined;\n blockNumber?: undefined;\n blockHash: Bytes;\n };\n\nexport type ValidateFilterResult =\n | {\n valid: true;\n error?: undefined;\n }\n | {\n valid: false;\n error: string;\n };\n\nexport abstract class RpcStreamConfig<TFilter, TBlock> {\n abstract headRefreshIntervalMs(): number;\n abstract finalizedRefreshIntervalMs(): number;\n\n abstract fetchCursorRange(args: FetchCursorRangeArgs): Promise<BlockInfo[]>;\n abstract fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;\n\n abstract validateFilter(filter: TFilter): ValidateFilterResult;\n\n abstract fetchBlockRange(\n args: FetchBlockRangeArgs<TFilter>,\n ): Promise<FetchBlockRangeResult<TBlock>>;\n\n abstract fetchBlockByNumber(\n args: FetchBlockByNumberArgs<TFilter>,\n ): Promise<FetchBlockByNumberResult<TBlock>>;\n}\n","import type { Cursor } from \"../common\";\nimport type { BlockInfo } from \"./config\";\n\nexport function blockInfoToCursor(blockInfo: BlockInfo): Cursor {\n return {\n orderKey: blockInfo.blockNumber,\n uniqueKey: blockInfo.blockHash,\n };\n}\n","import { fromHex } from \"viem\";\nimport type { Bytes, Cursor } from \"../common\";\nimport type { BlockInfo, FetchCursorRangeArgs } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\ntype UpdateHeadArgs = {\n newHead: BlockInfo;\n fetchCursorByHash: (hash: Bytes) => Promise<BlockInfo | null>;\n fetchCursorRange: (args: FetchCursorRangeArgs) => Promise<BlockInfo[]>;\n};\n\ntype UpdateHeadResult =\n | {\n status: \"unchanged\";\n }\n | {\n status: \"success\";\n }\n | {\n status: \"reorg\";\n cursor: Cursor;\n };\n\nexport class ChainTracker {\n #finalized: BlockInfo;\n #head: BlockInfo;\n #canonical: Map<bigint, BlockInfo>;\n #batchSize: bigint;\n\n constructor({\n head,\n finalized,\n batchSize,\n }: {\n finalized: BlockInfo;\n head: BlockInfo;\n batchSize: bigint;\n }) {\n this.#finalized = finalized;\n this.#head = head;\n this.#batchSize = batchSize;\n\n this.#canonical = new Map([\n [finalized.blockNumber, finalized],\n [head.blockNumber, head],\n ]);\n }\n\n head(): Cursor {\n return blockInfoToCursor(this.#head);\n }\n\n finalized(): Cursor {\n return blockInfoToCursor(this.#finalized);\n }\n\n updateFinalized(newFinalized: BlockInfo) {\n // console.debug(\n // `updateFinalized: new=${newFinalized.blockNumber} old=${this.#finalized.blockNumber}`,\n // );\n\n if (newFinalized.blockNumber < this.#finalized.blockNumber) {\n throw new Error(\"Finalized cursor moved backwards\");\n }\n\n if (newFinalized.blockNumber === this.#finalized.blockNumber) {\n if (newFinalized.blockHash !== this.#finalized.blockHash) {\n throw new Error(\"Received a different finalized cursor\");\n }\n\n return false;\n }\n\n // Delete all blocks that are now finalized.\n for (\n let bn = this.#finalized.blockNumber;\n bn < newFinalized.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n this.#canonical.set(newFinalized.blockNumber, newFinalized);\n this.#finalized = newFinalized;\n\n return true;\n }\n\n addToCanonicalChain({ blockInfo }: { blockInfo: BlockInfo }) {\n // console.debug(`addToCanonicalChain: block=${blockInfo.blockNumber}`);\n\n const existing = this.#canonical.get(blockInfo.blockNumber);\n\n if (existing) {\n if (existing.blockHash !== blockInfo.blockHash) {\n throw new Error(\n `Block already exists in canonical chain: previous ${existing.blockHash}, new ${blockInfo.blockHash}`,\n );\n }\n }\n\n const parent = this.#canonical.get(blockInfo.blockNumber - 1n);\n if (!parent) {\n throw new Error(\"Parent block not in canonical chain\");\n }\n\n if (parent.blockHash !== blockInfo.parentBlockHash) {\n throw new Error(\"Parent block hash mismatch.\");\n }\n\n this.#canonical.set(blockInfo.blockNumber, blockInfo);\n\n // console.log(\"Canon updated: \", canonical);\n\n return { status: \"success\" };\n }\n\n async updateHead({\n newHead,\n fetchCursorByHash,\n fetchCursorRange,\n }: UpdateHeadArgs): Promise<UpdateHeadResult> {\n // console.debug(\n // `updateHead: new=${newHead.blockNumber} old=${this.#head.blockNumber}`,\n // );\n\n // No changes to the chain.\n if (\n newHead.blockNumber === this.#head.blockNumber &&\n newHead.blockHash === this.#head.blockHash\n ) {\n return { status: \"unchanged\" };\n }\n\n // Most common case: the new head is the block after the current head.\n if (\n newHead.blockNumber === this.#head.blockNumber + 1n &&\n newHead.parentBlockHash === this.#head.blockHash\n ) {\n this.#canonical.set(newHead.blockNumber, newHead);\n this.#head = newHead;\n return { status: \"success\" };\n }\n\n // The new chain is not longer.\n if (newHead.blockNumber <= this.#head.blockNumber) {\n // console.log(\"head=\", this.#head, \"newhead=\", newHead);\n let currentNewHead = newHead;\n // Delete all blocks from canonical chain after the new head.\n for (\n let bn = newHead.blockNumber + 1n;\n bn <= this.#head.blockNumber;\n bn++\n ) {\n this.#canonical.delete(bn);\n }\n\n // Check if the chain was simply shrunk to this block.\n const existing = this.#canonical.get(currentNewHead.blockNumber);\n if (existing && existing.blockHash === currentNewHead.blockHash) {\n this.#head = existing;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(existing),\n };\n }\n\n while (currentNewHead.blockNumber > this.#finalized.blockNumber) {\n this.#canonical.delete(currentNewHead.blockNumber);\n\n const canonicalParent = this.#canonical.get(\n currentNewHead.blockNumber - 1n,\n );\n\n if (!canonicalParent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: missing parent in canonical chain\",\n );\n }\n\n // We found the common ancestor.\n if (canonicalParent.blockHash === currentNewHead.parentBlockHash) {\n this.#head = canonicalParent;\n return {\n status: \"reorg\",\n cursor: blockInfoToCursor(canonicalParent),\n };\n }\n\n const parent = await fetchCursorByHash(currentNewHead.parentBlockHash);\n\n if (!parent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: failed to fetch parent\",\n );\n }\n\n currentNewHead = parent;\n }\n\n throw new Error(\"Cannot reconcile new head with canonical chain.\");\n }\n\n // In all other cases we need to \"join\" the new head with the existing chain.\n // The new chain is longer and we need the missing blocks.\n // This may result in reorgs.\n\n // console.log(\n // `Moving from ${this.#head.blockNumber} to ${newHead.blockNumber} (${newHead.blockNumber - this.#head.blockNumber} blocks)`,\n // );\n\n let currentBlockNumber = this.#head.blockNumber + 1n;\n\n while (true) {\n let endBlockNumber = currentBlockNumber + this.#batchSize;\n if (endBlockNumber > newHead.blockNumber) {\n endBlockNumber = newHead.blockNumber;\n }\n\n const missing = await fetchCursorRange({\n startBlockNumber: currentBlockNumber,\n endBlockNumber,\n });\n\n for (const block of missing) {\n const canonicalParent = this.#canonical.get(block.blockNumber - 1n);\n if (\n !canonicalParent ||\n canonicalParent.blockHash !== block.parentBlockHash\n ) {\n throw new Error(\n \"Chain reorganization detected. Recovery not implemented\",\n );\n }\n\n this.#canonical.set(block.blockNumber, block);\n\n // console.log(`Applied block ${block.blockNumber}`);\n }\n\n if (endBlockNumber === newHead.blockNumber) {\n break;\n }\n\n currentBlockNumber = endBlockNumber + 1n;\n }\n\n /*\n while (true) {\n const parent = await fetchCursorByHash(current.parentBlockHash);\n\n if (!parent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: failed to fetch parent\",\n );\n }\n\n if (parent.blockNumber === this.#head.blockNumber) {\n if (parent.blockHash === this.#head.blockHash) {\n break;\n }\n\n const headParent = this.#canonical.get(this.#head.blockNumber - 1n);\n if (!headParent) {\n throw new Error(\n \"Cannot reconcile new head with canonical chain: missing parent in canonical chain\",\n );\n }\n\n // Update current head.\n this.#canonical.delete(this.#head.blockNumber);\n this.#head = headParent;\n reorgDetected = true;\n }\n\n blocksToApply.push(parent);\n current = parent;\n }\n */\n // throw new Error(\"FUCK IT\");\n\n // for (const block of blocksToApply.reverse()) {\n // this.#canonical.set(block.blockNumber, block);\n // }\n\n // const previousHead = this.#head;\n this.#head = newHead;\n\n // if (reorgDetected) {\n // return {\n // status: \"reorg\",\n // cursor: blockInfoToCursor(previousHead),\n // };\n // }\n\n return { status: \"success\" };\n }\n\n isCanonical({ orderKey, uniqueKey }: Cursor) {\n if (!uniqueKey) {\n return true;\n }\n\n const block = this.#canonical.get(orderKey);\n if (!block) {\n return true;\n }\n\n return block.blockHash === uniqueKey;\n }\n\n async initializeStartingCursor({\n cursor,\n fetchCursor,\n }: {\n cursor: Cursor;\n fetchCursor: (blockNumber: bigint) => Promise<BlockInfo | null>;\n }): Promise<\n | { canonical: true; reason?: undefined; fullCursor: Cursor }\n | { canonical: false; reason: string; fullCursor?: undefined }\n > {\n const head = this.head();\n const finalized = this.finalized();\n\n if (cursor.orderKey > head.orderKey) {\n return { canonical: false, reason: \"cursor is ahead of head\" };\n }\n\n const expectedInfo = await fetchCursor(cursor.orderKey);\n if (!cursor.uniqueKey) {\n if (expectedInfo === null) {\n throw new Error(\"Failed to initialize canonical cursor\");\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: blockInfoToCursor(expectedInfo) };\n }\n\n if (expectedInfo === null) {\n return {\n canonical: false,\n reason: \"expected block does not exist\",\n };\n }\n\n const expectedCursor = blockInfoToCursor(expectedInfo);\n\n // These two checks are redundant, but they are kept to avoid issues with bad config implementations.\n if (!expectedCursor.uniqueKey) {\n return {\n canonical: false,\n reason: \"expected cursor has no unique key (hash)\",\n };\n }\n\n if (expectedCursor.orderKey !== cursor.orderKey) {\n return {\n canonical: false,\n reason: \"cursor order key does not match expected order key\",\n };\n }\n\n if (\n fromHex(expectedCursor.uniqueKey, \"bigint\") !==\n fromHex(cursor.uniqueKey, \"bigint\")\n ) {\n return {\n canonical: false,\n reason: `cursor hash does not match expected hash: ${cursor.uniqueKey} !== ${expectedCursor.uniqueKey}`,\n };\n }\n\n if (expectedInfo.blockNumber > finalized.orderKey) {\n this.#canonical.set(expectedInfo.blockNumber, expectedInfo);\n }\n\n return { canonical: true, fullCursor: expectedCursor };\n }\n}\n\nexport function createChainTracker({\n head,\n finalized,\n batchSize,\n}: {\n head: BlockInfo;\n finalized: BlockInfo;\n batchSize: bigint;\n}): ChainTracker {\n return new ChainTracker({ finalized, head, batchSize });\n}\n","import type { StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport { type ChainTracker, createChainTracker } from \"./chain-tracker\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\n\ntype State<TFilter, TBlock> = {\n // The network-specific config.\n config: RpcStreamConfig<TFilter, TBlock>;\n // The current cursor, that is the last block that was filtered.\n cursor: Cursor;\n // When the finalized block was last refreshed.\n lastFinalizedRefresh: number;\n // When the head was last refreshed.\n lastHeadRefresh: number;\n // When the last heartbeat was sent.\n lastHeartbeat: number;\n // When the last backfill message was sent.\n lastBackfillMessage: number;\n // Track the chain's state.\n chainTracker: ChainTracker;\n // Heartbeat interval in milliseconds.\n heartbeatIntervalMs: number;\n // The request filter.\n filter: TFilter;\n // The request options.\n options?: StreamDataOptions;\n};\n\nexport class RpcDataStream<TFilter, TBlock> {\n private heartbeatIntervalMs: number;\n\n constructor(\n private config: RpcStreamConfig<TFilter, TBlock>,\n private request: StreamDataRequest<TFilter>,\n private options?: StreamDataOptions,\n ) {\n this.heartbeatIntervalMs = request.heartbeatInterval\n ? Number(request.heartbeatInterval.seconds) * 1000\n : DEFAULT_HEARTBEAT_INTERVAL_MS;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamDataResponse<TBlock>> {\n const startingState = await this.initialize();\n yield* dataStreamLoop(startingState);\n }\n\n private async initialize(): Promise<State<TFilter, TBlock>> {\n if (this.request.filter.length === 0) {\n throw new Error(\"Request.filter: empty.\");\n }\n\n if (this.request.filter.length > 1) {\n throw new Error(\"Request.filter: only one filter is supported.\");\n }\n\n const [head, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n if (finalized === null) {\n throw new Error(\"EvmRpcStream requires a finalized block\");\n }\n\n if (head === null) {\n throw new Error(\"EvmRpcStream requires a chain with blocks.\");\n }\n\n const chainTracker = createChainTracker({\n head,\n finalized,\n batchSize: 20n,\n });\n\n let cursor: Cursor;\n if (this.request.startingCursor) {\n cursor = this.request.startingCursor;\n\n const { canonical, reason, fullCursor } =\n await chainTracker.initializeStartingCursor({\n cursor,\n fetchCursor: (blockNumber) =>\n this.config.fetchCursor({ blockNumber }),\n });\n\n if (!canonical) {\n throw new Error(`Starting cursor is not canonical: ${reason}`);\n }\n\n cursor = fullCursor;\n } else {\n cursor = { orderKey: -1n };\n }\n\n return {\n cursor,\n lastHeartbeat: Date.now(),\n lastFinalizedRefresh: Date.now(),\n lastHeadRefresh: Date.now(),\n lastBackfillMessage: Date.now(),\n chainTracker,\n config: this.config,\n heartbeatIntervalMs: this.heartbeatIntervalMs,\n filter: this.request.filter[0],\n options: this.options,\n };\n }\n}\n\nasync function* dataStreamLoop<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n while (shouldContinue(state)) {\n const { cursor, chainTracker } = state;\n\n // Always check for heartbeats first to ensure we don't miss any.\n if (shouldSendHeartbeat(state)) {\n state.lastHeartbeat = Date.now();\n yield { _tag: \"heartbeat\" };\n }\n\n if (shouldRefreshFinalized(state)) {\n const finalizedInfo = await state.config.fetchCursor({\n blockTag: \"finalized\",\n });\n\n if (finalizedInfo === null) {\n throw new Error(\"Failed to fetch finalized cursor\");\n }\n\n const finalized = blockInfoToCursor(finalizedInfo);\n const finalizedChanged =\n state.chainTracker.updateFinalized(finalizedInfo);\n\n // Only send finalized if it's needed.\n if (finalizedChanged && state.cursor.orderKey > finalized.orderKey) {\n yield { _tag: \"finalize\", finalize: { cursor: finalized } };\n }\n\n state.lastFinalizedRefresh = Date.now();\n }\n\n const finalized = chainTracker.finalized();\n\n // console.debug(\n // `RpcLoop: c=${cursor.orderKey} f=${finalized.orderKey} h=${chainTracker.head().orderKey}`,\n // );\n\n if (cursor.orderKey < finalized.orderKey) {\n yield* backfillFinalizedBlocks(state);\n } else {\n // If we're at the head, wait for a change.\n //\n // We don't want to produce a block immediately, but re-run the loop so\n // that it's like any other iteration.\n if (isAtHead(state)) {\n yield* waitForHeadChange(state);\n } else {\n yield* produceLiveBlocks(state);\n }\n }\n }\n}\n\nasync function* backfillFinalizedBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { cursor, chainTracker, config, filter } = state;\n const finalized = chainTracker.finalized();\n\n // While backfilling we want to regularly send some blocks (even if empty) so\n // that the client can store the cursor.\n const force = shouldForceBackfill(state);\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: finalized.orderKey,\n force,\n filter,\n });\n\n if (filterData.endBlock > finalized.orderKey) {\n throw new Error(\n \"Network-specific stream returned invalid data, crossing the finalized block.\",\n );\n }\n\n for (const data of filterData.data) {\n state.lastHeartbeat = Date.now();\n state.lastBackfillMessage = Date.now();\n yield {\n _tag: \"data\",\n data: {\n cursor: data.cursor,\n endCursor: data.endCursor,\n data: [data.block],\n finality: \"finalized\",\n production: \"backfill\",\n },\n };\n }\n\n // Notice that we check that filteredData.endBlock <= finalized.orderKey above.\n if (filterData.endBlock === finalized.orderKey) {\n // Prepare for transition to non-finalized data.\n state.cursor = finalized;\n } else {\n state.cursor = { orderKey: filterData.endBlock };\n }\n}\n\n// This is a generator to possibly produce data for live blocks.\n//\n// It's a generator because it's not guaranteed to produce data for the next block.\nasync function* produceLiveBlocks<TFilter, TBlock>(\n state: State<TFilter, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { config, cursor, chainTracker, filter } = state;\n\n if (shouldRefreshHead(state)) {\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n state.lastHeadRefresh = Date.now();\n\n if (result.status === \"reorg\") {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (cursor.orderKey < state.cursor.orderKey) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n\n return;\n }\n }\n }\n\n const head = chainTracker.head();\n\n const filterData = await config.fetchBlockRange({\n startBlock: cursor.orderKey + 1n,\n maxBlock: head.orderKey,\n force: false,\n filter,\n });\n\n for (const { cursor, endCursor, block } of filterData.data) {\n if (!chainTracker.isCanonical(endCursor)) {\n throw new Error(\"Trying to process non-canonical block\");\n }\n\n if (block !== null) {\n state.lastHeartbeat = Date.now();\n const production = isAtHead(state) ? \"live\" : \"backfill\";\n\n yield {\n _tag: \"data\",\n data: {\n cursor,\n endCursor,\n data: [block],\n finality: \"accepted\",\n production,\n },\n };\n }\n\n state.cursor = {\n orderKey: endCursor.orderKey,\n uniqueKey: endCursor.uniqueKey,\n };\n }\n}\n\nasync function* waitForHeadChange<TBlock>(\n state: State<unknown, TBlock>,\n): AsyncGenerator<StreamDataResponse<TBlock>> {\n const { chainTracker, config } = state;\n\n const heartbeatDeadline = state.lastHeartbeat + state.heartbeatIntervalMs;\n const finalizedRefreshDeadline =\n state.lastFinalizedRefresh + config.finalizedRefreshIntervalMs();\n\n while (true) {\n const now = Date.now();\n // Allow the outer loop to send the heartbeat message or refresh finalized blocks.\n if (now >= heartbeatDeadline || now >= finalizedRefreshDeadline) {\n return;\n }\n\n const maybeNewHead = await config.fetchCursor({ blockTag: \"latest\" });\n\n if (maybeNewHead === null) {\n throw new Error(\"Failed to fetch the latest block\");\n }\n\n const result = await chainTracker.updateHead({\n newHead: maybeNewHead,\n fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),\n fetchCursorRange: (args) => config.fetchCursorRange(args),\n });\n\n switch (result.status) {\n case \"unchanged\": {\n const heartbeatTimeout = heartbeatDeadline - now;\n const finalizedTimeout = finalizedRefreshDeadline - now;\n\n // Wait until whatever happens next.\n await sleep(\n Math.min(\n heartbeatTimeout,\n finalizedTimeout,\n config.headRefreshIntervalMs(),\n ),\n );\n\n break;\n }\n case \"reorg\": {\n const { cursor } = result;\n // Only handle reorgs if they involve blocks already processed.\n if (cursor.orderKey < state.cursor.orderKey) {\n state.cursor = cursor;\n\n yield {\n _tag: \"invalidate\",\n invalidate: { cursor },\n };\n }\n\n break;\n }\n case \"success\": {\n // Chain grew without any issues. Go back to the top-level loop to produce data.\n return;\n }\n }\n }\n}\n\nfunction shouldSendHeartbeat(state: State<unknown, unknown>): boolean {\n const { heartbeatIntervalMs, lastHeartbeat } = state;\n const now = Date.now();\n return now - lastHeartbeat >= heartbeatIntervalMs;\n}\n\nfunction shouldForceBackfill(state: State<unknown, unknown>): boolean {\n const { lastBackfillMessage, heartbeatIntervalMs } = state;\n const now = Date.now();\n return now - lastBackfillMessage >= heartbeatIntervalMs;\n}\n\nfunction shouldContinue(state: State<unknown, unknown>): boolean {\n const { endingCursor } = state.options || {};\n if (endingCursor === undefined) return true;\n\n return state.cursor.orderKey < endingCursor.orderKey;\n}\n\nfunction shouldRefreshFinalized(state: State<unknown, unknown>): boolean {\n const { lastFinalizedRefresh, config } = state;\n const now = Date.now();\n return now - lastFinalizedRefresh >= config.finalizedRefreshIntervalMs();\n}\n\nfunction shouldRefreshHead(state: State<unknown, unknown>): boolean {\n const { lastHeadRefresh, config } = state;\n const now = Date.now();\n return now - lastHeadRefresh >= config.headRefreshIntervalMs();\n}\n\nfunction isAtHead(state: State<unknown, unknown>): boolean {\n const head = state.chainTracker.head();\n return state.cursor.orderKey === head.orderKey;\n}\n\nfunction sleep(duration: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, duration));\n}\n","import type { Client, ClientCallOptions, StreamDataOptions } from \"../client\";\nimport type { Cursor } from \"../common\";\nimport type { StatusRequest, StatusResponse } from \"../status\";\nimport type { StreamDataRequest, StreamDataResponse } from \"../stream\";\nimport type { RpcStreamConfig } from \"./config\";\nimport { RpcDataStream } from \"./data-stream\";\nimport { blockInfoToCursor } from \"./helpers\";\n\nexport class RpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {\n constructor(private config: RpcStreamConfig<TFilter, TBlock>) {}\n\n async status(\n _request?: StatusRequest,\n _options?: ClientCallOptions,\n ): Promise<StatusResponse> {\n const [currentHead, finalized] = await Promise.all([\n this.config.fetchCursor({ blockTag: \"latest\" }),\n this.config.fetchCursor({ blockTag: \"finalized\" }),\n ]);\n\n const starting: Cursor = { orderKey: 0n };\n\n return {\n currentHead: currentHead ? blockInfoToCursor(currentHead) : undefined,\n lastIngested: currentHead ? blockInfoToCursor(currentHead) : undefined,\n finalized: finalized ? blockInfoToCursor(finalized) : undefined,\n starting,\n };\n }\n\n streamData(\n request: StreamDataRequest<TFilter>,\n options?: StreamDataOptions,\n ): AsyncIterable<StreamDataResponse<TBlock>> {\n const index = 0;\n for (const filter of request.filter) {\n const { valid, error } = this.config.validateFilter(filter);\n if (!valid) {\n throw new Error(`Filter at position ${index} is invalid: ${error}`);\n }\n }\n\n return new RpcDataStream(this.config, request, options);\n }\n}\n\nexport function createRpcClient<TFilter, TBlock>(\n config: RpcStreamConfig<TFilter, TBlock>,\n): RpcClient<TFilter, TBlock> {\n return new RpcClient(config);\n}\n"],"names":["fromHex","finalized","cursor"],"mappings":"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"}