@apibara/protocol 2.1.0-beta.51 → 2.1.0-beta.53
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 +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/rpc/index.cjs +1 -1
- package/dist/rpc/index.d.cts +1 -1
- package/dist/rpc/index.d.mts +1 -1
- package/dist/rpc/index.d.ts +1 -1
- package/dist/rpc/index.mjs +1 -1
- package/dist/shared/{protocol.bde61588.mjs → protocol.05fab89c.mjs} +105 -75
- package/dist/shared/protocol.05fab89c.mjs.map +1 -0
- package/dist/shared/{protocol.54f17699.cjs → protocol.27cb7b14.cjs} +105 -75
- package/dist/shared/protocol.27cb7b14.cjs.map +1 -0
- package/dist/shared/{protocol.7aa4aab6.d.cts → protocol.d99fa7ff.d.cts} +9 -3
- package/dist/shared/{protocol.6ab8d6dd.d.mts → protocol.e53aa437.d.mts} +9 -3
- package/dist/shared/{protocol.8407f25e.d.ts → protocol.f900827e.d.ts} +9 -3
- package/package.json +2 -1
- package/src/rpc/chain-tracker.ts +83 -16
- package/src/rpc/config.ts +7 -1
- package/src/rpc/data-stream.ts +69 -40
- package/src/rpc/index.ts +1 -0
- package/dist/shared/protocol.54f17699.cjs.map +0 -1
- package/dist/shared/protocol.bde61588.mjs.map +0 -1
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.
|
|
9
|
+
const rpc_index = require('./shared/protocol.27cb7b14.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.
|
|
4
|
+
export { i as rpc } from './shared/protocol.d99fa7ff.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.
|
|
4
|
+
export { i as rpc } from './shared/protocol.e53aa437.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.
|
|
4
|
+
export { i as rpc } from './shared/protocol.f900827e.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.
|
|
9
|
+
export { i as rpc } from './shared/protocol.05fab89c.mjs';
|
|
10
10
|
import 'viem';
|
|
11
11
|
import 'long';
|
|
12
12
|
|
package/dist/rpc/index.cjs
CHANGED
package/dist/rpc/index.d.cts
CHANGED
|
@@ -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 RpcClient,
|
|
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';
|
|
2
2
|
import '../shared/protocol.0e734e33.cjs';
|
|
3
3
|
import '../codec.cjs';
|
|
4
4
|
import 'nice-grpc-common';
|
package/dist/rpc/index.d.mts
CHANGED
|
@@ -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 RpcClient,
|
|
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';
|
|
2
2
|
import '../shared/protocol.21e66b9e.mjs';
|
|
3
3
|
import '../codec.mjs';
|
|
4
4
|
import 'nice-grpc-common';
|
package/dist/rpc/index.d.ts
CHANGED
|
@@ -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 RpcClient,
|
|
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';
|
|
2
2
|
import '../shared/protocol.8fb09325.js';
|
|
3
3
|
import '../codec.js';
|
|
4
4
|
import 'nice-grpc-common';
|
package/dist/rpc/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { a as RpcClient, b as RpcDataStream, R as RpcStreamConfig, c as createRpcClient } from '../shared/protocol.
|
|
1
|
+
export { a as RpcClient, b as RpcDataStream, R as RpcStreamConfig, c as createRpcClient } from '../shared/protocol.05fab89c.mjs';
|
|
2
2
|
import 'viem';
|
|
3
3
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -28,14 +28,20 @@ var __privateSet = (obj, member, value, setter) => {
|
|
|
28
28
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
29
29
|
return value;
|
|
30
30
|
};
|
|
31
|
-
var _finalized, _head, _canonical;
|
|
31
|
+
var _finalized, _head, _canonical, _batchSize;
|
|
32
32
|
class ChainTracker {
|
|
33
|
-
constructor({
|
|
33
|
+
constructor({
|
|
34
|
+
head,
|
|
35
|
+
finalized,
|
|
36
|
+
batchSize
|
|
37
|
+
}) {
|
|
34
38
|
__privateAdd(this, _finalized, void 0);
|
|
35
39
|
__privateAdd(this, _head, void 0);
|
|
36
40
|
__privateAdd(this, _canonical, void 0);
|
|
41
|
+
__privateAdd(this, _batchSize, void 0);
|
|
37
42
|
__privateSet(this, _finalized, finalized);
|
|
38
43
|
__privateSet(this, _head, head);
|
|
44
|
+
__privateSet(this, _batchSize, batchSize);
|
|
39
45
|
__privateSet(this, _canonical, /* @__PURE__ */ new Map([
|
|
40
46
|
[finalized.blockNumber, finalized],
|
|
41
47
|
[head.blockNumber, head]
|
|
@@ -85,7 +91,8 @@ class ChainTracker {
|
|
|
85
91
|
}
|
|
86
92
|
async updateHead({
|
|
87
93
|
newHead,
|
|
88
|
-
fetchCursorByHash
|
|
94
|
+
fetchCursorByHash,
|
|
95
|
+
fetchCursorRange
|
|
89
96
|
}) {
|
|
90
97
|
if (newHead.blockNumber === __privateGet(this, _head).blockNumber && newHead.blockHash === __privateGet(this, _head).blockHash) {
|
|
91
98
|
return { status: "unchanged" };
|
|
@@ -135,46 +142,43 @@ class ChainTracker {
|
|
|
135
142
|
}
|
|
136
143
|
throw new Error("Cannot reconcile new head with canonical chain.");
|
|
137
144
|
}
|
|
138
|
-
let
|
|
139
|
-
let reorgDetected = false;
|
|
140
|
-
const blocksToApply = [newHead];
|
|
145
|
+
let currentBlockNumber = __privateGet(this, _head).blockNumber + 1n;
|
|
141
146
|
while (true) {
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
"Cannot reconcile new head with canonical chain: failed to fetch parent"
|
|
146
|
-
);
|
|
147
|
+
let endBlockNumber = currentBlockNumber + __privateGet(this, _batchSize);
|
|
148
|
+
if (endBlockNumber > newHead.blockNumber) {
|
|
149
|
+
endBlockNumber = newHead.blockNumber;
|
|
147
150
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
const missing = await fetchCursorRange({
|
|
152
|
+
startBlockNumber: currentBlockNumber,
|
|
153
|
+
endBlockNumber
|
|
154
|
+
});
|
|
155
|
+
for (const block of missing) {
|
|
156
|
+
const canonicalParent = __privateGet(this, _canonical).get(block.blockNumber - 1n);
|
|
157
|
+
if (!canonicalParent || canonicalParent.blockHash !== block.parentBlockHash) {
|
|
154
158
|
throw new Error(
|
|
155
|
-
"
|
|
159
|
+
"Chain reorganization detected. Recovery not implemented"
|
|
156
160
|
);
|
|
157
161
|
}
|
|
158
|
-
__privateGet(this, _canonical).
|
|
159
|
-
__privateSet(this, _head, headParent);
|
|
160
|
-
reorgDetected = true;
|
|
162
|
+
__privateGet(this, _canonical).set(block.blockNumber, block);
|
|
161
163
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
__privateGet(this, _canonical).set(block.blockNumber, block);
|
|
164
|
+
if (endBlockNumber === newHead.blockNumber) {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
currentBlockNumber = endBlockNumber + 1n;
|
|
167
168
|
}
|
|
168
|
-
const previousHead = __privateGet(this, _head);
|
|
169
169
|
__privateSet(this, _head, newHead);
|
|
170
|
-
if (reorgDetected) {
|
|
171
|
-
return {
|
|
172
|
-
status: "reorg",
|
|
173
|
-
cursor: blockInfoToCursor(previousHead)
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
170
|
return { status: "success" };
|
|
177
171
|
}
|
|
172
|
+
isCanonical({ orderKey, uniqueKey }) {
|
|
173
|
+
if (!uniqueKey) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
const block = __privateGet(this, _canonical).get(orderKey);
|
|
177
|
+
if (!block) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
return block.blockHash === uniqueKey;
|
|
181
|
+
}
|
|
178
182
|
async initializeStartingCursor({
|
|
179
183
|
cursor,
|
|
180
184
|
fetchCursor
|
|
@@ -228,11 +232,13 @@ class ChainTracker {
|
|
|
228
232
|
_finalized = new WeakMap();
|
|
229
233
|
_head = new WeakMap();
|
|
230
234
|
_canonical = new WeakMap();
|
|
235
|
+
_batchSize = new WeakMap();
|
|
231
236
|
function createChainTracker({
|
|
232
237
|
head,
|
|
233
|
-
finalized
|
|
238
|
+
finalized,
|
|
239
|
+
batchSize
|
|
234
240
|
}) {
|
|
235
|
-
return new ChainTracker({ finalized, head });
|
|
241
|
+
return new ChainTracker({ finalized, head, batchSize });
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
var __defProp = Object.defineProperty;
|
|
@@ -273,7 +279,8 @@ class RpcDataStream {
|
|
|
273
279
|
}
|
|
274
280
|
const chainTracker = createChainTracker({
|
|
275
281
|
head,
|
|
276
|
-
finalized
|
|
282
|
+
finalized,
|
|
283
|
+
batchSize: 20n
|
|
277
284
|
});
|
|
278
285
|
let cursor;
|
|
279
286
|
if (this.request.startingCursor) {
|
|
@@ -293,6 +300,7 @@ class RpcDataStream {
|
|
|
293
300
|
cursor,
|
|
294
301
|
lastHeartbeat: Date.now(),
|
|
295
302
|
lastFinalizedRefresh: Date.now(),
|
|
303
|
+
lastHeadRefresh: Date.now(),
|
|
296
304
|
lastBackfillMessage: Date.now(),
|
|
297
305
|
chainTracker,
|
|
298
306
|
config: this.config,
|
|
@@ -330,7 +338,7 @@ async function* dataStreamLoop(state) {
|
|
|
330
338
|
if (isAtHead(state)) {
|
|
331
339
|
yield* waitForHeadChange(state);
|
|
332
340
|
} else {
|
|
333
|
-
yield*
|
|
341
|
+
yield* produceLiveBlocks(state);
|
|
334
342
|
}
|
|
335
343
|
}
|
|
336
344
|
}
|
|
@@ -341,7 +349,7 @@ async function* backfillFinalizedBlocks(state) {
|
|
|
341
349
|
const force = shouldForceBackfill(state);
|
|
342
350
|
const filterData = await config.fetchBlockRange({
|
|
343
351
|
startBlock: cursor.orderKey + 1n,
|
|
344
|
-
|
|
352
|
+
maxBlock: finalized.orderKey,
|
|
345
353
|
force,
|
|
346
354
|
filter
|
|
347
355
|
});
|
|
@@ -370,43 +378,59 @@ async function* backfillFinalizedBlocks(state) {
|
|
|
370
378
|
state.cursor = { orderKey: filterData.endBlock };
|
|
371
379
|
}
|
|
372
380
|
}
|
|
373
|
-
async function*
|
|
374
|
-
const
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
381
|
+
async function* produceLiveBlocks(state) {
|
|
382
|
+
const { config, cursor, chainTracker, filter } = state;
|
|
383
|
+
if (shouldRefreshHead(state)) {
|
|
384
|
+
const maybeNewHead = await config.fetchCursor({ blockTag: "latest" });
|
|
385
|
+
if (maybeNewHead === null) {
|
|
386
|
+
throw new Error("Failed to fetch the latest block");
|
|
387
|
+
}
|
|
388
|
+
const result = await chainTracker.updateHead({
|
|
389
|
+
newHead: maybeNewHead,
|
|
390
|
+
fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),
|
|
391
|
+
fetchCursorRange: (args) => config.fetchCursorRange(args)
|
|
392
|
+
});
|
|
393
|
+
state.lastHeadRefresh = Date.now();
|
|
394
|
+
if (result.status === "reorg") {
|
|
395
|
+
const { cursor: cursor2 } = result;
|
|
396
|
+
if (cursor2.orderKey < state.cursor.orderKey) {
|
|
397
|
+
state.cursor = cursor2;
|
|
398
|
+
yield {
|
|
399
|
+
_tag: "invalidate",
|
|
400
|
+
invalidate: { cursor: cursor2 }
|
|
401
|
+
};
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
386
405
|
}
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
blockInfo
|
|
406
|
+
const head = chainTracker.head();
|
|
407
|
+
const filterData = await config.fetchBlockRange({
|
|
408
|
+
startBlock: cursor.orderKey + 1n,
|
|
409
|
+
maxBlock: head.orderKey,
|
|
410
|
+
force: false,
|
|
411
|
+
filter
|
|
394
412
|
});
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
413
|
+
for (const { cursor: cursor2, endCursor, block } of filterData.data) {
|
|
414
|
+
if (!chainTracker.isCanonical(endCursor)) {
|
|
415
|
+
throw new Error("Trying to process non-canonical block");
|
|
416
|
+
}
|
|
417
|
+
if (block !== null) {
|
|
418
|
+
state.lastHeartbeat = Date.now();
|
|
419
|
+
const production = isAtHead(state) ? "live" : "backfill";
|
|
420
|
+
yield {
|
|
421
|
+
_tag: "data",
|
|
422
|
+
data: {
|
|
423
|
+
cursor: cursor2,
|
|
424
|
+
endCursor,
|
|
425
|
+
data: [block],
|
|
426
|
+
finality: "accepted",
|
|
427
|
+
production
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
state.cursor = {
|
|
432
|
+
orderKey: endCursor.orderKey,
|
|
433
|
+
uniqueKey: endCursor.uniqueKey
|
|
410
434
|
};
|
|
411
435
|
}
|
|
412
436
|
}
|
|
@@ -425,7 +449,8 @@ async function* waitForHeadChange(state) {
|
|
|
425
449
|
}
|
|
426
450
|
const result = await chainTracker.updateHead({
|
|
427
451
|
newHead: maybeNewHead,
|
|
428
|
-
fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash })
|
|
452
|
+
fetchCursorByHash: (blockHash) => config.fetchCursor({ blockHash }),
|
|
453
|
+
fetchCursorRange: (args) => config.fetchCursorRange(args)
|
|
429
454
|
});
|
|
430
455
|
switch (result.status) {
|
|
431
456
|
case "unchanged": {
|
|
@@ -478,6 +503,11 @@ function shouldRefreshFinalized(state) {
|
|
|
478
503
|
const now = Date.now();
|
|
479
504
|
return now - lastFinalizedRefresh >= config.finalizedRefreshIntervalMs();
|
|
480
505
|
}
|
|
506
|
+
function shouldRefreshHead(state) {
|
|
507
|
+
const { lastHeadRefresh, config } = state;
|
|
508
|
+
const now = Date.now();
|
|
509
|
+
return now - lastHeadRefresh >= config.headRefreshIntervalMs();
|
|
510
|
+
}
|
|
481
511
|
function isAtHead(state) {
|
|
482
512
|
const head = state.chainTracker.head();
|
|
483
513
|
return state.cursor.orderKey === head.orderKey;
|
|
@@ -527,4 +557,4 @@ const index = {
|
|
|
527
557
|
};
|
|
528
558
|
|
|
529
559
|
export { RpcStreamConfig as R, RpcClient as a, RpcDataStream as b, createRpcClient as c, index as i };
|
|
530
|
-
//# sourceMappingURL=protocol.
|
|
560
|
+
//# sourceMappingURL=protocol.05fab89c.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|