@secondlayer/sdk 5.8.0 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +104 -1
- package/dist/index.js +152 -6
- package/dist/index.js.map +8 -7
- package/dist/streams/index.d.ts +104 -1
- package/dist/streams/index.js +152 -6
- package/dist/streams/index.js.map +8 -7
- package/dist/subgraphs/index.d.ts +85 -0
- package/dist/subgraphs/index.js +151 -6
- package/dist/subgraphs/index.js.map +7 -6
- package/package.json +2 -2
package/dist/streams/index.d.ts
CHANGED
|
@@ -13,11 +13,21 @@ type StreamsEvent = {
|
|
|
13
13
|
contract_id: string | null
|
|
14
14
|
payload: StreamsEventPayload
|
|
15
15
|
ts: string
|
|
16
|
+
/**
|
|
17
|
+
* True when this event's block is past the finality boundary (immutable).
|
|
18
|
+
* Optional for back-compat; the API always sets it on Streams responses.
|
|
19
|
+
*/
|
|
20
|
+
finalized?: boolean
|
|
16
21
|
};
|
|
17
22
|
type StreamsTip = {
|
|
18
23
|
block_height: number
|
|
19
24
|
block_hash: string
|
|
20
25
|
burn_block_height: number
|
|
26
|
+
/**
|
|
27
|
+
* Highest Stacks block past the burn-confirmation finality boundary.
|
|
28
|
+
* Optional for back-compat; the API always sets it.
|
|
29
|
+
*/
|
|
30
|
+
finalized_height?: number
|
|
21
31
|
lag_seconds: number
|
|
22
32
|
};
|
|
23
33
|
type StreamsCanonicalBlock = {
|
|
@@ -57,12 +67,18 @@ type StreamsEventsListParams = {
|
|
|
57
67
|
toHeight?: number
|
|
58
68
|
types?: readonly StreamsEventType[]
|
|
59
69
|
contractId?: string
|
|
70
|
+
sender?: string
|
|
71
|
+
recipient?: string
|
|
72
|
+
assetIdentifier?: string
|
|
60
73
|
limit?: number
|
|
61
74
|
};
|
|
62
75
|
type StreamsEventsStreamParams = {
|
|
63
76
|
fromCursor?: string | null
|
|
64
77
|
types?: readonly StreamsEventType[]
|
|
65
78
|
contractId?: string
|
|
79
|
+
sender?: string
|
|
80
|
+
recipient?: string
|
|
81
|
+
assetIdentifier?: string
|
|
66
82
|
batchSize?: number
|
|
67
83
|
emptyBackoffMs?: number
|
|
68
84
|
maxPages?: number
|
|
@@ -74,6 +90,9 @@ type StreamsEventsConsumeParams = {
|
|
|
74
90
|
mode?: "tail" | "bounded"
|
|
75
91
|
types?: readonly StreamsEventType[]
|
|
76
92
|
contractId?: string
|
|
93
|
+
sender?: string
|
|
94
|
+
recipient?: string
|
|
95
|
+
assetIdentifier?: string
|
|
77
96
|
batchSize?: number
|
|
78
97
|
onBatch: (events: StreamsEvent[], envelope: StreamsEventsEnvelope) => Promise<string | null | undefined> | string | null | undefined
|
|
79
98
|
emptyBackoffMs?: number
|
|
@@ -86,7 +105,63 @@ type StreamsEventsConsumeResult = {
|
|
|
86
105
|
pages: number
|
|
87
106
|
emptyPolls: number
|
|
88
107
|
};
|
|
108
|
+
type StreamsEventsReplayParams = {
|
|
109
|
+
/** Start point: `"genesis"` (default) or a `<block>:<index>` cursor. */
|
|
110
|
+
from?: "genesis" | string
|
|
111
|
+
/**
|
|
112
|
+
* Called once per finalized dump file, in block order, before live tailing.
|
|
113
|
+
* Process the parquet with your own tooling (e.g. DuckDB) — the SDK does not
|
|
114
|
+
* decode parquet. Use `client.dumps.download(file)` to fetch + verify bytes.
|
|
115
|
+
*/
|
|
116
|
+
onDumpFile: (file: StreamsDumpFile) => Promise<void> | void
|
|
117
|
+
/** Called per live page after the dump phase, like `consume`. */
|
|
118
|
+
onBatch: (events: StreamsEvent[], envelope: StreamsEventsEnvelope) => Promise<string | null | undefined> | string | null | undefined
|
|
119
|
+
mode?: "tail" | "bounded"
|
|
120
|
+
batchSize?: number
|
|
121
|
+
emptyBackoffMs?: number
|
|
122
|
+
maxPages?: number
|
|
123
|
+
maxEmptyPolls?: number
|
|
124
|
+
signal?: AbortSignal
|
|
125
|
+
};
|
|
89
126
|
type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
127
|
+
/** One bulk parquet file in the dumps manifest. `path` is the object key under
|
|
128
|
+
* the dumps base URL. */
|
|
129
|
+
type StreamsDumpFile = {
|
|
130
|
+
path: string
|
|
131
|
+
from_block: number
|
|
132
|
+
to_block: number
|
|
133
|
+
min_cursor: string | null
|
|
134
|
+
max_cursor: string | null
|
|
135
|
+
row_count: number
|
|
136
|
+
byte_size: number
|
|
137
|
+
sha256: string
|
|
138
|
+
schema_version: number
|
|
139
|
+
created_at: string
|
|
140
|
+
};
|
|
141
|
+
type StreamsDumpsManifest = {
|
|
142
|
+
dataset: string
|
|
143
|
+
network: string
|
|
144
|
+
version: string
|
|
145
|
+
schema_version: number
|
|
146
|
+
generated_at: string
|
|
147
|
+
producer_version: string
|
|
148
|
+
finality_lag_blocks: number
|
|
149
|
+
/** Cursor at the end of the finalized bulk coverage — hand to live tailing. */
|
|
150
|
+
latest_finalized_cursor: string | null
|
|
151
|
+
coverage: {
|
|
152
|
+
from_block: number
|
|
153
|
+
to_block: number
|
|
154
|
+
}
|
|
155
|
+
files: StreamsDumpFile[]
|
|
156
|
+
};
|
|
157
|
+
type StreamsDumps = {
|
|
158
|
+
/** Fetch and parse the latest dumps manifest. */
|
|
159
|
+
list(): Promise<StreamsDumpsManifest>
|
|
160
|
+
/** Absolute URL for a manifest file. */
|
|
161
|
+
fileUrl(file: StreamsDumpFile): string
|
|
162
|
+
/** Download a parquet file and verify its sha256 against the manifest. */
|
|
163
|
+
download(file: StreamsDumpFile): Promise<Uint8Array>
|
|
164
|
+
};
|
|
90
165
|
type StreamsClient = {
|
|
91
166
|
events: {
|
|
92
167
|
list(params?: StreamsEventsListParams): Promise<StreamsEventsEnvelope>
|
|
@@ -102,6 +177,14 @@ type StreamsClient = {
|
|
|
102
177
|
*/
|
|
103
178
|
consume(params: StreamsEventsConsumeParams): Promise<StreamsEventsConsumeResult>
|
|
104
179
|
/**
|
|
180
|
+
* Backfill from bulk dumps, then continue live from the dump→live seam in
|
|
181
|
+
* one call. Iterates finalized dump files (via `onDumpFile`) in block
|
|
182
|
+
* order, then tails live from the manifest's `latest_finalized_cursor`
|
|
183
|
+
* (exclusive input → no gap or duplicate at the seam). Requires
|
|
184
|
+
* `dumpsBaseUrl`.
|
|
185
|
+
*/
|
|
186
|
+
replay(params: StreamsEventsReplayParams): Promise<StreamsEventsConsumeResult>
|
|
187
|
+
/**
|
|
105
188
|
* Follow Streams as an async iterator.
|
|
106
189
|
*
|
|
107
190
|
* Use `stream` for live processors and watch-style apps. It tails
|
|
@@ -116,6 +199,8 @@ type StreamsClient = {
|
|
|
116
199
|
reorgs: {
|
|
117
200
|
list(params: StreamsReorgsListParams): Promise<StreamsReorgsListEnvelope>
|
|
118
201
|
}
|
|
202
|
+
/** Bulk parquet dumps. Requires `dumpsBaseUrl` on the client. */
|
|
203
|
+
dumps: StreamsDumps
|
|
119
204
|
canonical(height: number): Promise<StreamsCanonicalBlock>
|
|
120
205
|
tip(): Promise<StreamsTip>
|
|
121
206
|
};
|
|
@@ -123,6 +208,20 @@ type CreateStreamsClientOptions = {
|
|
|
123
208
|
apiKey: string
|
|
124
209
|
baseUrl?: string
|
|
125
210
|
fetchImpl?: FetchLike
|
|
211
|
+
/**
|
|
212
|
+
* Public base URL for bulk parquet dumps (the R2/CDN bucket root). Required
|
|
213
|
+
* to use `client.dumps`. See `GET /public/streams/dumps/manifest`.
|
|
214
|
+
*/
|
|
215
|
+
dumpsBaseUrl?: string
|
|
216
|
+
/**
|
|
217
|
+
* Verify the ed25519 `X-Signature` on every response (default off). Pass
|
|
218
|
+
* `true` to fetch the server's public key from
|
|
219
|
+
* `/public/streams/signing-key`, or `{ publicKey }` to pin a known PEM. A
|
|
220
|
+
* failed or missing signature throws `StreamsSignatureError`.
|
|
221
|
+
*/
|
|
222
|
+
verify?: boolean | {
|
|
223
|
+
publicKey: string
|
|
224
|
+
}
|
|
126
225
|
};
|
|
127
226
|
declare function createStreamsClient(options: CreateStreamsClientOptions): StreamsClient;
|
|
128
227
|
declare class AuthError extends Error {
|
|
@@ -144,6 +243,10 @@ declare class StreamsServerError extends Error {
|
|
|
144
243
|
readonly body?: unknown;
|
|
145
244
|
constructor(message: string, status: number, body?: unknown);
|
|
146
245
|
}
|
|
246
|
+
/** Thrown when response signature verification is enabled and fails. */
|
|
247
|
+
declare class StreamsSignatureError extends Error {
|
|
248
|
+
constructor(message?: string);
|
|
249
|
+
}
|
|
147
250
|
type FtTransferPayload = {
|
|
148
251
|
asset_identifier: string
|
|
149
252
|
sender: string
|
|
@@ -410,4 +513,4 @@ type DecodedEventColumns = {
|
|
|
410
513
|
payload?: unknown
|
|
411
514
|
};
|
|
412
515
|
type DecodedEventRow = DecodedFtTransfer | DecodedNftTransfer | DecodedStxTransfer | DecodedStxMint | DecodedStxBurn | DecodedStxLock | DecodedFtMint | DecodedFtBurn | DecodedNftMint | DecodedNftBurn | DecodedPrint;
|
|
413
|
-
export { isStxTransfer, isStxMint, isStxLock, isStxBurn, isPrint, isNftTransfer, isNftMint, isNftBurn, isFtTransfer, isFtMint, isFtBurn, decodeStxTransfer, decodeStxMint, decodeStxLock, decodeStxBurn, decodePrint, decodeNftTransfer, decodeNftMint, decodeNftBurn, decodeFtTransfer, decodeFtMint, decodeFtBurn, createStreamsClient, ValidationError, StreamsTip, StreamsServerError, StreamsReorgsListParams, StreamsReorgsListEnvelope, StreamsReorg, StreamsEventsStreamParams, StreamsEventsListParams, StreamsEventsListEnvelope, StreamsEventsEnvelope, StreamsEventsConsumeResult, StreamsEventsConsumeParams, StreamsEventType, StreamsEventPayload, StreamsEvent, StreamsClient, StreamsCanonicalBlock, STREAMS_EVENT_TYPES, RateLimitError, NftTransferPayload, NftTransferEvent, FtTransferPayload, FtTransferEvent, FetchLike, DecodedStxTransferPayload, DecodedStxTransfer, DecodedStxMintPayload, DecodedStxMint, DecodedStxLockPayload, DecodedStxLock, DecodedStxBurnPayload, DecodedStxBurn, DecodedPrintValue, DecodedPrintPayload, DecodedPrint, DecodedNftTransferPayload, DecodedNftTransfer, DecodedNftMintPayload, DecodedNftMint, DecodedNftBurnPayload, DecodedNftBurn, DecodedFtTransferPayload, DecodedFtTransfer, DecodedFtMintPayload, DecodedFtMint, DecodedFtBurnPayload, DecodedFtBurn, DecodedEventRow, DecodedEventColumns, AuthError };
|
|
516
|
+
export { isStxTransfer, isStxMint, isStxLock, isStxBurn, isPrint, isNftTransfer, isNftMint, isNftBurn, isFtTransfer, isFtMint, isFtBurn, decodeStxTransfer, decodeStxMint, decodeStxLock, decodeStxBurn, decodePrint, decodeNftTransfer, decodeNftMint, decodeNftBurn, decodeFtTransfer, decodeFtMint, decodeFtBurn, createStreamsClient, ValidationError, StreamsTip, StreamsSignatureError, StreamsServerError, StreamsReorgsListParams, StreamsReorgsListEnvelope, StreamsReorg, StreamsEventsStreamParams, StreamsEventsListParams, StreamsEventsListEnvelope, StreamsEventsEnvelope, StreamsEventsConsumeResult, StreamsEventsConsumeParams, StreamsEventType, StreamsEventPayload, StreamsEvent, StreamsDumpsManifest, StreamsDumps, StreamsDumpFile, StreamsClient, StreamsCanonicalBlock, STREAMS_EVENT_TYPES, RateLimitError, NftTransferPayload, NftTransferEvent, FtTransferPayload, FtTransferEvent, FetchLike, DecodedStxTransferPayload, DecodedStxTransfer, DecodedStxMintPayload, DecodedStxMint, DecodedStxLockPayload, DecodedStxLock, DecodedStxBurnPayload, DecodedStxBurn, DecodedPrintValue, DecodedPrintPayload, DecodedPrint, DecodedNftTransferPayload, DecodedNftTransfer, DecodedNftMintPayload, DecodedNftMint, DecodedNftBurnPayload, DecodedNftBurn, DecodedFtTransferPayload, DecodedFtTransfer, DecodedFtMintPayload, DecodedFtMint, DecodedFtBurnPayload, DecodedFtBurn, DecodedEventRow, DecodedEventColumns, AuthError };
|
package/dist/streams/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/streams/client.ts
|
|
2
|
+
import { ed25519 } from "@secondlayer/shared";
|
|
3
|
+
|
|
1
4
|
// src/streams/consumer.ts
|
|
2
5
|
async function defaultSleep(ms, signal) {
|
|
3
6
|
if (signal?.aborted)
|
|
@@ -26,7 +29,10 @@ async function consumeStreamsEvents(opts) {
|
|
|
26
29
|
cursor,
|
|
27
30
|
limit: opts.batchSize,
|
|
28
31
|
types: opts.types,
|
|
29
|
-
contractId: opts.contractId
|
|
32
|
+
contractId: opts.contractId,
|
|
33
|
+
sender: opts.sender,
|
|
34
|
+
recipient: opts.recipient,
|
|
35
|
+
assetIdentifier: opts.assetIdentifier
|
|
30
36
|
});
|
|
31
37
|
pages++;
|
|
32
38
|
const returnedCursor = await opts.onBatch(envelope.events, envelope);
|
|
@@ -61,7 +67,10 @@ async function* streamStreamsEvents(opts) {
|
|
|
61
67
|
cursor,
|
|
62
68
|
limit: opts.batchSize,
|
|
63
69
|
types: opts.types,
|
|
64
|
-
contractId: opts.contractId
|
|
70
|
+
contractId: opts.contractId,
|
|
71
|
+
sender: opts.sender,
|
|
72
|
+
recipient: opts.recipient,
|
|
73
|
+
assetIdentifier: opts.assetIdentifier
|
|
65
74
|
});
|
|
66
75
|
pages++;
|
|
67
76
|
for (const event of envelope.events) {
|
|
@@ -86,6 +95,9 @@ async function* streamStreamsEvents(opts) {
|
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
|
|
98
|
+
// src/streams/dumps.ts
|
|
99
|
+
import { createHash } from "node:crypto";
|
|
100
|
+
|
|
89
101
|
// src/streams/errors.ts
|
|
90
102
|
class AuthError extends Error {
|
|
91
103
|
status = 401;
|
|
@@ -127,7 +139,60 @@ class StreamsServerError extends Error {
|
|
|
127
139
|
}
|
|
128
140
|
}
|
|
129
141
|
|
|
142
|
+
class StreamsSignatureError extends Error {
|
|
143
|
+
constructor(message = "Streams response signature verification failed.") {
|
|
144
|
+
super(message);
|
|
145
|
+
this.name = "StreamsSignatureError";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/streams/dumps.ts
|
|
150
|
+
function createStreamsDumps(opts) {
|
|
151
|
+
const baseUrl = opts.baseUrl?.replace(/\/+$/, "");
|
|
152
|
+
function requireBaseUrl() {
|
|
153
|
+
if (!baseUrl) {
|
|
154
|
+
throw new StreamsServerError("Streams dumps require `dumpsBaseUrl` on createStreamsClient.", 0);
|
|
155
|
+
}
|
|
156
|
+
return baseUrl;
|
|
157
|
+
}
|
|
158
|
+
function fileUrl(file) {
|
|
159
|
+
return `${requireBaseUrl()}/${file.path.replace(/^\/+/, "")}`;
|
|
160
|
+
}
|
|
161
|
+
async function list() {
|
|
162
|
+
const url = `${requireBaseUrl()}/manifest/latest.json`;
|
|
163
|
+
const res = await opts.fetchImpl(url);
|
|
164
|
+
if (!res.ok) {
|
|
165
|
+
throw new StreamsServerError(`Could not fetch dumps manifest (${res.status}).`, res.status);
|
|
166
|
+
}
|
|
167
|
+
return await res.json();
|
|
168
|
+
}
|
|
169
|
+
async function download(file) {
|
|
170
|
+
const res = await opts.fetchImpl(fileUrl(file));
|
|
171
|
+
if (!res.ok) {
|
|
172
|
+
throw new StreamsServerError(`Could not download dump ${file.path} (${res.status}).`, res.status);
|
|
173
|
+
}
|
|
174
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
175
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
176
|
+
if (digest !== file.sha256) {
|
|
177
|
+
throw new StreamsSignatureError(`Dump ${file.path} sha256 mismatch (expected ${file.sha256}, got ${digest}).`);
|
|
178
|
+
}
|
|
179
|
+
return bytes;
|
|
180
|
+
}
|
|
181
|
+
return { list, fileUrl, download };
|
|
182
|
+
}
|
|
183
|
+
|
|
130
184
|
// src/streams/client.ts
|
|
185
|
+
function cursorTuple(cursor) {
|
|
186
|
+
if (!cursor)
|
|
187
|
+
return [-1, -1];
|
|
188
|
+
const [block, index] = cursor.split(":");
|
|
189
|
+
return [Number(block), Number(index)];
|
|
190
|
+
}
|
|
191
|
+
function maxCursor(a, b) {
|
|
192
|
+
const [ah, ai] = cursorTuple(a);
|
|
193
|
+
const [bh, bi] = cursorTuple(b);
|
|
194
|
+
return ah > bh || ah === bh && ai >= bi ? a : b;
|
|
195
|
+
}
|
|
131
196
|
var DEFAULT_STREAMS_BASE_URL = "https://api.secondlayer.tools";
|
|
132
197
|
function normalizeBaseUrl(baseUrl) {
|
|
133
198
|
return baseUrl.replace(/\/+$/, "");
|
|
@@ -175,21 +240,68 @@ async function mapStreamsError(response) {
|
|
|
175
240
|
function createStreamsClient(options) {
|
|
176
241
|
const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_STREAMS_BASE_URL);
|
|
177
242
|
const fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));
|
|
243
|
+
const verify = options.verify ?? false;
|
|
244
|
+
const dumps = createStreamsDumps({
|
|
245
|
+
baseUrl: options.dumpsBaseUrl,
|
|
246
|
+
fetchImpl
|
|
247
|
+
});
|
|
248
|
+
let publicKeyPromise = null;
|
|
249
|
+
function getPublicKey() {
|
|
250
|
+
if (publicKeyPromise)
|
|
251
|
+
return publicKeyPromise;
|
|
252
|
+
publicKeyPromise = (async () => {
|
|
253
|
+
if (typeof verify === "object") {
|
|
254
|
+
return ed25519.loadEd25519PublicKey(verify.publicKey);
|
|
255
|
+
}
|
|
256
|
+
const res = await fetchImpl(`${baseUrl}/public/streams/signing-key`);
|
|
257
|
+
if (!res.ok) {
|
|
258
|
+
throw new StreamsSignatureError(`Could not fetch signing key (${res.status}).`);
|
|
259
|
+
}
|
|
260
|
+
const body = await res.json();
|
|
261
|
+
if (!body.public_key_pem) {
|
|
262
|
+
throw new StreamsSignatureError("Signing key response missing key.");
|
|
263
|
+
}
|
|
264
|
+
return ed25519.loadEd25519PublicKey(body.public_key_pem);
|
|
265
|
+
})();
|
|
266
|
+
return publicKeyPromise;
|
|
267
|
+
}
|
|
178
268
|
async function request(path) {
|
|
179
269
|
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
180
270
|
headers: { Authorization: `Bearer ${options.apiKey}` }
|
|
181
271
|
});
|
|
182
272
|
if (!response.ok)
|
|
183
273
|
await mapStreamsError(response);
|
|
184
|
-
|
|
274
|
+
const text = await response.text();
|
|
275
|
+
if (verify) {
|
|
276
|
+
const signature = response.headers.get("X-Signature");
|
|
277
|
+
if (!signature) {
|
|
278
|
+
throw new StreamsSignatureError("Response is missing X-Signature.");
|
|
279
|
+
}
|
|
280
|
+
const publicKey = await getPublicKey();
|
|
281
|
+
if (!ed25519.verifyEd25519(text, signature, publicKey)) {
|
|
282
|
+
throw new StreamsSignatureError;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return JSON.parse(text);
|
|
185
286
|
}
|
|
186
287
|
const fetchEvents = async ({
|
|
187
288
|
cursor,
|
|
188
289
|
limit,
|
|
189
290
|
types,
|
|
190
|
-
contractId
|
|
291
|
+
contractId,
|
|
292
|
+
sender,
|
|
293
|
+
recipient,
|
|
294
|
+
assetIdentifier
|
|
191
295
|
}) => {
|
|
192
|
-
return listEvents({
|
|
296
|
+
return listEvents({
|
|
297
|
+
cursor,
|
|
298
|
+
limit,
|
|
299
|
+
types,
|
|
300
|
+
contractId,
|
|
301
|
+
sender,
|
|
302
|
+
recipient,
|
|
303
|
+
assetIdentifier
|
|
304
|
+
});
|
|
193
305
|
};
|
|
194
306
|
async function listEvents(params = {}) {
|
|
195
307
|
const searchParams = new URLSearchParams;
|
|
@@ -198,6 +310,9 @@ function createStreamsClient(options) {
|
|
|
198
310
|
appendSearchParam(searchParams, "to_height", params.toHeight);
|
|
199
311
|
appendSearchParam(searchParams, "limit", params.limit);
|
|
200
312
|
appendSearchParam(searchParams, "contract_id", params.contractId);
|
|
313
|
+
appendSearchParam(searchParams, "sender", params.sender);
|
|
314
|
+
appendSearchParam(searchParams, "recipient", params.recipient);
|
|
315
|
+
appendSearchParam(searchParams, "asset_identifier", params.assetIdentifier);
|
|
201
316
|
if (params.types?.length) {
|
|
202
317
|
searchParams.set("types", params.types.join(","));
|
|
203
318
|
}
|
|
@@ -216,6 +331,9 @@ function createStreamsClient(options) {
|
|
|
216
331
|
mode: params.mode,
|
|
217
332
|
types: params.types,
|
|
218
333
|
contractId: params.contractId,
|
|
334
|
+
sender: params.sender,
|
|
335
|
+
recipient: params.recipient,
|
|
336
|
+
assetIdentifier: params.assetIdentifier,
|
|
219
337
|
batchSize: params.batchSize ?? 100,
|
|
220
338
|
fetchEvents,
|
|
221
339
|
onBatch: params.onBatch,
|
|
@@ -230,6 +348,9 @@ function createStreamsClient(options) {
|
|
|
230
348
|
fromCursor: params.fromCursor,
|
|
231
349
|
types: params.types,
|
|
232
350
|
contractId: params.contractId,
|
|
351
|
+
sender: params.sender,
|
|
352
|
+
recipient: params.recipient,
|
|
353
|
+
assetIdentifier: params.assetIdentifier,
|
|
233
354
|
batchSize: params.batchSize ?? 100,
|
|
234
355
|
emptyBackoffMs: params.emptyBackoffMs,
|
|
235
356
|
maxPages: params.maxPages,
|
|
@@ -237,6 +358,29 @@ function createStreamsClient(options) {
|
|
|
237
358
|
signal: params.signal,
|
|
238
359
|
fetchEvents
|
|
239
360
|
});
|
|
361
|
+
},
|
|
362
|
+
async replay(params) {
|
|
363
|
+
const fromCursor = params.from === "genesis" ? null : params.from ?? null;
|
|
364
|
+
const fromBlock = fromCursor ? cursorTuple(fromCursor)[0] : 0;
|
|
365
|
+
const manifest = await dumps.list();
|
|
366
|
+
const files = manifest.files.filter((file) => file.to_block >= fromBlock).sort((a, b) => a.from_block - b.from_block || a.to_block - b.to_block);
|
|
367
|
+
for (const file of files) {
|
|
368
|
+
if (params.signal?.aborted)
|
|
369
|
+
break;
|
|
370
|
+
await params.onDumpFile(file);
|
|
371
|
+
}
|
|
372
|
+
const seam = maxCursor(fromCursor, manifest.latest_finalized_cursor);
|
|
373
|
+
return consumeStreamsEvents({
|
|
374
|
+
fromCursor: seam,
|
|
375
|
+
mode: params.mode ?? "tail",
|
|
376
|
+
batchSize: params.batchSize ?? 100,
|
|
377
|
+
fetchEvents,
|
|
378
|
+
onBatch: params.onBatch,
|
|
379
|
+
emptyBackoffMs: params.emptyBackoffMs,
|
|
380
|
+
maxPages: params.maxPages,
|
|
381
|
+
maxEmptyPolls: params.maxEmptyPolls,
|
|
382
|
+
signal: params.signal
|
|
383
|
+
});
|
|
240
384
|
}
|
|
241
385
|
},
|
|
242
386
|
blocks: {
|
|
@@ -253,6 +397,7 @@ function createStreamsClient(options) {
|
|
|
253
397
|
return request(`/v1/streams/reorgs${query ? `?${query}` : ""}`);
|
|
254
398
|
}
|
|
255
399
|
},
|
|
400
|
+
dumps,
|
|
256
401
|
canonical(height) {
|
|
257
402
|
return request(`/v1/streams/canonical/${height}`);
|
|
258
403
|
},
|
|
@@ -652,11 +797,12 @@ export {
|
|
|
652
797
|
decodeFtBurn,
|
|
653
798
|
createStreamsClient,
|
|
654
799
|
ValidationError,
|
|
800
|
+
StreamsSignatureError,
|
|
655
801
|
StreamsServerError,
|
|
656
802
|
STREAMS_EVENT_TYPES,
|
|
657
803
|
RateLimitError,
|
|
658
804
|
AuthError
|
|
659
805
|
};
|
|
660
806
|
|
|
661
|
-
//# debugId=
|
|
807
|
+
//# debugId=AC24B4EAD103932F64756E2164756E21
|
|
662
808
|
//# sourceMappingURL=index.js.map
|