@apibara/protocol 0.4.7 → 0.4.9
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/client.d.ts +9 -9
- package/dist/client.js +26 -14
- package/dist/client.js.map +1 -1
- package/dist/cursor.d.ts +15 -2
- package/dist/cursor.js +26 -2
- package/dist/cursor.js.map +1 -1
- package/dist/cursor.test.d.ts +1 -0
- package/dist/cursor.test.js +22 -0
- package/dist/cursor.test.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js.map +1 -1
- package/dist/proto/apibara/node/v1alpha2/Data.d.ts +3 -3
- package/dist/proto/apibara/node/v1alpha2/DataFinality.d.ts +8 -6
- package/dist/proto/apibara/node/v1alpha2/DataFinality.js +6 -7
- package/dist/proto/apibara/node/v1alpha2/DataFinality.js.map +1 -1
- package/dist/proto/apibara/node/v1alpha2/StreamDataRequest.d.ts +3 -3
- package/dist/proto/index.d.ts +1 -1
- package/dist/proto/index.js.map +1 -1
- package/dist/proto/stream.d.ts +1 -1
- package/dist/proto/testing.d.ts +1 -1
- package/dist/proto/testing.js +4 -2
- package/dist/proto/testing.js.map +1 -1
- package/dist/proto/v1alpha2.d.ts +9 -9
- package/dist/proto/v1alpha2.js +1 -1
- package/dist/proto/v1alpha2.js.map +1 -1
- package/dist/request.d.ts +2 -2
- package/dist/request.js +1 -0
- package/dist/request.js.map +1 -1
- package/dist/request.test.js +9 -10
- package/dist/request.test.js.map +1 -1
- package/package.json +4 -3
- package/src/client.ts +118 -97
- package/src/cursor.test.ts +21 -0
- package/src/cursor.ts +35 -7
- package/src/index.ts +4 -4
- package/src/proto/apibara/node/v1alpha2/Data.ts +3 -3
- package/src/proto/apibara/node/v1alpha2/DataFinality.ts +18 -6
- package/src/proto/apibara/node/v1alpha2/StreamDataRequest.ts +3 -3
- package/src/proto/index.ts +1 -1
- package/src/proto/testing.ts +5 -5
- package/src/proto/v1alpha2.ts +16 -14
- package/src/request.test.ts +19 -20
- package/src/request.ts +16 -16
package/src/client.ts
CHANGED
|
@@ -5,47 +5,47 @@ import {
|
|
|
5
5
|
ClientOptions,
|
|
6
6
|
Metadata,
|
|
7
7
|
StatusObject,
|
|
8
|
-
} from
|
|
9
|
-
import { CallMetadataGenerator } from
|
|
10
|
-
import { v1alpha2 } from
|
|
11
|
-
import { StreamDataRequest } from
|
|
8
|
+
} from "@grpc/grpc-js";
|
|
9
|
+
import { CallMetadataGenerator } from "@grpc/grpc-js/build/src/call-credentials";
|
|
10
|
+
import { v1alpha2 } from "./proto";
|
|
11
|
+
import { StreamDataRequest } from "./request";
|
|
12
12
|
|
|
13
|
-
export { ChannelCredentials, StatusObject } from
|
|
13
|
+
export { ChannelCredentials, StatusObject } from "@grpc/grpc-js";
|
|
14
14
|
|
|
15
|
-
const StreamService = v1alpha2.protoDescriptor.apibara.node.v1alpha2.Stream
|
|
15
|
+
const StreamService = v1alpha2.protoDescriptor.apibara.node.v1alpha2.Stream;
|
|
16
16
|
|
|
17
17
|
// Server produces an heartbeat every 30 seconds, so we use 45 seconds as a timeout.
|
|
18
|
-
const MESSAGE_TIMEOUT_MS = 45_000
|
|
18
|
+
const MESSAGE_TIMEOUT_MS = 45_000;
|
|
19
19
|
|
|
20
20
|
// Increase the default message length to 128 MiB.
|
|
21
|
-
const DEFAULT_MESSAGE_LENGTH = 128 * 1_048_576 // 128 MiB
|
|
21
|
+
const DEFAULT_MESSAGE_LENGTH = 128 * 1_048_576; // 128 MiB
|
|
22
22
|
|
|
23
23
|
export type DataStream = ClientDuplexStream<
|
|
24
24
|
v1alpha2.IStreamDataRequest,
|
|
25
25
|
v1alpha2.IStreamDataResponse
|
|
26
|
-
|
|
26
|
+
>;
|
|
27
27
|
|
|
28
28
|
export type ConfigureArgs = {
|
|
29
29
|
/**
|
|
30
30
|
* Stream filter, encoded.
|
|
31
31
|
*/
|
|
32
|
-
filter: Uint8Array
|
|
32
|
+
filter: Uint8Array;
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* How much data in a single message.
|
|
36
36
|
*/
|
|
37
|
-
batchSize?: number
|
|
37
|
+
batchSize?: number;
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Starting cursor. This cursor is stream-specific.
|
|
41
41
|
*/
|
|
42
|
-
cursor?: v1alpha2.ICursor | null
|
|
42
|
+
cursor?: v1alpha2.ICursor | null;
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Data finality, e.g. finalized or accepted.
|
|
46
46
|
*/
|
|
47
|
-
finality?: v1alpha2.DataFinality | null
|
|
48
|
-
}
|
|
47
|
+
finality?: v1alpha2.DataFinality | null;
|
|
48
|
+
};
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Reconnect callback return value.
|
|
@@ -54,7 +54,7 @@ export type OnReconnectResult = {
|
|
|
54
54
|
/**
|
|
55
55
|
* If `true`, reconnects to the stream.
|
|
56
56
|
*/
|
|
57
|
-
reconnect: boolean
|
|
57
|
+
reconnect: boolean;
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Stream configuration used when reconnecting.
|
|
@@ -62,66 +62,66 @@ export type OnReconnectResult = {
|
|
|
62
62
|
* By default, the client uses the last configuration passed to
|
|
63
63
|
* `configure` and updates the `cursor` with the most recent one.
|
|
64
64
|
*/
|
|
65
|
-
args?: ConfigureArgs
|
|
66
|
-
}
|
|
65
|
+
args?: ConfigureArgs;
|
|
66
|
+
};
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Reconnect callback.
|
|
70
70
|
*/
|
|
71
71
|
export type OnReconnect = (
|
|
72
72
|
err: StatusObject,
|
|
73
|
-
retryCount: number
|
|
74
|
-
) => Promise<OnReconnectResult> | OnReconnectResult
|
|
73
|
+
retryCount: number,
|
|
74
|
+
) => Promise<OnReconnectResult> | OnReconnectResult;
|
|
75
75
|
|
|
76
76
|
export type StreamClientArgs = {
|
|
77
77
|
/**
|
|
78
78
|
* The stream url.
|
|
79
79
|
*/
|
|
80
|
-
url: string
|
|
80
|
+
url: string;
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
83
|
* Override Grpc credentials.
|
|
84
84
|
*
|
|
85
85
|
* Use `ChannelCredentials.createInsecure()` to disable SSL.
|
|
86
86
|
*/
|
|
87
|
-
credentials?: ChannelCredentials
|
|
87
|
+
credentials?: ChannelCredentials;
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
90
|
* Grpc client options.
|
|
91
91
|
*/
|
|
92
|
-
clientOptions?: ClientOptions
|
|
92
|
+
clientOptions?: ClientOptions;
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* Authorization bearer token, used to authenticate with the server.
|
|
96
96
|
*/
|
|
97
|
-
token?: string
|
|
97
|
+
token?: string;
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Callback to control reconnection after receiving an error from the stream.
|
|
101
101
|
*
|
|
102
102
|
* By default uses `defaultOnReconnect`, which only reconnects on internal grpc errors.
|
|
103
103
|
*/
|
|
104
|
-
onReconnect?: OnReconnect
|
|
104
|
+
onReconnect?: OnReconnect;
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* Maximum time to wait for a message before timing out, in milliseconds.
|
|
108
108
|
*
|
|
109
109
|
* Defaults to 45 seconds.
|
|
110
110
|
*/
|
|
111
|
-
timeout?: number
|
|
112
|
-
}
|
|
111
|
+
timeout?: number;
|
|
112
|
+
};
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* A client to configure and stream data.
|
|
116
116
|
*/
|
|
117
117
|
export class StreamClient {
|
|
118
|
-
private readonly inner: v1alpha2.StreamClient
|
|
118
|
+
private readonly inner: v1alpha2.StreamClient;
|
|
119
119
|
|
|
120
|
-
private stream?: DataStream
|
|
121
|
-
private stream_id: number
|
|
122
|
-
private onReconnect: OnReconnect
|
|
123
|
-
private configuration?: ConfigureArgs
|
|
124
|
-
private timeout: number
|
|
120
|
+
private stream?: DataStream;
|
|
121
|
+
private stream_id: number;
|
|
122
|
+
private onReconnect: OnReconnect;
|
|
123
|
+
private configuration?: ConfigureArgs;
|
|
124
|
+
private timeout: number;
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
127
|
* Create a new `StreamClient`.
|
|
@@ -142,24 +142,33 @@ export class StreamClient {
|
|
|
142
142
|
* }
|
|
143
143
|
* ```
|
|
144
144
|
*/
|
|
145
|
-
constructor({
|
|
146
|
-
|
|
145
|
+
constructor({
|
|
146
|
+
url,
|
|
147
|
+
credentials,
|
|
148
|
+
clientOptions,
|
|
149
|
+
token,
|
|
150
|
+
onReconnect,
|
|
151
|
+
timeout,
|
|
152
|
+
}: StreamClientArgs) {
|
|
153
|
+
const baseCredentials = credentials ?? ChannelCredentials.createSsl();
|
|
147
154
|
|
|
148
155
|
// only secure credentials can be composed with metadata generators.
|
|
149
156
|
const credentialsWithMetadata = baseCredentials._isSecure()
|
|
150
157
|
? baseCredentials.compose(
|
|
151
|
-
CallCredentials.createFromMetadataGenerator(
|
|
158
|
+
CallCredentials.createFromMetadataGenerator(
|
|
159
|
+
createMetadataGenerator(token),
|
|
160
|
+
),
|
|
152
161
|
)
|
|
153
|
-
: baseCredentials
|
|
162
|
+
: baseCredentials;
|
|
154
163
|
|
|
155
164
|
this.inner = new StreamService(url, credentialsWithMetadata, {
|
|
156
|
-
|
|
157
|
-
|
|
165
|
+
"grpc.keepalive_timeout_ms": 3_600_000,
|
|
166
|
+
"grpc.max_receive_message_length": DEFAULT_MESSAGE_LENGTH,
|
|
158
167
|
...clientOptions,
|
|
159
|
-
})
|
|
160
|
-
this.stream_id = 0
|
|
161
|
-
this.onReconnect = onReconnect ?? defaultOnReconnect
|
|
162
|
-
this.timeout = timeout ?? MESSAGE_TIMEOUT_MS
|
|
168
|
+
});
|
|
169
|
+
this.stream_id = 0;
|
|
170
|
+
this.onReconnect = onReconnect ?? defaultOnReconnect;
|
|
171
|
+
this.timeout = timeout ?? MESSAGE_TIMEOUT_MS;
|
|
163
172
|
}
|
|
164
173
|
|
|
165
174
|
/**
|
|
@@ -167,86 +176,93 @@ export class StreamClient {
|
|
|
167
176
|
*/
|
|
168
177
|
async *[Symbol.asyncIterator](): AsyncIterator<v1alpha2.IStreamDataResponse> {
|
|
169
178
|
if (!this.configuration) {
|
|
170
|
-
throw new Error(
|
|
179
|
+
throw new Error("StreamClient must be configured");
|
|
171
180
|
}
|
|
172
181
|
|
|
173
182
|
// connect if not connected.
|
|
174
183
|
if (!this.stream) {
|
|
175
|
-
this.connect()
|
|
176
|
-
this._configure(this.configuration)
|
|
184
|
+
this.connect();
|
|
185
|
+
this._configure(this.configuration);
|
|
177
186
|
}
|
|
178
187
|
|
|
179
188
|
while (true) {
|
|
180
|
-
let retryCount = 1
|
|
181
|
-
let cursor = null
|
|
182
|
-
let clock
|
|
189
|
+
let retryCount = 1;
|
|
190
|
+
let cursor = null;
|
|
191
|
+
let clock;
|
|
183
192
|
try {
|
|
184
193
|
// this check is to make ts happy
|
|
185
194
|
if (!this.stream) {
|
|
186
|
-
throw new Error(
|
|
195
|
+
throw new Error("Stream disconnected unexpectedly");
|
|
187
196
|
}
|
|
188
197
|
|
|
189
|
-
const streamIter = this.stream[Symbol.asyncIterator]()
|
|
198
|
+
const streamIter = this.stream[Symbol.asyncIterator]();
|
|
190
199
|
while (true) {
|
|
191
200
|
const timeout = new Promise((_, reject) => {
|
|
192
201
|
clock = setTimeout(() => {
|
|
193
|
-
reject(new Error(
|
|
194
|
-
}, this.timeout)
|
|
195
|
-
})
|
|
202
|
+
reject(new Error("Stream timed out"));
|
|
203
|
+
}, this.timeout);
|
|
204
|
+
});
|
|
196
205
|
|
|
197
206
|
const message = <IteratorResult<v1alpha2.IStreamDataResponse>>(
|
|
198
207
|
await Promise.race([streamIter.next(), timeout])
|
|
199
|
-
)
|
|
200
|
-
const messageTyped = message.value as v1alpha2.IStreamDataResponse
|
|
208
|
+
);
|
|
209
|
+
const messageTyped = message.value as v1alpha2.IStreamDataResponse;
|
|
201
210
|
|
|
202
|
-
clearTimeout(clock)
|
|
211
|
+
clearTimeout(clock);
|
|
203
212
|
|
|
204
|
-
|
|
205
|
-
|
|
213
|
+
if (messageTyped.message === "heartbeat") {
|
|
214
|
+
yield messageTyped;
|
|
215
|
+
} else if (
|
|
216
|
+
messageTyped.streamId?.toString() === this.stream_id.toString()
|
|
217
|
+
) {
|
|
218
|
+
// only return messages if they are with the most recently configured stream
|
|
206
219
|
// reset retry count on new message
|
|
207
|
-
retryCount = 1
|
|
220
|
+
retryCount = 1;
|
|
208
221
|
|
|
209
222
|
// keep cursor updated for use when reconnecting
|
|
210
223
|
if (messageTyped.data) {
|
|
211
|
-
cursor = messageTyped.data.cursor
|
|
224
|
+
cursor = messageTyped.data.cursor;
|
|
212
225
|
} else if (messageTyped.invalidate) {
|
|
213
|
-
cursor = messageTyped.invalidate.cursor
|
|
226
|
+
cursor = messageTyped.invalidate.cursor;
|
|
214
227
|
}
|
|
215
228
|
|
|
216
|
-
yield messageTyped
|
|
229
|
+
yield messageTyped;
|
|
217
230
|
}
|
|
218
231
|
}
|
|
232
|
+
// rome-ignore lint: any is needed for catch
|
|
219
233
|
} catch (err: any) {
|
|
220
|
-
clearTimeout(clock)
|
|
234
|
+
clearTimeout(clock);
|
|
221
235
|
|
|
222
236
|
const isGrpcError =
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
237
|
+
Object.hasOwn(err, "code") &&
|
|
238
|
+
Object.hasOwn(err, "details") &&
|
|
239
|
+
Object.hasOwn(err, "metadata");
|
|
226
240
|
|
|
227
241
|
// non-grpc error, so just bubble it up
|
|
228
242
|
if (!isGrpcError) {
|
|
229
|
-
throw err
|
|
243
|
+
throw err;
|
|
230
244
|
}
|
|
231
245
|
|
|
232
|
-
const { reconnect, args } = await Promise.resolve(
|
|
233
|
-
|
|
246
|
+
const { reconnect, args } = await Promise.resolve(
|
|
247
|
+
this.onReconnect(err, retryCount),
|
|
248
|
+
);
|
|
249
|
+
retryCount += 1;
|
|
234
250
|
if (!reconnect) {
|
|
235
|
-
throw err
|
|
251
|
+
throw err;
|
|
236
252
|
}
|
|
237
253
|
|
|
238
|
-
this.connect()
|
|
254
|
+
this.connect();
|
|
239
255
|
|
|
240
256
|
if (args) {
|
|
241
|
-
this._configure(args)
|
|
257
|
+
this._configure(args);
|
|
242
258
|
} else {
|
|
243
259
|
// use same configuration specified by user, restarting from the
|
|
244
260
|
// latest ingested batch.
|
|
245
261
|
const configuration = {
|
|
246
262
|
...this.configuration,
|
|
247
263
|
cursor: cursor ?? this.configuration.cursor,
|
|
248
|
-
}
|
|
249
|
-
this._configure(configuration)
|
|
264
|
+
};
|
|
265
|
+
this._configure(configuration);
|
|
250
266
|
}
|
|
251
267
|
}
|
|
252
268
|
}
|
|
@@ -260,46 +276,51 @@ export class StreamClient {
|
|
|
260
276
|
* are old messages in-flight.
|
|
261
277
|
*/
|
|
262
278
|
configure(args: ConfigureArgs) {
|
|
263
|
-
this.configuration = args
|
|
264
|
-
this._configure(args)
|
|
279
|
+
this.configuration = args;
|
|
280
|
+
this._configure(args);
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
private _configure(args: ConfigureArgs) {
|
|
268
|
-
const { filter, batchSize, cursor, finality } = args
|
|
269
|
-
this.stream_id
|
|
284
|
+
const { filter, batchSize, cursor, finality } = args;
|
|
285
|
+
this.stream_id++;
|
|
270
286
|
|
|
271
287
|
// only send configuration if connected
|
|
272
288
|
if (this.stream) {
|
|
273
|
-
const builder = StreamDataRequest.create()
|
|
289
|
+
const builder = StreamDataRequest.create()
|
|
290
|
+
.withStreamId(this.stream_id)
|
|
291
|
+
.withFilter(filter);
|
|
274
292
|
|
|
275
293
|
if (batchSize) {
|
|
276
|
-
builder.withBatchSize(batchSize)
|
|
294
|
+
builder.withBatchSize(batchSize);
|
|
277
295
|
}
|
|
278
296
|
if (cursor) {
|
|
279
|
-
builder.withStartingCursor(cursor)
|
|
297
|
+
builder.withStartingCursor(cursor);
|
|
280
298
|
}
|
|
281
299
|
if (finality) {
|
|
282
|
-
builder.withFinality(finality)
|
|
300
|
+
builder.withFinality(finality);
|
|
283
301
|
}
|
|
284
302
|
|
|
285
|
-
const request = builder.encode()
|
|
286
|
-
this.stream?.write(request)
|
|
303
|
+
const request = builder.encode();
|
|
304
|
+
this.stream?.write(request);
|
|
287
305
|
}
|
|
288
306
|
}
|
|
289
307
|
|
|
290
308
|
private connect() {
|
|
291
|
-
this.stream = this.inner.streamData()
|
|
292
|
-
return this
|
|
309
|
+
this.stream = this.inner.streamData();
|
|
310
|
+
return this;
|
|
293
311
|
}
|
|
294
312
|
}
|
|
295
313
|
|
|
296
314
|
/**
|
|
297
315
|
* A `onReconnect` callback that never reconnects.
|
|
298
316
|
*/
|
|
299
|
-
export function neverReconnect(
|
|
317
|
+
export function neverReconnect(
|
|
318
|
+
_err: StatusObject,
|
|
319
|
+
_retryCount: number,
|
|
320
|
+
): OnReconnectResult {
|
|
300
321
|
return {
|
|
301
322
|
reconnect: false,
|
|
302
|
-
}
|
|
323
|
+
};
|
|
303
324
|
}
|
|
304
325
|
|
|
305
326
|
/**
|
|
@@ -310,30 +331,30 @@ export function neverReconnect(_err: StatusObject, _retryCount: number): OnRecon
|
|
|
310
331
|
*/
|
|
311
332
|
export async function defaultOnReconnect(
|
|
312
333
|
err: StatusObject,
|
|
313
|
-
retryCount: number
|
|
334
|
+
retryCount: number,
|
|
314
335
|
): Promise<OnReconnectResult> {
|
|
315
|
-
if (err.code
|
|
336
|
+
if (err.code !== 13) {
|
|
316
337
|
return {
|
|
317
338
|
reconnect: false,
|
|
318
|
-
}
|
|
339
|
+
};
|
|
319
340
|
}
|
|
320
341
|
|
|
321
|
-
await new Promise((resolve) => setTimeout(resolve, retryCount * 1000))
|
|
342
|
+
await new Promise((resolve) => setTimeout(resolve, retryCount * 1000));
|
|
322
343
|
return {
|
|
323
344
|
reconnect: retryCount < 5,
|
|
324
|
-
}
|
|
345
|
+
};
|
|
325
346
|
}
|
|
326
347
|
|
|
327
348
|
/*
|
|
328
349
|
* Returns a generator that adds the given `token` to request metadata.
|
|
329
350
|
*/
|
|
330
351
|
function createMetadataGenerator(token?: string): CallMetadataGenerator {
|
|
331
|
-
const metadata = new Metadata()
|
|
352
|
+
const metadata = new Metadata();
|
|
332
353
|
if (token) {
|
|
333
|
-
metadata.add(
|
|
354
|
+
metadata.add("authorization", `bearer ${token}`);
|
|
334
355
|
}
|
|
335
356
|
|
|
336
357
|
return (_options, cb) => {
|
|
337
|
-
cb(null, metadata)
|
|
338
|
-
}
|
|
358
|
+
cb(null, metadata);
|
|
359
|
+
};
|
|
339
360
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Long from "long";
|
|
2
|
+
import { Cursor } from "./cursor";
|
|
3
|
+
|
|
4
|
+
describe("Cursor", () => {
|
|
5
|
+
it("can be converted to and from javascript objects", () => {
|
|
6
|
+
const cursorObject = {
|
|
7
|
+
orderKey: "1234",
|
|
8
|
+
uniqueKey:
|
|
9
|
+
"0x05dd5e4f023a81a8daaf86b8bf3967b04276a89c81b840e8e55d658323854ad7",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const cursor = Cursor.fromObject(cursorObject);
|
|
13
|
+
expect(cursor.orderKey).toEqual(Long.fromNumber(1234));
|
|
14
|
+
expect(cursor.uniqueKey).toHaveLength(32);
|
|
15
|
+
|
|
16
|
+
const back = Cursor.toObject(cursor);
|
|
17
|
+
|
|
18
|
+
expect(back?.orderKey).toEqual(cursorObject.orderKey);
|
|
19
|
+
expect(back?.uniqueKey).toEqual(cursorObject.uniqueKey);
|
|
20
|
+
});
|
|
21
|
+
});
|
package/src/cursor.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import Long from
|
|
2
|
-
import { ICursor } from
|
|
1
|
+
import Long from "long";
|
|
2
|
+
import { ICursor } from "./proto/v1alpha2";
|
|
3
3
|
|
|
4
4
|
export const Cursor = {
|
|
5
5
|
/**
|
|
@@ -12,7 +12,7 @@ export const Cursor = {
|
|
|
12
12
|
return {
|
|
13
13
|
orderKey: Long.fromValue(order),
|
|
14
14
|
uniqueKey: new Uint8Array(),
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
16
|
},
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -25,15 +25,43 @@ export const Cursor = {
|
|
|
25
25
|
return {
|
|
26
26
|
orderKey: Long.fromValue(order),
|
|
27
27
|
uniqueKey: unique,
|
|
28
|
-
}
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new cursor from a plain Javascript object.
|
|
33
|
+
*/
|
|
34
|
+
fromObject({ orderKey, uniqueKey }: ReturnType<typeof _toObject>): ICursor {
|
|
35
|
+
return {
|
|
36
|
+
orderKey: Long.fromString(orderKey),
|
|
37
|
+
uniqueKey: Buffer.from(uniqueKey.slice(2), "hex"),
|
|
38
|
+
};
|
|
29
39
|
},
|
|
30
40
|
|
|
31
41
|
/**
|
|
32
42
|
* Returns the cursor string representation.
|
|
33
43
|
*/
|
|
34
44
|
toString: (cursor?: ICursor | null): string | undefined => {
|
|
35
|
-
if (!cursor) return
|
|
36
|
-
|
|
37
|
-
return `${
|
|
45
|
+
if (!cursor) return;
|
|
46
|
+
const { orderKey, uniqueKey } = _toObject(cursor);
|
|
47
|
+
return `${orderKey}/${uniqueKey}`;
|
|
38
48
|
},
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Returns the cursor as plain Javascript object.
|
|
52
|
+
*/
|
|
53
|
+
toObject: (
|
|
54
|
+
cursor?: ICursor | null,
|
|
55
|
+
): ReturnType<typeof _toObject> | undefined => {
|
|
56
|
+
if (!cursor) return;
|
|
57
|
+
return _toObject(cursor);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
function _toObject(cursor: ICursor): { orderKey: string; uniqueKey: string } {
|
|
62
|
+
const hash = Buffer.from(cursor.uniqueKey).toString("hex");
|
|
63
|
+
return {
|
|
64
|
+
orderKey: cursor.orderKey.toString(),
|
|
65
|
+
uniqueKey: `0x${hash}`,
|
|
66
|
+
};
|
|
39
67
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from "./proto";
|
|
2
|
+
export * from "./client";
|
|
3
|
+
export * from "./request";
|
|
4
|
+
export * from "./cursor";
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// Original file: src/proto/stream.proto
|
|
2
2
|
|
|
3
3
|
import type { Cursor as _apibara_node_v1alpha2_Cursor, Cursor__Output as _apibara_node_v1alpha2_Cursor__Output } from '../../../apibara/node/v1alpha2/Cursor';
|
|
4
|
-
import type { DataFinality as _apibara_node_v1alpha2_DataFinality } from '../../../apibara/node/v1alpha2/DataFinality';
|
|
4
|
+
import type { DataFinality as _apibara_node_v1alpha2_DataFinality, DataFinality__Output as _apibara_node_v1alpha2_DataFinality__Output } from '../../../apibara/node/v1alpha2/DataFinality';
|
|
5
5
|
|
|
6
6
|
export interface Data {
|
|
7
7
|
'endCursor'?: (_apibara_node_v1alpha2_Cursor | null);
|
|
8
|
-
'finality'?: (_apibara_node_v1alpha2_DataFinality
|
|
8
|
+
'finality'?: (_apibara_node_v1alpha2_DataFinality);
|
|
9
9
|
'data'?: (Buffer | Uint8Array | string)[];
|
|
10
10
|
'cursor'?: (_apibara_node_v1alpha2_Cursor | null);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface Data__Output {
|
|
14
14
|
'endCursor': (_apibara_node_v1alpha2_Cursor__Output | null);
|
|
15
|
-
'finality': (
|
|
15
|
+
'finality': (_apibara_node_v1alpha2_DataFinality__Output);
|
|
16
16
|
'data': (Uint8Array)[];
|
|
17
17
|
'cursor': (_apibara_node_v1alpha2_Cursor__Output | null);
|
|
18
18
|
}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
// Original file: src/proto/stream.proto
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
DATA_STATUS_UNKNOWN
|
|
5
|
-
DATA_STATUS_PENDING
|
|
6
|
-
DATA_STATUS_ACCEPTED
|
|
7
|
-
DATA_STATUS_FINALIZED
|
|
8
|
-
}
|
|
3
|
+
export const DataFinality = {
|
|
4
|
+
DATA_STATUS_UNKNOWN: 'DATA_STATUS_UNKNOWN',
|
|
5
|
+
DATA_STATUS_PENDING: 'DATA_STATUS_PENDING',
|
|
6
|
+
DATA_STATUS_ACCEPTED: 'DATA_STATUS_ACCEPTED',
|
|
7
|
+
DATA_STATUS_FINALIZED: 'DATA_STATUS_FINALIZED',
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
export type DataFinality =
|
|
11
|
+
| 'DATA_STATUS_UNKNOWN'
|
|
12
|
+
| 0
|
|
13
|
+
| 'DATA_STATUS_PENDING'
|
|
14
|
+
| 1
|
|
15
|
+
| 'DATA_STATUS_ACCEPTED'
|
|
16
|
+
| 2
|
|
17
|
+
| 'DATA_STATUS_FINALIZED'
|
|
18
|
+
| 3
|
|
19
|
+
|
|
20
|
+
export type DataFinality__Output = typeof DataFinality[keyof typeof DataFinality]
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// Original file: src/proto/stream.proto
|
|
2
2
|
|
|
3
3
|
import type { Cursor as _apibara_node_v1alpha2_Cursor, Cursor__Output as _apibara_node_v1alpha2_Cursor__Output } from '../../../apibara/node/v1alpha2/Cursor';
|
|
4
|
-
import type { DataFinality as _apibara_node_v1alpha2_DataFinality } from '../../../apibara/node/v1alpha2/DataFinality';
|
|
4
|
+
import type { DataFinality as _apibara_node_v1alpha2_DataFinality, DataFinality__Output as _apibara_node_v1alpha2_DataFinality__Output } from '../../../apibara/node/v1alpha2/DataFinality';
|
|
5
5
|
import type { Long } from '@grpc/proto-loader';
|
|
6
6
|
|
|
7
7
|
export interface StreamDataRequest {
|
|
8
8
|
'streamId'?: (number | string | Long);
|
|
9
9
|
'batchSize'?: (number | string | Long);
|
|
10
10
|
'startingCursor'?: (_apibara_node_v1alpha2_Cursor | null);
|
|
11
|
-
'finality'?: (_apibara_node_v1alpha2_DataFinality
|
|
11
|
+
'finality'?: (_apibara_node_v1alpha2_DataFinality);
|
|
12
12
|
'filter'?: (Buffer | Uint8Array | string);
|
|
13
13
|
'_streamId'?: "streamId";
|
|
14
14
|
'_batchSize'?: "batchSize";
|
|
@@ -19,7 +19,7 @@ export interface StreamDataRequest__Output {
|
|
|
19
19
|
'streamId'?: (Long);
|
|
20
20
|
'batchSize'?: (Long);
|
|
21
21
|
'startingCursor': (_apibara_node_v1alpha2_Cursor__Output | null);
|
|
22
|
-
'finality'?: (
|
|
22
|
+
'finality'?: (_apibara_node_v1alpha2_DataFinality__Output);
|
|
23
23
|
'filter': (Uint8Array);
|
|
24
24
|
'_streamId': "streamId";
|
|
25
25
|
'_batchSize': "batchSize";
|
package/src/proto/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * as v1alpha2 from
|
|
1
|
+
export * as v1alpha2 from "./v1alpha2";
|
package/src/proto/testing.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Field, Message } from "protobufjs/light";
|
|
2
2
|
|
|
3
3
|
export class TestFilter extends Message<TestFilter> {
|
|
4
|
-
@Field.d(1,
|
|
4
|
+
@Field.d(1, "uint64")
|
|
5
5
|
// @ts-ignore
|
|
6
|
-
public num: number
|
|
6
|
+
public num: number;
|
|
7
7
|
|
|
8
|
-
@Field.d(2,
|
|
8
|
+
@Field.d(2, "string")
|
|
9
9
|
// @ts-ignore
|
|
10
|
-
public text: string
|
|
10
|
+
public text: string;
|
|
11
11
|
}
|
package/src/proto/v1alpha2.ts
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import { loadPackageDefinition } from
|
|
2
|
-
import { loadSync } from
|
|
3
|
-
import { ProtoGrpcType } from
|
|
1
|
+
import { loadPackageDefinition } from "@grpc/grpc-js";
|
|
2
|
+
import { loadSync } from "@grpc/proto-loader";
|
|
3
|
+
import { ProtoGrpcType } from "./stream";
|
|
4
4
|
|
|
5
|
-
const __NODE_PROTO_PATH = __dirname +
|
|
5
|
+
const __NODE_PROTO_PATH = __dirname + "/stream.proto";
|
|
6
6
|
|
|
7
7
|
// export definitions
|
|
8
8
|
export const packageDefinition = loadSync(__NODE_PROTO_PATH, {
|
|
9
9
|
oneofs: true,
|
|
10
10
|
defaults: true,
|
|
11
|
-
})
|
|
12
|
-
export const protoDescriptor = loadPackageDefinition(
|
|
11
|
+
});
|
|
12
|
+
export const protoDescriptor = loadPackageDefinition(
|
|
13
|
+
packageDefinition,
|
|
14
|
+
) as unknown as ProtoGrpcType;
|
|
13
15
|
|
|
14
16
|
// re-export all types, use same naming convention as protobufjs
|
|
15
|
-
export { Cursor__Output as ICursor } from
|
|
16
|
-
export { Data__Output as IData } from
|
|
17
|
-
export { DataFinality } from
|
|
18
|
-
export { Heartbeat__Output as IHeartbeat } from
|
|
19
|
-
export { Invalidate__Output as IInvalidate } from
|
|
20
|
-
export { StreamClient } from
|
|
21
|
-
export { StreamDataRequest as IStreamDataRequest } from
|
|
22
|
-
export { StreamDataResponse__Output as IStreamDataResponse } from
|
|
17
|
+
export { Cursor__Output as ICursor } from "./apibara/node/v1alpha2/Cursor";
|
|
18
|
+
export { Data__Output as IData } from "./apibara/node/v1alpha2/Data";
|
|
19
|
+
export { DataFinality } from "./apibara/node/v1alpha2/DataFinality";
|
|
20
|
+
export { Heartbeat__Output as IHeartbeat } from "./apibara/node/v1alpha2/Heartbeat";
|
|
21
|
+
export { Invalidate__Output as IInvalidate } from "./apibara/node/v1alpha2/Invalidate";
|
|
22
|
+
export { StreamClient } from "./apibara/node/v1alpha2/Stream";
|
|
23
|
+
export { StreamDataRequest as IStreamDataRequest } from "./apibara/node/v1alpha2/StreamDataRequest";
|
|
24
|
+
export { StreamDataResponse__Output as IStreamDataResponse } from "./apibara/node/v1alpha2/StreamDataResponse";
|