@secondlayer/sdk 6.39.0 → 6.40.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.
@@ -453,6 +453,12 @@ type StreamsEventBase = {
453
453
  * Optional for back-compat; the API always sets it on Streams responses.
454
454
  */
455
455
  finalized?: boolean
456
+ /**
457
+ * Labels whose filter group this event satisfied, present only when the
458
+ * request used a labelled `filters` map. The SDK dispatches on it for you
459
+ * (`on.<label>`), so handlers rarely read it directly.
460
+ */
461
+ matched?: string[]
456
462
  };
457
463
  type StreamsEventOf<
458
464
  T extends StreamsEventType,
@@ -522,6 +528,34 @@ type StreamsReorgsListEnvelope = {
522
528
  };
523
529
  /** A filter that matches a single value or any value in a list. */
524
530
  type StreamsFilterValue = string | readonly string[];
531
+ /**
532
+ * One labelled filter group. Fields inside a group AND together; groups in a
533
+ * map OR together server-side.
534
+ */
535
+ type StreamsLabelledFilter = {
536
+ types?: readonly StreamsEventType[]
537
+ contractId?: StreamsFilterValue
538
+ sender?: StreamsFilterValue
539
+ recipient?: StreamsFilterValue
540
+ assetIdentifier?: string
541
+ };
542
+ /** A map of label → filter group. Labels are yours; the server echoes them. */
543
+ type StreamsFilterMap = Record<string, StreamsLabelledFilter>;
544
+ /**
545
+ * The events one label can yield. A group that declares `types` narrows to
546
+ * exactly those variants, so a per-label handler needs no `event_type` guard;
547
+ * a group without `types` keeps the full union.
548
+ */
549
+ type StreamsEventForFilter<
550
+ F,
551
+ D extends boolean = false
552
+ > = F extends {
553
+ types: readonly (infer T extends StreamsEventType)[]
554
+ } ? D extends true ? Extract<IndexEvent, {
555
+ event_type: T
556
+ }> : Extract<StreamsEvent, {
557
+ event_type: T
558
+ }> : D extends true ? IndexEvent : StreamsEvent;
525
559
  type StreamsEventsListParams = {
526
560
  cursor?: string | null
527
561
  fromHeight?: number
@@ -533,6 +567,12 @@ type StreamsEventsListParams = {
533
567
  sender?: StreamsFilterValue
534
568
  recipient?: StreamsFilterValue
535
569
  assetIdentifier?: string
570
+ /**
571
+ * Labelled filter groups. The groups OR together in one scan and each
572
+ * returned event carries the labels it matched (`event.matched`) — two
573
+ * unrelated concerns share one page, one cursor, one checkpoint.
574
+ */
575
+ filters?: StreamsFilterMap
536
576
  limit?: number
537
577
  };
538
578
  type StreamsEventsStreamParams = {
@@ -543,6 +583,8 @@ type StreamsEventsStreamParams = {
543
583
  sender?: StreamsFilterValue
544
584
  recipient?: StreamsFilterValue
545
585
  assetIdentifier?: string
586
+ /** Labelled filter groups; see {@link StreamsEventsListParams.filters}. */
587
+ filters?: StreamsFilterMap
546
588
  batchSize?: number
547
589
  emptyBackoffMs?: number
548
590
  maxPages?: number
@@ -558,6 +600,8 @@ type StreamsEventsSubscribeParams = {
558
600
  sender?: StreamsFilterValue
559
601
  recipient?: StreamsFilterValue
560
602
  assetIdentifier?: string
603
+ /** Labelled filter groups; see {@link StreamsEventsListParams.filters}. */
604
+ filters?: StreamsFilterMap
561
605
  /** Abort to unsubscribe (the returned function does the same). */
562
606
  signal?: AbortSignal
563
607
  /** Called for each pushed event, in order. */
@@ -609,7 +653,8 @@ type StreamsReorgContext = {
609
653
  };
610
654
  type StreamsEventsConsumeParams<
611
655
  TTx = never,
612
- D extends boolean = false
656
+ D extends boolean = false,
657
+ F extends StreamsFilterMap = Record<never, never>
613
658
  > = {
614
659
  fromCursor?: string | null
615
660
  /**
@@ -643,13 +688,33 @@ type StreamsEventsConsumeParams<
643
688
  sender?: StreamsFilterValue
644
689
  recipient?: StreamsFilterValue
645
690
  assetIdentifier?: string
691
+ /**
692
+ * Labelled filter groups. The groups OR together in ONE server-side scan,
693
+ * so two unrelated concerns share one page, one cursor, and one checkpoint
694
+ * instead of two consume loops. Pair with `on` to handle each label.
695
+ */
696
+ filters?: F
697
+ /**
698
+ * One handler per label in `filters`. Every label must be handled, so
699
+ * adding a label is a compile error until its handler exists.
700
+ *
701
+ * A label's declared `types` narrows its handler's events, so `payload` is
702
+ * typed without an `event_type` guard. Labels are dispatched in declaration
703
+ * order: a label's own events stay in cursor order, but events of different
704
+ * labels do not interleave within a page — add `onBatch` when you need
705
+ * strict global order across labels.
706
+ */
707
+ on?: { [K in keyof F] : (events: StreamsEventForFilter<F[K], D>[], ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | Promise<void> }
646
708
  batchSize?: number
647
709
  /**
648
710
  * Apply a page of canonical events. Persist `ctx.cursor` in the same
649
711
  * transaction as your writes. Returning a cursor overrides `ctx.cursor` as
650
712
  * the resume point (advanced manual control); returning nothing uses it.
713
+ *
714
+ * Optional only when `on` handles the page instead; a consume call with
715
+ * neither throws.
651
716
  */
652
- onBatch: (events: D extends true ? IndexEvent[] : StreamsEvent[], envelope: StreamsEventsEnvelope, ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | string | null | undefined | Promise<void> | Promise<string | null | undefined>
717
+ onBatch?: (events: D extends true ? IndexEvent[] : StreamsEvent[], envelope: StreamsEventsEnvelope, ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | string | null | undefined | Promise<void> | Promise<string | null | undefined>
653
718
  /**
654
719
  * Roll your projection back to `reorg.fork_point_height`, persisting
655
720
  * `ctx.cursor` in the same transaction. Called once per *new* reorg
@@ -807,9 +872,10 @@ type StreamsClient = {
807
872
  * stops it.
808
873
  */
809
874
  consume<
875
+ const F extends StreamsFilterMap = Record<never, never>,
810
876
  TTx = never,
811
877
  D extends boolean = false
812
- >(params: StreamsEventsConsumeParams<TTx, D> & {
878
+ >(params: StreamsEventsConsumeParams<TTx, D, F> & {
813
879
  sink?: ConsumerSink<TTx>
814
880
  }): Promise<StreamsEventsConsumeResult>
815
881
  /**
@@ -669,7 +669,8 @@ async function consumeStreamsEvents(opts) {
669
669
  contractId: opts.contractId,
670
670
  sender: opts.sender,
671
671
  recipient: opts.recipient,
672
- assetIdentifier: opts.assetIdentifier
672
+ assetIdentifier: opts.assetIdentifier,
673
+ filters: opts.filters
673
674
  }), {
674
675
  retryCount: opts.retryCount,
675
676
  retryDelay: opts.retryDelay,
@@ -746,7 +747,8 @@ async function* iterateStreamsBatches(opts) {
746
747
  contractId: opts.contractId,
747
748
  sender: opts.sender,
748
749
  recipient: opts.recipient,
749
- assetIdentifier: opts.assetIdentifier
750
+ assetIdentifier: opts.assetIdentifier,
751
+ filters: opts.filters
750
752
  });
751
753
  const checkpoint = envelope.next_cursor ?? cursor;
752
754
  if (envelope.events.length > 0 || envelope.reorgs.length > 0) {
@@ -783,7 +785,8 @@ async function* streamStreamsEvents(opts) {
783
785
  contractId: opts.contractId,
784
786
  sender: opts.sender,
785
787
  recipient: opts.recipient,
786
- assetIdentifier: opts.assetIdentifier
788
+ assetIdentifier: opts.assetIdentifier,
789
+ filters: opts.filters
787
790
  });
788
791
  pages++;
789
792
  for (const event of envelope.events) {
@@ -1598,7 +1601,8 @@ function subscribeStreamsEvents(opts) {
1598
1601
  contract_id: params.contractId,
1599
1602
  sender: params.sender,
1600
1603
  recipient: params.recipient,
1601
- asset_identifier: params.assetIdentifier
1604
+ asset_identifier: params.assetIdentifier,
1605
+ filters: params.filters ? JSON.stringify(params.filters) : undefined
1602
1606
  })}`;
1603
1607
  const res = await opts.fetchImpl(url, {
1604
1608
  headers: {
@@ -1842,7 +1846,8 @@ function createStreamsClient(options) {
1842
1846
  contractId,
1843
1847
  sender,
1844
1848
  recipient,
1845
- assetIdentifier
1849
+ assetIdentifier,
1850
+ filters
1846
1851
  }) => {
1847
1852
  return listEvents({
1848
1853
  cursor,
@@ -1852,9 +1857,13 @@ function createStreamsClient(options) {
1852
1857
  contractId,
1853
1858
  sender,
1854
1859
  recipient,
1855
- assetIdentifier
1860
+ assetIdentifier,
1861
+ filters
1856
1862
  });
1857
1863
  };
1864
+ function encodeFilters(filters) {
1865
+ return filters ? JSON.stringify(filters) : undefined;
1866
+ }
1858
1867
  async function listEvents(params = {}) {
1859
1868
  return request(`/v1/streams/events${buildQuery({
1860
1869
  cursor: params.cursor,
@@ -1866,9 +1875,56 @@ function createStreamsClient(options) {
1866
1875
  recipient: params.recipient,
1867
1876
  asset_identifier: params.assetIdentifier,
1868
1877
  types: params.types,
1869
- not_types: params.notTypes
1878
+ not_types: params.notTypes,
1879
+ filters: encodeFilters(params.filters)
1870
1880
  })}`);
1871
1881
  }
1882
+ function consumeEvents(params) {
1883
+ const labels = params.filters ? Object.keys(params.filters) : [];
1884
+ if (labels.length === 0 && !params.onBatch) {
1885
+ throw new ValidationError("consume requires onBatch, or filters + on handlers.", 400);
1886
+ }
1887
+ if (labels.length > 0 && !params.on && !params.onBatch) {
1888
+ throw new ValidationError("consume with filters requires on handlers (or onBatch).", 400);
1889
+ }
1890
+ const dispatch = params.on;
1891
+ const project = (events) => params.decoded ? events.map(decode) : events;
1892
+ const onBatch = async (events, envelope, ctx) => {
1893
+ for (const label of labels) {
1894
+ const forLabel = events.filter((event) => event.matched?.includes(label));
1895
+ if (forLabel.length === 0)
1896
+ continue;
1897
+ await dispatch?.[label]?.(project(forLabel), ctx);
1898
+ }
1899
+ const userOnBatch = params.onBatch;
1900
+ return await userOnBatch?.(project(events), envelope, ctx);
1901
+ };
1902
+ return consumeStreamsEvents({
1903
+ fromCursor: params.fromCursor,
1904
+ sink: params.sink,
1905
+ onProgress: params.onProgress,
1906
+ mode: params.mode,
1907
+ finalizedOnly: params.finalizedOnly,
1908
+ types: params.types,
1909
+ notTypes: params.notTypes,
1910
+ contractId: params.contractId,
1911
+ sender: params.sender,
1912
+ recipient: params.recipient,
1913
+ assetIdentifier: params.assetIdentifier,
1914
+ filters: params.filters,
1915
+ batchSize: params.batchSize ?? 100,
1916
+ fetchEvents,
1917
+ onBatch,
1918
+ onReorg: params.onReorg,
1919
+ emptyBackoffMs: params.emptyBackoffMs,
1920
+ maxPages: params.maxPages,
1921
+ maxEmptyPolls: params.maxEmptyPolls,
1922
+ signal: params.signal,
1923
+ retryCount: params.retryCount,
1924
+ retryDelay: params.retryDelay,
1925
+ onError: params.onError
1926
+ });
1927
+ }
1872
1928
  return {
1873
1929
  consume(params = {}) {
1874
1930
  return iterateStreamsBatches({
@@ -1890,33 +1946,7 @@ function createStreamsClient(options) {
1890
1946
  byTxId(txId) {
1891
1947
  return request(`/v1/streams/events/${encodeURIComponent(txId)}`);
1892
1948
  },
1893
- consume(params) {
1894
- const onBatch = params.decoded ? (events, envelope, ctx) => params.onBatch(events.map(decode), envelope, ctx) : params.onBatch;
1895
- return consumeStreamsEvents({
1896
- fromCursor: params.fromCursor,
1897
- sink: params.sink,
1898
- onProgress: params.onProgress,
1899
- mode: params.mode,
1900
- finalizedOnly: params.finalizedOnly,
1901
- types: params.types,
1902
- notTypes: params.notTypes,
1903
- contractId: params.contractId,
1904
- sender: params.sender,
1905
- recipient: params.recipient,
1906
- assetIdentifier: params.assetIdentifier,
1907
- batchSize: params.batchSize ?? 100,
1908
- fetchEvents,
1909
- onBatch,
1910
- onReorg: params.onReorg,
1911
- emptyBackoffMs: params.emptyBackoffMs,
1912
- maxPages: params.maxPages,
1913
- maxEmptyPolls: params.maxEmptyPolls,
1914
- signal: params.signal,
1915
- retryCount: params.retryCount,
1916
- retryDelay: params.retryDelay,
1917
- onError: params.onError
1918
- });
1919
- },
1949
+ consume: consumeEvents,
1920
1950
  stream(params = {}) {
1921
1951
  return streamStreamsEvents({
1922
1952
  fromCursor: params.fromCursor,
@@ -2149,5 +2179,5 @@ export {
2149
2179
  Subgraphs
2150
2180
  };
2151
2181
 
2152
- //# debugId=F62665719058CC2664756E2164756E21
2182
+ //# debugId=4B9D9DF481DBB85464756E2164756E21
2153
2183
  //# sourceMappingURL=index.js.map