@apibara/protocol 2.0.0-beta.9 → 2.1.0-beta.10

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.
@@ -135,6 +135,43 @@ function dataFinalityToJSON(object) {
135
135
  return "UNRECOGNIZED";
136
136
  }
137
137
  }
138
+ var DataProduction$1 = /* @__PURE__ */ ((DataProduction2) => {
139
+ DataProduction2[DataProduction2["UNKNOWN"] = 0] = "UNKNOWN";
140
+ DataProduction2[DataProduction2["BACKFILL"] = 1] = "BACKFILL";
141
+ DataProduction2[DataProduction2["LIVE"] = 2] = "LIVE";
142
+ DataProduction2[DataProduction2["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
143
+ return DataProduction2;
144
+ })(DataProduction$1 || {});
145
+ function dataProductionFromJSON(object) {
146
+ switch (object) {
147
+ case 0:
148
+ case "DATA_PRODUCTION_UNKNOWN":
149
+ return 0 /* UNKNOWN */;
150
+ case 1:
151
+ case "DATA_PRODUCTION_BACKFILL":
152
+ return 1 /* BACKFILL */;
153
+ case 2:
154
+ case "DATA_PRODUCTION_LIVE":
155
+ return 2 /* LIVE */;
156
+ case -1:
157
+ case "UNRECOGNIZED":
158
+ default:
159
+ return -1 /* UNRECOGNIZED */;
160
+ }
161
+ }
162
+ function dataProductionToJSON(object) {
163
+ switch (object) {
164
+ case 0 /* UNKNOWN */:
165
+ return "DATA_PRODUCTION_UNKNOWN";
166
+ case 1 /* BACKFILL */:
167
+ return "DATA_PRODUCTION_BACKFILL";
168
+ case 2 /* LIVE */:
169
+ return "DATA_PRODUCTION_LIVE";
170
+ case -1 /* UNRECOGNIZED */:
171
+ default:
172
+ return "UNRECOGNIZED";
173
+ }
174
+ }
138
175
  function createBaseCursor() {
139
176
  return { orderKey: BigInt("0"), uniqueKey: new Uint8Array(0) };
140
177
  }
@@ -663,7 +700,7 @@ const Finalize$1 = {
663
700
  }
664
701
  };
665
702
  function createBaseData() {
666
- return { cursor: void 0, endCursor: void 0, finality: 0, data: [] };
703
+ return { cursor: void 0, endCursor: void 0, finality: 0, data: [], production: 0 };
667
704
  }
668
705
  const Data$1 = {
669
706
  encode(message, writer = _m0__default.Writer.create()) {
@@ -679,6 +716,9 @@ const Data$1 = {
679
716
  for (const v of message.data) {
680
717
  writer.uint32(34).bytes(v);
681
718
  }
719
+ if (message.production !== 0) {
720
+ writer.uint32(40).int32(message.production);
721
+ }
682
722
  return writer;
683
723
  },
684
724
  decode(input, length) {
@@ -712,6 +752,12 @@ const Data$1 = {
712
752
  }
713
753
  message.data.push(reader.bytes());
714
754
  continue;
755
+ case 5:
756
+ if (tag !== 40) {
757
+ break;
758
+ }
759
+ message.production = reader.int32();
760
+ continue;
715
761
  }
716
762
  if ((tag & 7) === 4 || tag === 0) {
717
763
  break;
@@ -725,7 +771,8 @@ const Data$1 = {
725
771
  cursor: isSet$1(object.cursor) ? Cursor$1.fromJSON(object.cursor) : void 0,
726
772
  endCursor: isSet$1(object.endCursor) ? Cursor$1.fromJSON(object.endCursor) : void 0,
727
773
  finality: isSet$1(object.finality) ? dataFinalityFromJSON(object.finality) : 0,
728
- data: globalThis.Array.isArray(object?.data) ? object.data.map((e) => bytesFromBase64(e)) : []
774
+ data: globalThis.Array.isArray(object?.data) ? object.data.map((e) => bytesFromBase64(e)) : [],
775
+ production: isSet$1(object.production) ? dataProductionFromJSON(object.production) : 0
729
776
  };
730
777
  },
731
778
  toJSON(message) {
@@ -742,6 +789,9 @@ const Data$1 = {
742
789
  if (message.data?.length) {
743
790
  obj.data = message.data.map((e) => base64FromBytes(e));
744
791
  }
792
+ if (message.production !== 0) {
793
+ obj.production = dataProductionToJSON(message.production);
794
+ }
745
795
  return obj;
746
796
  },
747
797
  create(base) {
@@ -753,6 +803,7 @@ const Data$1 = {
753
803
  message.endCursor = object.endCursor !== void 0 && object.endCursor !== null ? Cursor$1.fromPartial(object.endCursor) : void 0;
754
804
  message.finality = object.finality ?? 0;
755
805
  message.data = object.data?.map((e) => e) || [];
806
+ message.production = object.production ?? 0;
756
807
  return message;
757
808
  }
758
809
  };
@@ -925,6 +976,7 @@ const stream = {
925
976
  Cursor: Cursor$1,
926
977
  Data: Data$1,
927
978
  DataFinality: DataFinality$1,
979
+ DataProduction: DataProduction$1,
928
980
  DnaStreamDefinition: DnaStreamDefinition,
929
981
  Finalize: Finalize$1,
930
982
  Heartbeat: Heartbeat$1,
@@ -936,6 +988,8 @@ const stream = {
936
988
  SystemMessage: SystemMessage$1,
937
989
  dataFinalityFromJSON: dataFinalityFromJSON,
938
990
  dataFinalityToJSON: dataFinalityToJSON,
991
+ dataProductionFromJSON: dataProductionFromJSON,
992
+ dataProductionToJSON: dataProductionToJSON,
939
993
  protobufPackage: protobufPackage$1
940
994
  };
941
995
 
@@ -1097,6 +1151,21 @@ const CursorFromBytes = schema.Schema.transform(
1097
1151
  );
1098
1152
  const cursorToBytes = schema.Schema.encodeSync(CursorFromBytes);
1099
1153
  const cursorFromBytes = schema.Schema.decodeSync(CursorFromBytes);
1154
+ function isCursor(value) {
1155
+ return schema.Schema.is(Cursor)(value);
1156
+ }
1157
+ function normalizeCursor(cursor) {
1158
+ if (cursor.uniqueKey !== null && cursor.uniqueKey.length > 0) {
1159
+ const uniqueKey = cursor.uniqueKey;
1160
+ return {
1161
+ orderKey: BigInt(cursor.orderKey),
1162
+ uniqueKey
1163
+ };
1164
+ }
1165
+ return {
1166
+ orderKey: BigInt(cursor.orderKey)
1167
+ };
1168
+ }
1100
1169
 
1101
1170
  const DataFinality = schema.Schema.transform(
1102
1171
  schema.Schema.Enums(DataFinality$1),
@@ -1123,6 +1192,29 @@ const DataFinality = schema.Schema.transform(
1123
1192
  }
1124
1193
  }
1125
1194
  );
1195
+ const DataProduction = schema.Schema.transform(
1196
+ schema.Schema.Enums(DataProduction$1),
1197
+ schema.Schema.Literal("backfill", "live", "unknown"),
1198
+ {
1199
+ decode(value) {
1200
+ const enumMap = {
1201
+ [DataProduction$1.BACKFILL]: "backfill",
1202
+ [DataProduction$1.LIVE]: "live",
1203
+ [DataProduction$1.UNKNOWN]: "unknown",
1204
+ [DataProduction$1.UNRECOGNIZED]: "unknown"
1205
+ };
1206
+ return enumMap[value] ?? "unknown";
1207
+ },
1208
+ encode(value) {
1209
+ const enumMap = {
1210
+ backfill: DataProduction$1.BACKFILL,
1211
+ live: DataProduction$1.LIVE,
1212
+ unknown: DataProduction$1.UNKNOWN
1213
+ };
1214
+ return enumMap[value] ?? DataProduction$1.UNKNOWN;
1215
+ }
1216
+ }
1217
+ );
1126
1218
  const Duration = schema.Schema.Struct({
1127
1219
  seconds: schema.Schema.BigIntFromSelf,
1128
1220
  nanos: schema.Schema.Number
@@ -1159,15 +1251,16 @@ const StdErr = schema.Schema.Struct({
1159
1251
  const SystemMessage = schema.Schema.Struct({
1160
1252
  _tag: tag("systemMessage"),
1161
1253
  systemMessage: schema.Schema.Struct({
1162
- output: schema.Schema.optional(schema.Schema.Union(StdOut, StdErr))
1254
+ output: schema.Schema.Union(StdOut, StdErr)
1163
1255
  })
1164
1256
  });
1165
1257
  const Data = (schema$1) => schema.Schema.Struct({
1166
1258
  _tag: tag("data"),
1167
1259
  data: schema.Schema.Struct({
1168
1260
  cursor: schema.Schema.optional(Cursor),
1169
- endCursor: schema.Schema.optional(Cursor),
1261
+ endCursor: Cursor,
1170
1262
  finality: DataFinality,
1263
+ production: DataProduction,
1171
1264
  data: schema.Schema.Array(schema$1)
1172
1265
  })
1173
1266
  });
@@ -1225,6 +1318,7 @@ exports.Cursor = Cursor;
1225
1318
  exports.CursorFromBytes = CursorFromBytes;
1226
1319
  exports.Data = Data;
1227
1320
  exports.DataFinality = DataFinality;
1321
+ exports.DataProduction = DataProduction;
1228
1322
  exports.DnaStreamDefinition = DnaStreamDefinition;
1229
1323
  exports.Duration = Duration;
1230
1324
  exports.Finalize = Finalize;
@@ -1244,5 +1338,7 @@ exports.cursorFromBytes = cursorFromBytes;
1244
1338
  exports.cursorFromProto = cursorFromProto;
1245
1339
  exports.cursorToBytes = cursorToBytes;
1246
1340
  exports.cursorToProto = cursorToProto;
1341
+ exports.isCursor = isCursor;
1342
+ exports.normalizeCursor = normalizeCursor;
1247
1343
  exports.stream = stream;
1248
1344
  exports.testing = testing;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const schema = require('@effect/schema');
4
- const config = require('../shared/protocol.e1dec68a.cjs');
4
+ const config = require('../shared/protocol.e39e40d6.cjs');
5
5
  require('protobufjs/minimal.js');
6
6
  require('effect');
7
7
  require('viem');
@@ -1,4 +1,4 @@
1
- import { A as Client, q as StreamDataRequest, z as StreamDataOptions, w as StreamDataResponse, S as StatusRequest, y as ClientCallOptions, l as StatusResponse, x as StreamConfig, c as Cursor, C as CursorProto, K as DataFinality } from '../shared/protocol.8c2a685d.cjs';
1
+ import { J as Client, u as StreamDataRequest, G as StreamDataOptions, z as StreamDataResponse, S as StatusRequest, E as ClientCallOptions, m as StatusResponse, A as StreamConfig, c as Cursor, C as CursorProto, O as DataFinality, P as DataProduction } from '../shared/protocol.4b1cfe2c.cjs';
2
2
  import { Schema } from '@effect/schema';
3
3
  import 'nice-grpc';
4
4
  import 'nice-grpc-common';
@@ -40,8 +40,9 @@ declare const MockStreamResponse: Schema.Union<[Schema.Struct<{
40
40
  _tag: Schema.PropertySignature<":", "data", "$case", ":", "data", false, never>;
41
41
  data: Schema.Struct<{
42
42
  cursor: Schema.optional<Schema.Schema<Cursor, CursorProto, never>>;
43
- endCursor: Schema.optional<Schema.Schema<Cursor, CursorProto, never>>;
43
+ endCursor: Schema.Schema<Cursor, CursorProto, never>;
44
44
  finality: Schema.transform<Schema.Enums<typeof DataFinality>, Schema.Literal<["finalized", "accepted", "pending", "unknown"]>>;
45
+ production: Schema.transform<Schema.Enums<typeof DataProduction>, Schema.Literal<["backfill", "live", "unknown"]>>;
45
46
  data: Schema.Array$<Schema.Schema<{
46
47
  readonly data?: string | undefined;
47
48
  } | null, Uint8Array, never>>;
@@ -61,13 +62,13 @@ declare const MockStreamResponse: Schema.Union<[Schema.Struct<{
61
62
  }>, Schema.Struct<{
62
63
  _tag: Schema.PropertySignature<":", "systemMessage", "$case", ":", "systemMessage", false, never>;
63
64
  systemMessage: Schema.Struct<{
64
- output: Schema.optional<Schema.Union<[Schema.Struct<{
65
+ output: Schema.Union<[Schema.Struct<{
65
66
  _tag: Schema.PropertySignature<":", "stdout", "$case", ":", "stdout", false, never>;
66
67
  stdout: typeof Schema.String;
67
68
  }>, Schema.Struct<{
68
69
  _tag: Schema.PropertySignature<":", "stderr", "$case", ":", "stderr", false, never>;
69
70
  stderr: typeof Schema.String;
70
- }>]>>;
71
+ }>]>;
71
72
  }>;
72
73
  }>]>;
73
74
  type MockStreamResponse = typeof MockStreamResponse.Type;
@@ -1,4 +1,4 @@
1
- import { A as Client, q as StreamDataRequest, z as StreamDataOptions, w as StreamDataResponse, S as StatusRequest, y as ClientCallOptions, l as StatusResponse, x as StreamConfig, c as Cursor, C as CursorProto, K as DataFinality } from '../shared/protocol.8c2a685d.mjs';
1
+ import { J as Client, u as StreamDataRequest, G as StreamDataOptions, z as StreamDataResponse, S as StatusRequest, E as ClientCallOptions, m as StatusResponse, A as StreamConfig, c as Cursor, C as CursorProto, O as DataFinality, P as DataProduction } from '../shared/protocol.4b1cfe2c.mjs';
2
2
  import { Schema } from '@effect/schema';
3
3
  import 'nice-grpc';
4
4
  import 'nice-grpc-common';
@@ -40,8 +40,9 @@ declare const MockStreamResponse: Schema.Union<[Schema.Struct<{
40
40
  _tag: Schema.PropertySignature<":", "data", "$case", ":", "data", false, never>;
41
41
  data: Schema.Struct<{
42
42
  cursor: Schema.optional<Schema.Schema<Cursor, CursorProto, never>>;
43
- endCursor: Schema.optional<Schema.Schema<Cursor, CursorProto, never>>;
43
+ endCursor: Schema.Schema<Cursor, CursorProto, never>;
44
44
  finality: Schema.transform<Schema.Enums<typeof DataFinality>, Schema.Literal<["finalized", "accepted", "pending", "unknown"]>>;
45
+ production: Schema.transform<Schema.Enums<typeof DataProduction>, Schema.Literal<["backfill", "live", "unknown"]>>;
45
46
  data: Schema.Array$<Schema.Schema<{
46
47
  readonly data?: string | undefined;
47
48
  } | null, Uint8Array, never>>;
@@ -61,13 +62,13 @@ declare const MockStreamResponse: Schema.Union<[Schema.Struct<{
61
62
  }>, Schema.Struct<{
62
63
  _tag: Schema.PropertySignature<":", "systemMessage", "$case", ":", "systemMessage", false, never>;
63
64
  systemMessage: Schema.Struct<{
64
- output: Schema.optional<Schema.Union<[Schema.Struct<{
65
+ output: Schema.Union<[Schema.Struct<{
65
66
  _tag: Schema.PropertySignature<":", "stdout", "$case", ":", "stdout", false, never>;
66
67
  stdout: typeof Schema.String;
67
68
  }>, Schema.Struct<{
68
69
  _tag: Schema.PropertySignature<":", "stderr", "$case", ":", "stderr", false, never>;
69
70
  stderr: typeof Schema.String;
70
- }>]>>;
71
+ }>]>;
71
72
  }>;
72
73
  }>]>;
73
74
  type MockStreamResponse = typeof MockStreamResponse.Type;
@@ -1,4 +1,4 @@
1
- import { A as Client, q as StreamDataRequest, z as StreamDataOptions, w as StreamDataResponse, S as StatusRequest, y as ClientCallOptions, l as StatusResponse, x as StreamConfig, c as Cursor, C as CursorProto, K as DataFinality } from '../shared/protocol.8c2a685d.js';
1
+ import { J as Client, u as StreamDataRequest, G as StreamDataOptions, z as StreamDataResponse, S as StatusRequest, E as ClientCallOptions, m as StatusResponse, A as StreamConfig, c as Cursor, C as CursorProto, O as DataFinality, P as DataProduction } from '../shared/protocol.4b1cfe2c.js';
2
2
  import { Schema } from '@effect/schema';
3
3
  import 'nice-grpc';
4
4
  import 'nice-grpc-common';
@@ -40,8 +40,9 @@ declare const MockStreamResponse: Schema.Union<[Schema.Struct<{
40
40
  _tag: Schema.PropertySignature<":", "data", "$case", ":", "data", false, never>;
41
41
  data: Schema.Struct<{
42
42
  cursor: Schema.optional<Schema.Schema<Cursor, CursorProto, never>>;
43
- endCursor: Schema.optional<Schema.Schema<Cursor, CursorProto, never>>;
43
+ endCursor: Schema.Schema<Cursor, CursorProto, never>;
44
44
  finality: Schema.transform<Schema.Enums<typeof DataFinality>, Schema.Literal<["finalized", "accepted", "pending", "unknown"]>>;
45
+ production: Schema.transform<Schema.Enums<typeof DataProduction>, Schema.Literal<["backfill", "live", "unknown"]>>;
45
46
  data: Schema.Array$<Schema.Schema<{
46
47
  readonly data?: string | undefined;
47
48
  } | null, Uint8Array, never>>;
@@ -61,13 +62,13 @@ declare const MockStreamResponse: Schema.Union<[Schema.Struct<{
61
62
  }>, Schema.Struct<{
62
63
  _tag: Schema.PropertySignature<":", "systemMessage", "$case", ":", "systemMessage", false, never>;
63
64
  systemMessage: Schema.Struct<{
64
- output: Schema.optional<Schema.Union<[Schema.Struct<{
65
+ output: Schema.Union<[Schema.Struct<{
65
66
  _tag: Schema.PropertySignature<":", "stdout", "$case", ":", "stdout", false, never>;
66
67
  stdout: typeof Schema.String;
67
68
  }>, Schema.Struct<{
68
69
  _tag: Schema.PropertySignature<":", "stderr", "$case", ":", "stderr", false, never>;
69
70
  stderr: typeof Schema.String;
70
- }>]>>;
71
+ }>]>;
71
72
  }>;
72
73
  }>]>;
73
74
  type MockStreamResponse = typeof MockStreamResponse.Type;
@@ -1,5 +1,5 @@
1
1
  import { Schema } from '@effect/schema';
2
- import { M as MockFilter$1, p as MockBlock$1, o as StreamConfig, S as StreamDataResponse } from '../shared/protocol.d9596779.mjs';
2
+ import { M as MockFilter$1, u as MockBlock$1, r as StreamConfig, S as StreamDataResponse } from '../shared/protocol.991ff9ad.mjs';
3
3
  import 'protobufjs/minimal.js';
4
4
  import 'effect';
5
5
  import 'viem';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apibara/protocol",
3
- "version": "2.0.0-beta.9",
3
+ "version": "2.1.0-beta.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
package/src/client.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Schema } from "@effect/schema";
2
2
  import {
3
+ type ChannelCredentials,
4
+ type ChannelOptions,
3
5
  type DefaultCallOptions,
4
6
  type NormalizedServiceDefinition,
5
7
  createChannel,
@@ -19,14 +21,27 @@ import {
19
21
  } from "./status";
20
22
  import { type StreamDataRequest, StreamDataResponse } from "./stream";
21
23
 
24
+ export { ClientError, Status } from "nice-grpc";
25
+
26
+ const DEFAULT_TIMEOUT_MS = 45_000;
27
+
28
+ export class TimeoutError extends Error {
29
+ constructor(timeout: number) {
30
+ super(`No message received in ${timeout}ms`);
31
+ this.name = "TimeoutError";
32
+ }
33
+ }
34
+
22
35
  /** Client call options. */
23
36
  export interface ClientCallOptions {
24
37
  signal?: AbortSignal;
25
38
  }
26
39
 
27
40
  export interface StreamDataOptions extends ClientCallOptions {
28
- /** Stop at the specified cursor (inclusive) */
41
+ /** Stop at the specified cursor (inclusive). */
29
42
  endingCursor?: Cursor;
43
+ /** Timeout between messages, in milliseconds. */
44
+ timeout?: number;
30
45
  }
31
46
 
32
47
  /** DNA client. */
@@ -44,20 +59,32 @@ export interface Client<TFilter, TBlock> {
44
59
  ): AsyncIterable<StreamDataResponse<TBlock>>;
45
60
  }
46
61
 
62
+ export type CreateClientOptions = {
63
+ defaultCallOptions?: DefaultCallOptions<
64
+ NormalizedServiceDefinition<proto.stream.DnaStreamDefinition>
65
+ >;
66
+ credentials?: ChannelCredentials;
67
+ channelOptions?: ChannelOptions;
68
+ };
69
+
47
70
  /** Create a client connecting to the DNA grpc service. */
48
71
  export function createClient<TFilter, TBlock>(
49
72
  config: StreamConfig<TFilter, TBlock>,
50
73
  streamUrl: string,
51
- defaultCallOptions?: DefaultCallOptions<
52
- NormalizedServiceDefinition<proto.stream.DnaStreamDefinition>
53
- >,
74
+ options: CreateClientOptions = {},
54
75
  ) {
55
- const channel = createChannel(streamUrl);
76
+ const channel = createChannel(
77
+ streamUrl,
78
+ options?.credentials,
79
+ options?.channelOptions,
80
+ );
81
+
56
82
  const client: proto.stream.DnaStreamClient = grpcCreateClient(
57
83
  proto.stream.DnaStreamDefinition,
58
84
  channel,
59
- defaultCallOptions,
85
+ options?.defaultCallOptions,
60
86
  );
87
+
61
88
  return new GrpcClient(config, client);
62
89
  }
63
90
 
@@ -96,44 +123,61 @@ export class StreamDataIterable<TBlock> {
96
123
  const inner = this.it[Symbol.asyncIterator]();
97
124
  const schema = StreamDataResponse(this.schema);
98
125
  const decoder = Schema.decodeSync(schema);
99
- const { endingCursor } = this.options ?? {};
126
+ const { endingCursor, timeout = DEFAULT_TIMEOUT_MS } = this.options ?? {};
100
127
  let shouldStop = false;
101
128
 
129
+ let clock: string | number | NodeJS.Timeout | undefined;
130
+
102
131
  return {
103
132
  async next() {
104
133
  if (shouldStop) {
105
134
  return { done: true, value: undefined };
106
135
  }
107
136
 
108
- const { done, value } = await inner.next();
137
+ // biome-ignore lint/suspicious/noExplicitAny: any is ok
138
+ const t: Promise<{ done: boolean; value: any }> = new Promise(
139
+ (_, reject) => {
140
+ clock = setTimeout(() => {
141
+ reject(new TimeoutError(timeout));
142
+ }, timeout);
143
+ },
144
+ );
109
145
 
110
- if (done || value.message === undefined) {
111
- return { done: true, value: undefined };
112
- }
146
+ try {
147
+ const { done, value } = await Promise.race([inner.next(), t]);
113
148
 
114
- const decodedMessage = decoder(value.message);
149
+ clearTimeout(clock);
115
150
 
116
- if (endingCursor) {
117
- assert(value.message.$case === "data");
118
- assert(decodedMessage._tag === "data");
151
+ if (done || value.message === undefined) {
152
+ return { done: true, value: undefined };
153
+ }
154
+
155
+ const decodedMessage = decoder(value.message);
156
+
157
+ if (endingCursor) {
158
+ assert(value.message.$case === "data");
159
+ assert(decodedMessage._tag === "data");
119
160
 
120
- const { orderKey, uniqueKey } = endingCursor;
121
- const endCursor = decodedMessage.data.endCursor;
161
+ const { orderKey, uniqueKey } = endingCursor;
162
+ const endCursor = decodedMessage.data.endCursor;
122
163
 
123
- // Check if the orderKey matches
124
- if (orderKey === endCursor?.orderKey) {
125
- // If a uniqueKey is specified, it must also match
126
- if (!uniqueKey || uniqueKey === endCursor.uniqueKey) {
127
- shouldStop = true;
128
- return { done: false, value: decodedMessage };
164
+ // Check if the orderKey matches
165
+ if (orderKey === endCursor?.orderKey) {
166
+ // If a uniqueKey is specified, it must also match
167
+ if (!uniqueKey || uniqueKey === endCursor.uniqueKey) {
168
+ shouldStop = true;
169
+ return { done: false, value: decodedMessage };
170
+ }
129
171
  }
130
172
  }
131
- }
132
173
 
133
- return {
134
- done: false,
135
- value: decodedMessage,
136
- };
174
+ return {
175
+ done: false,
176
+ value: decodedMessage,
177
+ };
178
+ } finally {
179
+ clearTimeout(clock);
180
+ }
137
181
  },
138
182
  };
139
183
  }
package/src/common.ts CHANGED
@@ -63,3 +63,31 @@ export const CursorFromBytes = Schema.transform(
63
63
 
64
64
  export const cursorToBytes = Schema.encodeSync(CursorFromBytes);
65
65
  export const cursorFromBytes = Schema.decodeSync(CursorFromBytes);
66
+
67
+ export function isCursor(value: unknown): value is Cursor {
68
+ return Schema.is(Cursor)(value);
69
+ }
70
+
71
+ /** Normalize a cursor.
72
+ *
73
+ * The challenge is that the `Cursor` validator expects `uniqueKey` to be either a `0x${string}`
74
+ * or not present at all. Setting the field to `undefined` will result in a validation error.
75
+ *
76
+ * @param cursor The cursor to normalize
77
+ */
78
+ export function normalizeCursor(cursor: {
79
+ orderKey: bigint;
80
+ uniqueKey: string | null;
81
+ }): Cursor {
82
+ if (cursor.uniqueKey !== null && cursor.uniqueKey.length > 0) {
83
+ const uniqueKey = cursor.uniqueKey as `0x${string}`;
84
+ return {
85
+ orderKey: BigInt(cursor.orderKey),
86
+ uniqueKey,
87
+ };
88
+ }
89
+
90
+ return {
91
+ orderKey: BigInt(cursor.orderKey),
92
+ };
93
+ }
@@ -63,6 +63,48 @@ export function dataFinalityToJSON(object: DataFinality): string {
63
63
  }
64
64
  }
65
65
 
66
+ /** Data production mode. */
67
+ export enum DataProduction {
68
+ UNKNOWN = 0,
69
+ /** BACKFILL - Data is for a backfilled block. */
70
+ BACKFILL = 1,
71
+ /** LIVE - Data is for a live block. */
72
+ LIVE = 2,
73
+ UNRECOGNIZED = -1,
74
+ }
75
+
76
+ export function dataProductionFromJSON(object: any): DataProduction {
77
+ switch (object) {
78
+ case 0:
79
+ case "DATA_PRODUCTION_UNKNOWN":
80
+ return DataProduction.UNKNOWN;
81
+ case 1:
82
+ case "DATA_PRODUCTION_BACKFILL":
83
+ return DataProduction.BACKFILL;
84
+ case 2:
85
+ case "DATA_PRODUCTION_LIVE":
86
+ return DataProduction.LIVE;
87
+ case -1:
88
+ case "UNRECOGNIZED":
89
+ default:
90
+ return DataProduction.UNRECOGNIZED;
91
+ }
92
+ }
93
+
94
+ export function dataProductionToJSON(object: DataProduction): string {
95
+ switch (object) {
96
+ case DataProduction.UNKNOWN:
97
+ return "DATA_PRODUCTION_UNKNOWN";
98
+ case DataProduction.BACKFILL:
99
+ return "DATA_PRODUCTION_BACKFILL";
100
+ case DataProduction.LIVE:
101
+ return "DATA_PRODUCTION_LIVE";
102
+ case DataProduction.UNRECOGNIZED:
103
+ default:
104
+ return "UNRECOGNIZED";
105
+ }
106
+ }
107
+
66
108
  /** A cursor over the stream content. */
67
109
  export interface Cursor {
68
110
  /**
@@ -192,6 +234,8 @@ export interface Data {
192
234
  * This message contains chain-specific data serialized using protobuf.
193
235
  */
194
236
  readonly data: readonly Uint8Array[];
237
+ /** The production mode of the block. */
238
+ readonly production: DataProduction;
195
239
  }
196
240
 
197
241
  /** Sent to clients to check if stream is still connected. */
@@ -838,7 +882,7 @@ export const Finalize = {
838
882
  };
839
883
 
840
884
  function createBaseData(): Data {
841
- return { cursor: undefined, endCursor: undefined, finality: 0, data: [] };
885
+ return { cursor: undefined, endCursor: undefined, finality: 0, data: [], production: 0 };
842
886
  }
843
887
 
844
888
  export const Data = {
@@ -855,6 +899,9 @@ export const Data = {
855
899
  for (const v of message.data) {
856
900
  writer.uint32(34).bytes(v!);
857
901
  }
902
+ if (message.production !== 0) {
903
+ writer.uint32(40).int32(message.production);
904
+ }
858
905
  return writer;
859
906
  },
860
907
 
@@ -893,6 +940,13 @@ export const Data = {
893
940
 
894
941
  message.data.push(reader.bytes());
895
942
  continue;
943
+ case 5:
944
+ if (tag !== 40) {
945
+ break;
946
+ }
947
+
948
+ message.production = reader.int32() as any;
949
+ continue;
896
950
  }
897
951
  if ((tag & 7) === 4 || tag === 0) {
898
952
  break;
@@ -908,6 +962,7 @@ export const Data = {
908
962
  endCursor: isSet(object.endCursor) ? Cursor.fromJSON(object.endCursor) : undefined,
909
963
  finality: isSet(object.finality) ? dataFinalityFromJSON(object.finality) : 0,
910
964
  data: globalThis.Array.isArray(object?.data) ? object.data.map((e: any) => bytesFromBase64(e)) : [],
965
+ production: isSet(object.production) ? dataProductionFromJSON(object.production) : 0,
911
966
  };
912
967
  },
913
968
 
@@ -925,6 +980,9 @@ export const Data = {
925
980
  if (message.data?.length) {
926
981
  obj.data = message.data.map((e) => base64FromBytes(e));
927
982
  }
983
+ if (message.production !== 0) {
984
+ obj.production = dataProductionToJSON(message.production);
985
+ }
928
986
  return obj;
929
987
  },
930
988
 
@@ -941,6 +999,7 @@ export const Data = {
941
999
  : undefined;
942
1000
  message.finality = object.finality ?? 0;
943
1001
  message.data = object.data?.map((e) => e) || [];
1002
+ message.production = object.production ?? 0;
944
1003
  return message;
945
1004
  },
946
1005
  };
@@ -95,6 +95,11 @@ describe("StreamDataResponse", () => {
95
95
  data: {
96
96
  finality: "accepted",
97
97
  data: [{ value: "hello" }, { value: "world" }],
98
+ production: "backfill",
99
+ endCursor: {
100
+ orderKey: 5_000_000n,
101
+ uniqueKey: "0x1234567890",
102
+ },
98
103
  },
99
104
  } as const;
100
105
 
@@ -119,7 +124,18 @@ describe("StreamDataResponse", () => {
119
124
  100,
120
125
  ],
121
126
  ],
127
+ "endCursor": {
128
+ "orderKey": 5000000n,
129
+ "uniqueKey": Uint8Array [
130
+ 18,
131
+ 52,
132
+ 86,
133
+ 120,
134
+ 144,
135
+ ],
136
+ },
122
137
  "finality": 2,
138
+ "production": 1,
123
139
  },
124
140
  }
125
141
  `);