@secondlayer/sdk 3.3.2 → 3.5.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.
@@ -2,11 +2,14 @@ import { ReindexResponse, SubgraphDetail, SubgraphGapsResponse, SubgraphQueryPar
2
2
  import { DeploySubgraphRequest, DeploySubgraphResponse } from "@secondlayer/shared/schemas/subgraphs";
3
3
  import { SubgraphAgentSchema, SubgraphSpecOptions } from "@secondlayer/shared/subgraphs/spec";
4
4
  import { InferSubgraphClient } from "@secondlayer/subgraphs";
5
+ type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
5
6
  interface SecondLayerOptions {
6
7
  /** Base URL of the Secondlayer API (trailing slashes are stripped). */
7
8
  baseUrl: string;
8
9
  /** Bearer token for authenticated requests. */
9
10
  apiKey?: string;
11
+ /** Fetch implementation. Tests and edge runtimes can provide their own. */
12
+ fetchImpl?: FetchLike;
10
13
  /** Deploy origin label sent as `x-sl-origin` (telemetry). Defaults to `cli`. */
11
14
  origin?: "cli" | "mcp" | "session";
12
15
  }
@@ -102,6 +105,210 @@ declare class Subgraphs extends BaseClient {
102
105
  private createTableClient;
103
106
  }
104
107
  import { InferSubgraphClient as InferSubgraphClient2 } from "@secondlayer/subgraphs";
108
+ type IndexTip = {
109
+ block_height: number
110
+ lag_seconds: number
111
+ };
112
+ type FtTransfer = {
113
+ cursor: string
114
+ block_height: number
115
+ tx_id: string
116
+ tx_index: number
117
+ event_index: number
118
+ event_type: "ft_transfer"
119
+ contract_id: string
120
+ asset_identifier: string
121
+ sender: string
122
+ recipient: string
123
+ amount: string
124
+ };
125
+ type FtTransfersEnvelope = {
126
+ events: FtTransfer[]
127
+ next_cursor: string | null
128
+ tip: IndexTip
129
+ reorgs: never[]
130
+ };
131
+ type FtTransfersListParams = {
132
+ cursor?: string | null
133
+ fromCursor?: string | null
134
+ limit?: number
135
+ contractId?: string
136
+ sender?: string
137
+ recipient?: string
138
+ fromHeight?: number
139
+ toHeight?: number
140
+ };
141
+ type FtTransfersWalkParams = Omit<FtTransfersListParams, "limit"> & {
142
+ batchSize?: number
143
+ signal?: AbortSignal
144
+ };
145
+ type NftTransfer = {
146
+ cursor: string
147
+ block_height: number
148
+ tx_id: string
149
+ tx_index: number
150
+ event_index: number
151
+ event_type: "nft_transfer"
152
+ contract_id: string
153
+ asset_identifier: string
154
+ sender: string
155
+ recipient: string
156
+ value: string
157
+ };
158
+ type NftTransfersEnvelope = {
159
+ events: NftTransfer[]
160
+ next_cursor: string | null
161
+ tip: IndexTip
162
+ reorgs: never[]
163
+ };
164
+ type NftTransfersListParams = {
165
+ cursor?: string | null
166
+ fromCursor?: string | null
167
+ limit?: number
168
+ contractId?: string
169
+ assetIdentifier?: string
170
+ sender?: string
171
+ recipient?: string
172
+ fromHeight?: number
173
+ toHeight?: number
174
+ };
175
+ type NftTransfersWalkParams = Omit<NftTransfersListParams, "limit"> & {
176
+ batchSize?: number
177
+ signal?: AbortSignal
178
+ };
179
+ declare class Index extends BaseClient {
180
+ constructor(options?: Partial<SecondLayerOptions>);
181
+ readonly ftTransfers: {
182
+ list: (params?: FtTransfersListParams) => Promise<FtTransfersEnvelope>
183
+ walk: (params?: FtTransfersWalkParams) => AsyncIterable<FtTransfer>
184
+ };
185
+ readonly nftTransfers: {
186
+ list: (params?: NftTransfersListParams) => Promise<NftTransfersEnvelope>
187
+ walk: (params?: NftTransfersWalkParams) => AsyncIterable<NftTransfer>
188
+ };
189
+ private listFtTransfers;
190
+ private listNftTransfers;
191
+ private walkFtTransfers;
192
+ private walkNftTransfers;
193
+ }
194
+ declare const STREAMS_EVENT_TYPES: readonly ["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", "ft_burn", "nft_transfer", "nft_mint", "nft_burn", "print"];
195
+ type StreamsEventType = (typeof STREAMS_EVENT_TYPES)[number];
196
+ type StreamsEventPayload = Record<string, unknown>;
197
+ type StreamsEvent = {
198
+ cursor: string
199
+ block_height: number
200
+ index_block_hash: string
201
+ burn_block_height: number
202
+ tx_id: string
203
+ tx_index: number
204
+ event_index: number
205
+ event_type: StreamsEventType
206
+ contract_id: string | null
207
+ payload: StreamsEventPayload
208
+ ts: string
209
+ };
210
+ type StreamsTip = {
211
+ block_height: number
212
+ index_block_hash: string
213
+ burn_block_height: number
214
+ lag_seconds: number
215
+ };
216
+ type StreamsCanonicalBlock = {
217
+ block_height: number
218
+ index_block_hash: string
219
+ burn_block_height: number
220
+ burn_block_hash: string | null
221
+ is_canonical: true
222
+ };
223
+ type StreamsReorg = {
224
+ detected_at: string
225
+ fork_point_height: number
226
+ orphaned_range: {
227
+ from: string
228
+ to: string
229
+ }
230
+ new_canonical_tip: string
231
+ };
232
+ type StreamsEventsEnvelope = {
233
+ events: StreamsEvent[]
234
+ next_cursor: string | null
235
+ tip: StreamsTip
236
+ reorgs: StreamsReorg[]
237
+ };
238
+ type StreamsEventsListEnvelope = Omit<StreamsEventsEnvelope, "next_cursor">;
239
+ type StreamsReorgsListParams = {
240
+ since: string
241
+ limit?: number
242
+ };
243
+ type StreamsReorgsListEnvelope = {
244
+ reorgs: StreamsReorg[]
245
+ next_since: string | null
246
+ };
247
+ type StreamsEventsListParams = {
248
+ cursor?: string | null
249
+ fromHeight?: number
250
+ toHeight?: number
251
+ types?: readonly StreamsEventType[]
252
+ contractId?: string
253
+ limit?: number
254
+ };
255
+ type StreamsEventsStreamParams = {
256
+ fromCursor?: string | null
257
+ types?: readonly StreamsEventType[]
258
+ batchSize?: number
259
+ emptyBackoffMs?: number
260
+ maxPages?: number
261
+ maxEmptyPolls?: number
262
+ signal?: AbortSignal
263
+ };
264
+ type StreamsEventsConsumeParams = {
265
+ fromCursor?: string | null
266
+ mode?: "tail" | "bounded"
267
+ types?: readonly StreamsEventType[]
268
+ batchSize?: number
269
+ onBatch: (events: StreamsEvent[], envelope: StreamsEventsEnvelope) => Promise<string | null | undefined> | string | null | undefined
270
+ emptyBackoffMs?: number
271
+ maxPages?: number
272
+ maxEmptyPolls?: number
273
+ signal?: AbortSignal
274
+ };
275
+ type StreamsEventsConsumeResult = {
276
+ cursor: string | null
277
+ pages: number
278
+ emptyPolls: number
279
+ };
280
+ type StreamsClient = {
281
+ events: {
282
+ list(params?: StreamsEventsListParams): Promise<StreamsEventsEnvelope>
283
+ byTxId(txId: string): Promise<StreamsEventsListEnvelope>
284
+ /**
285
+ * Pull pages from Streams and call `onBatch` after each page.
286
+ *
287
+ * Use `consume` for indexers and ETL jobs that own checkpointing. Return
288
+ * the checkpoint cursor from `onBatch`. Default `mode: "tail"` keeps
289
+ * polling when caught up; `mode: "bounded"` exits on the first empty page.
290
+ * The consumer also exits when `maxPages`, `maxEmptyPolls`, or `signal`
291
+ * stops it.
292
+ */
293
+ consume(params: StreamsEventsConsumeParams): Promise<StreamsEventsConsumeResult>
294
+ /**
295
+ * Follow Streams as an async iterator.
296
+ *
297
+ * Use `stream` for live processors and watch-style apps. It tails
298
+ * indefinitely by default and stops when its `AbortSignal`, `maxPages`, or
299
+ * `maxEmptyPolls` stops it.
300
+ */
301
+ stream(params?: StreamsEventsStreamParams): AsyncIterable<StreamsEvent>
302
+ }
303
+ blocks: {
304
+ events(heightOrHash: number | string): Promise<StreamsEventsListEnvelope>
305
+ }
306
+ reorgs: {
307
+ list(params: StreamsReorgsListParams): Promise<StreamsReorgsListEnvelope>
308
+ }
309
+ canonical(height: number): Promise<StreamsCanonicalBlock>
310
+ tip(): Promise<StreamsTip>
311
+ };
105
312
  import { CreateSubscriptionRequest, CreateSubscriptionResponse, DeadRow, DeliveryRow, ReplayResult, RotateSecretResponse, SubscriptionDetail, SubscriptionSummary, UpdateSubscriptionRequest } from "@secondlayer/shared/schemas/subscriptions";
106
313
  declare class Subscriptions extends BaseClient {
107
314
  list(): Promise<{
@@ -131,6 +338,8 @@ declare class Subscriptions extends BaseClient {
131
338
  }>;
132
339
  }
133
340
  declare class SecondLayer extends BaseClient {
341
+ readonly streams: StreamsClient;
342
+ readonly index: Index;
134
343
  readonly subgraphs: Subgraphs;
135
344
  readonly subscriptions: Subscriptions;
136
345
  constructor(options?: Partial<SecondLayerOptions>);
@@ -276,6 +276,370 @@ class Subgraphs extends BaseClient {
276
276
  };
277
277
  }
278
278
  }
279
+ // src/index-api/client.ts
280
+ function appendSearchParam(params, name, value) {
281
+ if (value === undefined || value === null)
282
+ return;
283
+ params.set(name, String(value));
284
+ }
285
+ function firstWalkFromHeight(params) {
286
+ if (params.fromHeight !== undefined)
287
+ return params.fromHeight;
288
+ if (params.cursor || params.fromCursor)
289
+ return;
290
+ return 0;
291
+ }
292
+
293
+ class Index extends BaseClient {
294
+ constructor(options = {}) {
295
+ super(options);
296
+ }
297
+ ftTransfers = {
298
+ list: (params = {}) => this.listFtTransfers(params),
299
+ walk: (params = {}) => this.walkFtTransfers(params)
300
+ };
301
+ nftTransfers = {
302
+ list: (params = {}) => this.listNftTransfers(params),
303
+ walk: (params = {}) => this.walkNftTransfers(params)
304
+ };
305
+ async listFtTransfers(params = {}) {
306
+ const searchParams = new URLSearchParams;
307
+ appendSearchParam(searchParams, "cursor", params.cursor);
308
+ appendSearchParam(searchParams, "from_cursor", params.fromCursor);
309
+ appendSearchParam(searchParams, "limit", params.limit);
310
+ appendSearchParam(searchParams, "contract_id", params.contractId);
311
+ appendSearchParam(searchParams, "sender", params.sender);
312
+ appendSearchParam(searchParams, "recipient", params.recipient);
313
+ appendSearchParam(searchParams, "from_height", params.fromHeight);
314
+ appendSearchParam(searchParams, "to_height", params.toHeight);
315
+ const query = searchParams.toString();
316
+ return this.request("GET", `/v1/index/ft-transfers${query ? `?${query}` : ""}`);
317
+ }
318
+ async listNftTransfers(params = {}) {
319
+ const searchParams = new URLSearchParams;
320
+ appendSearchParam(searchParams, "cursor", params.cursor);
321
+ appendSearchParam(searchParams, "from_cursor", params.fromCursor);
322
+ appendSearchParam(searchParams, "limit", params.limit);
323
+ appendSearchParam(searchParams, "contract_id", params.contractId);
324
+ appendSearchParam(searchParams, "asset_identifier", params.assetIdentifier);
325
+ appendSearchParam(searchParams, "sender", params.sender);
326
+ appendSearchParam(searchParams, "recipient", params.recipient);
327
+ appendSearchParam(searchParams, "from_height", params.fromHeight);
328
+ appendSearchParam(searchParams, "to_height", params.toHeight);
329
+ const query = searchParams.toString();
330
+ return this.request("GET", `/v1/index/nft-transfers${query ? `?${query}` : ""}`);
331
+ }
332
+ async* walkFtTransfers(params = {}) {
333
+ const batchSize = params.batchSize ?? 200;
334
+ let cursor = params.cursor ?? params.fromCursor ?? null;
335
+ let firstPage = true;
336
+ while (!params.signal?.aborted) {
337
+ const envelope = await this.listFtTransfers({
338
+ ...params,
339
+ limit: batchSize,
340
+ cursor: firstPage ? params.cursor : cursor,
341
+ fromCursor: firstPage ? params.fromCursor : undefined,
342
+ fromHeight: firstPage ? firstWalkFromHeight(params) : undefined
343
+ });
344
+ for (const event of envelope.events) {
345
+ if (params.signal?.aborted)
346
+ return;
347
+ yield event;
348
+ }
349
+ const nextCursor = envelope.next_cursor;
350
+ if (!nextCursor || nextCursor === cursor || envelope.events.length < batchSize) {
351
+ return;
352
+ }
353
+ cursor = nextCursor;
354
+ firstPage = false;
355
+ }
356
+ }
357
+ async* walkNftTransfers(params = {}) {
358
+ const batchSize = params.batchSize ?? 200;
359
+ let cursor = params.cursor ?? params.fromCursor ?? null;
360
+ let firstPage = true;
361
+ while (!params.signal?.aborted) {
362
+ const envelope = await this.listNftTransfers({
363
+ ...params,
364
+ limit: batchSize,
365
+ cursor: firstPage ? params.cursor : cursor,
366
+ fromCursor: firstPage ? params.fromCursor : undefined,
367
+ fromHeight: firstPage ? firstWalkFromHeight(params) : undefined
368
+ });
369
+ for (const event of envelope.events) {
370
+ if (params.signal?.aborted)
371
+ return;
372
+ yield event;
373
+ }
374
+ const nextCursor = envelope.next_cursor;
375
+ if (!nextCursor || nextCursor === cursor || envelope.events.length < batchSize) {
376
+ return;
377
+ }
378
+ cursor = nextCursor;
379
+ firstPage = false;
380
+ }
381
+ }
382
+ }
383
+
384
+ // src/streams/consumer.ts
385
+ async function defaultSleep(ms, signal) {
386
+ if (signal?.aborted)
387
+ return;
388
+ await new Promise((resolve) => {
389
+ const timeout = setTimeout(resolve, ms);
390
+ if (!signal)
391
+ return;
392
+ signal.addEventListener("abort", () => {
393
+ clearTimeout(timeout);
394
+ resolve();
395
+ }, { once: true });
396
+ });
397
+ }
398
+ async function consumeStreamsEvents(opts) {
399
+ const sleep = opts.sleep ?? defaultSleep;
400
+ const mode = opts.mode ?? "tail";
401
+ const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
402
+ const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
403
+ const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
404
+ let cursor = opts.fromCursor ?? null;
405
+ let pages = 0;
406
+ let emptyPolls = 0;
407
+ while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
408
+ const envelope = await opts.fetchEvents({
409
+ cursor,
410
+ limit: opts.batchSize,
411
+ types: opts.types
412
+ });
413
+ pages++;
414
+ const returnedCursor = await opts.onBatch(envelope.events, envelope);
415
+ const nextCursor = returnedCursor ?? envelope.next_cursor;
416
+ if (nextCursor && nextCursor !== cursor) {
417
+ cursor = nextCursor;
418
+ emptyPolls = 0;
419
+ continue;
420
+ }
421
+ if (envelope.events.length === 0) {
422
+ emptyPolls++;
423
+ if (mode === "bounded") {
424
+ return { cursor, pages, emptyPolls };
425
+ }
426
+ await sleep(emptyBackoffMs, opts.signal);
427
+ continue;
428
+ }
429
+ return { cursor, pages, emptyPolls };
430
+ }
431
+ return { cursor, pages, emptyPolls };
432
+ }
433
+ async function* streamStreamsEvents(opts) {
434
+ const sleep = opts.sleep ?? defaultSleep;
435
+ const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
436
+ const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
437
+ const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
438
+ let cursor = opts.fromCursor ?? null;
439
+ let pages = 0;
440
+ let emptyPolls = 0;
441
+ while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
442
+ const envelope = await opts.fetchEvents({
443
+ cursor,
444
+ limit: opts.batchSize,
445
+ types: opts.types
446
+ });
447
+ pages++;
448
+ for (const event of envelope.events) {
449
+ if (opts.signal?.aborted)
450
+ return;
451
+ yield event;
452
+ }
453
+ const nextCursor = envelope.next_cursor;
454
+ if (nextCursor && nextCursor !== cursor) {
455
+ cursor = nextCursor;
456
+ emptyPolls = 0;
457
+ continue;
458
+ }
459
+ if (envelope.events.length === 0) {
460
+ emptyPolls++;
461
+ if (emptyPolls >= maxEmptyPolls || pages >= maxPages)
462
+ return;
463
+ await sleep(emptyBackoffMs, opts.signal);
464
+ continue;
465
+ }
466
+ return;
467
+ }
468
+ }
469
+
470
+ // src/streams/errors.ts
471
+ class AuthError extends Error {
472
+ status = 401;
473
+ constructor(message = "API key invalid or expired.") {
474
+ super(message);
475
+ this.name = "AuthError";
476
+ }
477
+ }
478
+
479
+ class RateLimitError extends Error {
480
+ retryAfter;
481
+ status = 429;
482
+ constructor(message = "Rate limited. Try again later.", retryAfter) {
483
+ super(message);
484
+ this.retryAfter = retryAfter;
485
+ this.name = "RateLimitError";
486
+ }
487
+ }
488
+
489
+ class ValidationError extends Error {
490
+ status;
491
+ body;
492
+ constructor(message, status, body) {
493
+ super(message);
494
+ this.status = status;
495
+ this.body = body;
496
+ this.name = "ValidationError";
497
+ }
498
+ }
499
+
500
+ class StreamsServerError extends Error {
501
+ status;
502
+ body;
503
+ constructor(message, status, body) {
504
+ super(message);
505
+ this.status = status;
506
+ this.body = body;
507
+ this.name = "StreamsServerError";
508
+ }
509
+ }
510
+
511
+ // src/streams/client.ts
512
+ var DEFAULT_STREAMS_BASE_URL = "https://api.secondlayer.tools";
513
+ function normalizeBaseUrl(baseUrl) {
514
+ return baseUrl.replace(/\/+$/, "");
515
+ }
516
+ function appendSearchParam2(params, name, value) {
517
+ if (value === undefined || value === null)
518
+ return;
519
+ params.set(name, String(value));
520
+ }
521
+ async function responseBody(response) {
522
+ const text = await response.text();
523
+ if (text.length === 0)
524
+ return;
525
+ try {
526
+ return JSON.parse(text);
527
+ } catch {
528
+ return text;
529
+ }
530
+ }
531
+ function errorMessage(body, fallback) {
532
+ if (body && typeof body === "object") {
533
+ const record = body;
534
+ const message = record.error ?? record.message;
535
+ if (typeof message === "string" && message.length > 0)
536
+ return message;
537
+ }
538
+ if (typeof body === "string" && body.length > 0)
539
+ return body;
540
+ return fallback;
541
+ }
542
+ async function mapStreamsError(response) {
543
+ const body = await responseBody(response);
544
+ if (response.status === 401) {
545
+ throw new AuthError(errorMessage(body, "API key invalid or expired."));
546
+ }
547
+ if (response.status === 429) {
548
+ const retryAfter = response.headers.get("Retry-After") ?? undefined;
549
+ throw new RateLimitError(errorMessage(body, "Rate limited. Try again later."), retryAfter);
550
+ }
551
+ if (response.status >= 500) {
552
+ throw new StreamsServerError(errorMessage(body, `Streams server returned ${response.status}.`), response.status, body);
553
+ }
554
+ throw new ValidationError(errorMessage(body, `Streams request returned ${response.status}.`), response.status, body);
555
+ }
556
+ function createStreamsClient(options) {
557
+ const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_STREAMS_BASE_URL);
558
+ const fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));
559
+ async function request(path) {
560
+ const response = await fetchImpl(`${baseUrl}${path}`, {
561
+ headers: { Authorization: `Bearer ${options.apiKey}` }
562
+ });
563
+ if (!response.ok)
564
+ await mapStreamsError(response);
565
+ return await response.json();
566
+ }
567
+ const fetchEvents = async ({
568
+ cursor,
569
+ limit,
570
+ types
571
+ }) => {
572
+ return listEvents({ cursor, limit, types });
573
+ };
574
+ async function listEvents(params = {}) {
575
+ const searchParams = new URLSearchParams;
576
+ appendSearchParam2(searchParams, "cursor", params.cursor);
577
+ appendSearchParam2(searchParams, "from_height", params.fromHeight);
578
+ appendSearchParam2(searchParams, "to_height", params.toHeight);
579
+ appendSearchParam2(searchParams, "limit", params.limit);
580
+ appendSearchParam2(searchParams, "contract_id", params.contractId);
581
+ if (params.types?.length) {
582
+ searchParams.set("types", params.types.join(","));
583
+ }
584
+ const query = searchParams.toString();
585
+ return request(`/v1/streams/events${query ? `?${query}` : ""}`);
586
+ }
587
+ return {
588
+ events: {
589
+ list: listEvents,
590
+ byTxId(txId) {
591
+ return request(`/v1/streams/events/${encodeURIComponent(txId)}`);
592
+ },
593
+ consume(params) {
594
+ return consumeStreamsEvents({
595
+ fromCursor: params.fromCursor,
596
+ mode: params.mode,
597
+ types: params.types,
598
+ batchSize: params.batchSize ?? 100,
599
+ fetchEvents,
600
+ onBatch: params.onBatch,
601
+ emptyBackoffMs: params.emptyBackoffMs,
602
+ maxPages: params.maxPages,
603
+ maxEmptyPolls: params.maxEmptyPolls,
604
+ signal: params.signal
605
+ });
606
+ },
607
+ stream(params = {}) {
608
+ return streamStreamsEvents({
609
+ fromCursor: params.fromCursor,
610
+ types: params.types,
611
+ batchSize: params.batchSize ?? 100,
612
+ emptyBackoffMs: params.emptyBackoffMs,
613
+ maxPages: params.maxPages,
614
+ maxEmptyPolls: params.maxEmptyPolls,
615
+ signal: params.signal,
616
+ fetchEvents
617
+ });
618
+ }
619
+ },
620
+ blocks: {
621
+ events(heightOrHash) {
622
+ return request(`/v1/streams/blocks/${encodeURIComponent(String(heightOrHash))}/events`);
623
+ }
624
+ },
625
+ reorgs: {
626
+ list(params) {
627
+ const searchParams = new URLSearchParams;
628
+ appendSearchParam2(searchParams, "since", params.since);
629
+ appendSearchParam2(searchParams, "limit", params.limit);
630
+ const query = searchParams.toString();
631
+ return request(`/v1/streams/reorgs${query ? `?${query}` : ""}`);
632
+ }
633
+ },
634
+ canonical(height) {
635
+ return request(`/v1/streams/canonical/${height}`);
636
+ },
637
+ tip() {
638
+ return request("/v1/streams/tip");
639
+ }
640
+ };
641
+ }
642
+
279
643
  // src/subscriptions/client.ts
280
644
  class Subscriptions extends BaseClient {
281
645
  async list() {
@@ -318,10 +682,18 @@ class Subscriptions extends BaseClient {
318
682
 
319
683
  // src/client.ts
320
684
  class SecondLayer extends BaseClient {
685
+ streams;
686
+ index;
321
687
  subgraphs;
322
688
  subscriptions;
323
689
  constructor(options = {}) {
324
690
  super(options);
691
+ this.streams = createStreamsClient({
692
+ apiKey: options.apiKey ?? "",
693
+ baseUrl: options.baseUrl,
694
+ fetchImpl: options.fetchImpl
695
+ });
696
+ this.index = new Index(options);
325
697
  this.subgraphs = new Subgraphs(options);
326
698
  this.subscriptions = new Subscriptions(options);
327
699
  }
@@ -342,5 +714,5 @@ export {
342
714
  Subgraphs
343
715
  };
344
716
 
345
- //# debugId=ADD697A31D92DD7264756E2164756E21
717
+ //# debugId=E734D986870AD6AC64756E2164756E21
346
718
  //# sourceMappingURL=index.js.map