@secondlayer/sdk 6.21.2 → 6.23.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.
@@ -442,6 +442,280 @@ class Contracts extends BaseClient {
442
442
  }
443
443
  }
444
444
 
445
+ // src/streams/errors.ts
446
+ class AuthError extends Error {
447
+ status = 401;
448
+ constructor(message = "API key invalid or expired.") {
449
+ super(message);
450
+ this.name = "AuthError";
451
+ }
452
+ }
453
+
454
+ class RateLimitError extends Error {
455
+ retryAfter;
456
+ status = 429;
457
+ constructor(message = "Rate limited. Try again later.", retryAfter) {
458
+ super(message);
459
+ this.retryAfter = retryAfter;
460
+ this.name = "RateLimitError";
461
+ }
462
+ }
463
+
464
+ class ValidationError extends Error {
465
+ status;
466
+ body;
467
+ constructor(message, status, body) {
468
+ super(message);
469
+ this.status = status;
470
+ this.body = body;
471
+ this.name = "ValidationError";
472
+ }
473
+ }
474
+
475
+ class StreamsServerError extends Error {
476
+ status;
477
+ body;
478
+ constructor(message, status, body) {
479
+ super(message);
480
+ this.status = status;
481
+ this.body = body;
482
+ this.name = "StreamsServerError";
483
+ }
484
+ }
485
+
486
+ class StreamsSignatureError extends Error {
487
+ constructor(message = "Streams response signature verification failed.") {
488
+ super(message);
489
+ this.name = "StreamsSignatureError";
490
+ }
491
+ }
492
+
493
+ // src/streams/cursor.ts
494
+ var Cursor = {
495
+ atHeight(height) {
496
+ return `${height}:0`;
497
+ },
498
+ parse(cursor) {
499
+ const parts = cursor.split(":");
500
+ const blockHeight = Number(parts[0]);
501
+ const eventIndex = Number(parts[1]);
502
+ if (parts.length !== 2 || !Number.isInteger(blockHeight) || !Number.isInteger(eventIndex)) {
503
+ throw new ValidationError(`Invalid stream cursor "${cursor}"; expected "<block>:<index>" (e.g. "951475:3").`, 400);
504
+ }
505
+ return { blockHeight, eventIndex };
506
+ }
507
+ };
508
+
509
+ // src/streams/consumer.ts
510
+ function reorgKey(reorg) {
511
+ return `${reorg.detected_at}|${reorg.fork_point_height}|${reorg.new_canonical_tip}`;
512
+ }
513
+ async function defaultSleep(ms, signal) {
514
+ if (signal?.aborted)
515
+ return;
516
+ await new Promise((resolve) => {
517
+ const timeout = setTimeout(resolve, ms);
518
+ if (!signal)
519
+ return;
520
+ signal.addEventListener("abort", () => {
521
+ clearTimeout(timeout);
522
+ resolve();
523
+ }, { once: true });
524
+ });
525
+ }
526
+ async function consumeStreamsEvents(opts) {
527
+ const sleep = opts.sleep ?? defaultSleep;
528
+ const mode = opts.mode ?? "tail";
529
+ const finalizedOnly = opts.finalizedOnly ?? false;
530
+ const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
531
+ const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
532
+ const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
533
+ let cursor = opts.fromCursor ?? null;
534
+ const handledReorgs = new Set;
535
+ let pages = 0;
536
+ let emptyPolls = 0;
537
+ while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
538
+ const envelope = await opts.fetchEvents({
539
+ cursor,
540
+ limit: opts.batchSize,
541
+ types: opts.types,
542
+ notTypes: opts.notTypes,
543
+ contractId: opts.contractId,
544
+ sender: opts.sender,
545
+ recipient: opts.recipient,
546
+ assetIdentifier: opts.assetIdentifier
547
+ });
548
+ pages++;
549
+ if (!finalizedOnly && opts.onReorg) {
550
+ const fresh = envelope.reorgs.filter((reorg) => !handledReorgs.has(reorgKey(reorg))).sort((a, b) => a.fork_point_height - b.fork_point_height);
551
+ if (fresh.length > 0) {
552
+ const forkPoint = Math.min(...fresh.map((reorg) => reorg.fork_point_height));
553
+ const rewind = Cursor.atHeight(forkPoint);
554
+ for (const reorg of fresh) {
555
+ await opts.onReorg(reorg, { cursor: rewind });
556
+ handledReorgs.add(reorgKey(reorg));
557
+ }
558
+ cursor = rewind;
559
+ emptyPolls = 0;
560
+ continue;
561
+ }
562
+ }
563
+ const emitted = finalizedOnly ? envelope.events.filter((event) => event.finalized) : envelope.events;
564
+ const checkpoint = finalizedOnly ? emitted.at(-1)?.cursor ?? cursor : envelope.next_cursor;
565
+ const returnedCursor = await opts.onBatch(emitted, envelope, {
566
+ cursor: checkpoint
567
+ });
568
+ const nextCursor = returnedCursor ?? checkpoint;
569
+ if (nextCursor && nextCursor !== cursor) {
570
+ cursor = nextCursor;
571
+ emptyPolls = 0;
572
+ continue;
573
+ }
574
+ if (emitted.length === 0) {
575
+ emptyPolls++;
576
+ if (mode === "bounded") {
577
+ return { cursor, pages, emptyPolls };
578
+ }
579
+ await sleep(emptyBackoffMs, opts.signal);
580
+ continue;
581
+ }
582
+ return { cursor, pages, emptyPolls };
583
+ }
584
+ return { cursor, pages, emptyPolls };
585
+ }
586
+ async function* iterateStreamsBatches(opts) {
587
+ const sleep = opts.sleep ?? defaultSleep;
588
+ let cursor = opts.fromCursor ?? null;
589
+ while (!opts.signal?.aborted) {
590
+ const envelope = await opts.fetchEvents({
591
+ cursor,
592
+ limit: opts.batchSize,
593
+ types: opts.types,
594
+ notTypes: opts.notTypes,
595
+ contractId: opts.contractId,
596
+ sender: opts.sender,
597
+ recipient: opts.recipient,
598
+ assetIdentifier: opts.assetIdentifier
599
+ });
600
+ const checkpoint = envelope.next_cursor ?? cursor;
601
+ if (envelope.events.length > 0 || envelope.reorgs.length > 0) {
602
+ yield {
603
+ events: envelope.events,
604
+ cursor: checkpoint,
605
+ tip: envelope.tip,
606
+ reorgs: envelope.reorgs
607
+ };
608
+ }
609
+ const advanced = checkpoint !== null && checkpoint !== cursor;
610
+ cursor = checkpoint;
611
+ if (!advanced && envelope.events.length === 0) {
612
+ if (opts.signal?.aborted)
613
+ return;
614
+ await sleep(opts.intervalMs, opts.signal);
615
+ }
616
+ }
617
+ }
618
+ async function* streamStreamsEvents(opts) {
619
+ const sleep = opts.sleep ?? defaultSleep;
620
+ const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
621
+ const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
622
+ const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
623
+ let cursor = opts.fromCursor ?? null;
624
+ let pages = 0;
625
+ let emptyPolls = 0;
626
+ while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
627
+ const envelope = await opts.fetchEvents({
628
+ cursor,
629
+ limit: opts.batchSize,
630
+ types: opts.types,
631
+ notTypes: opts.notTypes,
632
+ contractId: opts.contractId,
633
+ sender: opts.sender,
634
+ recipient: opts.recipient,
635
+ assetIdentifier: opts.assetIdentifier
636
+ });
637
+ pages++;
638
+ for (const event of envelope.events) {
639
+ if (opts.signal?.aborted)
640
+ return;
641
+ yield event;
642
+ }
643
+ const nextCursor = envelope.next_cursor;
644
+ if (nextCursor && nextCursor !== cursor) {
645
+ cursor = nextCursor;
646
+ emptyPolls = 0;
647
+ continue;
648
+ }
649
+ if (envelope.events.length === 0) {
650
+ emptyPolls++;
651
+ if (emptyPolls >= maxEmptyPolls || pages >= maxPages)
652
+ return;
653
+ await sleep(emptyBackoffMs, opts.signal);
654
+ continue;
655
+ }
656
+ return;
657
+ }
658
+ }
659
+
660
+ // src/index-api/consumer.ts
661
+ async function consumeIndexFeed(opts) {
662
+ const sleep = opts.sleep ?? defaultSleep;
663
+ const mode = opts.mode ?? "tail";
664
+ const finalizedOnly = opts.finalizedOnly ?? false;
665
+ const batchSize = opts.batchSize ?? 200;
666
+ const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
667
+ const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
668
+ const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
669
+ let cursor = opts.fromCursor ?? null;
670
+ const handledReorgs = new Set;
671
+ let pages = 0;
672
+ let emptyPolls = 0;
673
+ while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
674
+ const envelope = await opts.fetchPage({
675
+ cursor,
676
+ fromHeight: cursor === null ? opts.fromHeight : undefined,
677
+ limit: batchSize
678
+ });
679
+ pages++;
680
+ if (!finalizedOnly && opts.onReorg) {
681
+ const fresh = envelope.reorgs.filter((reorg) => !handledReorgs.has(reorg.id)).sort((a, b) => a.fork_point_height - b.fork_point_height);
682
+ if (fresh.length > 0) {
683
+ const forkPoint = Math.min(...fresh.map((reorg) => reorg.fork_point_height));
684
+ const rewind = Cursor.atHeight(forkPoint);
685
+ for (const reorg of fresh) {
686
+ await opts.onReorg(reorg, { cursor: rewind });
687
+ handledReorgs.add(reorg.id);
688
+ }
689
+ cursor = rewind;
690
+ emptyPolls = 0;
691
+ continue;
692
+ }
693
+ }
694
+ const items = opts.itemsOf(envelope);
695
+ const emitted = finalizedOnly ? items.filter((item) => item.block_height <= envelope.tip.finalized_height) : items;
696
+ const checkpoint = finalizedOnly ? emitted.at(-1)?.cursor ?? cursor : envelope.next_cursor;
697
+ const returnedCursor = await opts.onBatch(emitted, envelope, {
698
+ cursor: checkpoint
699
+ });
700
+ const nextCursor = returnedCursor ?? checkpoint;
701
+ if (nextCursor && nextCursor !== cursor) {
702
+ cursor = nextCursor;
703
+ emptyPolls = 0;
704
+ continue;
705
+ }
706
+ if (emitted.length === 0) {
707
+ emptyPolls++;
708
+ if (mode === "bounded") {
709
+ return { cursor, pages, emptyPolls };
710
+ }
711
+ await sleep(emptyBackoffMs, opts.signal);
712
+ continue;
713
+ }
714
+ return { cursor, pages, emptyPolls };
715
+ }
716
+ return { cursor, pages, emptyPolls };
717
+ }
718
+
445
719
  // src/index-api/client.ts
446
720
  function firstWalkFromHeight(params) {
447
721
  if (params.fromHeight !== undefined)
@@ -461,6 +735,15 @@ class Index extends BaseClient {
461
735
  discover() {
462
736
  return this.request("GET", "/v1/index");
463
737
  }
738
+ async printSchema(contractId) {
739
+ try {
740
+ return await this.request("GET", `/v1/index/contracts/${encodeURIComponent(contractId)}/print-schema`);
741
+ } catch (err) {
742
+ if (err instanceof ApiError && err.status === 404)
743
+ return null;
744
+ throw err;
745
+ }
746
+ }
464
747
  ftTransfers = Object.assign((params = {}) => this.listFtTransfers(params), {
465
748
  list: (params = {}) => this.listFtTransfers(params),
466
749
  walk: (params = {}) => this.walkFtTransfers(params)
@@ -471,11 +754,41 @@ class Index extends BaseClient {
471
754
  });
472
755
  events = Object.assign((params) => this.listEvents(params), {
473
756
  list: (params) => this.listEvents(params),
474
- walk: (params) => this.walkEvents(params)
757
+ walk: (params) => this.walkEvents(params),
758
+ consume: (params) => consumeIndexFeed({
759
+ ...params,
760
+ fetchPage: ({ cursor, fromHeight, limit }) => this.listEvents({
761
+ eventType: params.eventType,
762
+ contractId: params.contractId,
763
+ assetIdentifier: params.assetIdentifier,
764
+ sender: params.sender,
765
+ recipient: params.recipient,
766
+ trait: params.trait,
767
+ toHeight: params.toHeight,
768
+ cursor,
769
+ fromHeight,
770
+ limit
771
+ }),
772
+ itemsOf: (envelope) => envelope.events
773
+ })
475
774
  });
476
775
  contractCalls = {
477
776
  list: (params = {}) => this.listContractCalls(params),
478
- walk: (params = {}) => this.walkContractCalls(params)
777
+ walk: (params = {}) => this.walkContractCalls(params),
778
+ consume: (params) => consumeIndexFeed({
779
+ ...params,
780
+ fetchPage: ({ cursor, fromHeight, limit }) => this.listContractCalls({
781
+ contractId: params.contractId,
782
+ functionName: params.functionName,
783
+ sender: params.sender,
784
+ trait: params.trait,
785
+ toHeight: params.toHeight,
786
+ cursor,
787
+ fromHeight,
788
+ limit
789
+ }),
790
+ itemsOf: (envelope) => envelope.contract_calls
791
+ })
479
792
  };
480
793
  canonical = {
481
794
  list: (params = {}) => this.listCanonical(params),
@@ -896,221 +1209,6 @@ class Projects extends BaseClient {
896
1209
  // src/streams/client.ts
897
1210
  import { ed25519 as ed255192 } from "@secondlayer/shared";
898
1211
 
899
- // src/streams/errors.ts
900
- class AuthError extends Error {
901
- status = 401;
902
- constructor(message = "API key invalid or expired.") {
903
- super(message);
904
- this.name = "AuthError";
905
- }
906
- }
907
-
908
- class RateLimitError extends Error {
909
- retryAfter;
910
- status = 429;
911
- constructor(message = "Rate limited. Try again later.", retryAfter) {
912
- super(message);
913
- this.retryAfter = retryAfter;
914
- this.name = "RateLimitError";
915
- }
916
- }
917
-
918
- class ValidationError extends Error {
919
- status;
920
- body;
921
- constructor(message, status, body) {
922
- super(message);
923
- this.status = status;
924
- this.body = body;
925
- this.name = "ValidationError";
926
- }
927
- }
928
-
929
- class StreamsServerError extends Error {
930
- status;
931
- body;
932
- constructor(message, status, body) {
933
- super(message);
934
- this.status = status;
935
- this.body = body;
936
- this.name = "StreamsServerError";
937
- }
938
- }
939
-
940
- class StreamsSignatureError extends Error {
941
- constructor(message = "Streams response signature verification failed.") {
942
- super(message);
943
- this.name = "StreamsSignatureError";
944
- }
945
- }
946
-
947
- // src/streams/cursor.ts
948
- var Cursor = {
949
- atHeight(height) {
950
- return `${height}:0`;
951
- },
952
- parse(cursor) {
953
- const parts = cursor.split(":");
954
- const blockHeight = Number(parts[0]);
955
- const eventIndex = Number(parts[1]);
956
- if (parts.length !== 2 || !Number.isInteger(blockHeight) || !Number.isInteger(eventIndex)) {
957
- throw new ValidationError(`Invalid stream cursor "${cursor}"; expected "<block>:<index>" (e.g. "951475:3").`, 400);
958
- }
959
- return { blockHeight, eventIndex };
960
- }
961
- };
962
-
963
- // src/streams/consumer.ts
964
- function reorgKey(reorg) {
965
- return `${reorg.detected_at}|${reorg.fork_point_height}|${reorg.new_canonical_tip}`;
966
- }
967
- async function defaultSleep(ms, signal) {
968
- if (signal?.aborted)
969
- return;
970
- await new Promise((resolve) => {
971
- const timeout = setTimeout(resolve, ms);
972
- if (!signal)
973
- return;
974
- signal.addEventListener("abort", () => {
975
- clearTimeout(timeout);
976
- resolve();
977
- }, { once: true });
978
- });
979
- }
980
- async function consumeStreamsEvents(opts) {
981
- const sleep = opts.sleep ?? defaultSleep;
982
- const mode = opts.mode ?? "tail";
983
- const finalizedOnly = opts.finalizedOnly ?? false;
984
- const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
985
- const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
986
- const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
987
- let cursor = opts.fromCursor ?? null;
988
- const handledReorgs = new Set;
989
- let pages = 0;
990
- let emptyPolls = 0;
991
- while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
992
- const envelope = await opts.fetchEvents({
993
- cursor,
994
- limit: opts.batchSize,
995
- types: opts.types,
996
- notTypes: opts.notTypes,
997
- contractId: opts.contractId,
998
- sender: opts.sender,
999
- recipient: opts.recipient,
1000
- assetIdentifier: opts.assetIdentifier
1001
- });
1002
- pages++;
1003
- if (!finalizedOnly && opts.onReorg) {
1004
- const fresh = envelope.reorgs.filter((reorg) => !handledReorgs.has(reorgKey(reorg))).sort((a, b) => a.fork_point_height - b.fork_point_height);
1005
- if (fresh.length > 0) {
1006
- const forkPoint = Math.min(...fresh.map((reorg) => reorg.fork_point_height));
1007
- const rewind = Cursor.atHeight(forkPoint);
1008
- for (const reorg of fresh) {
1009
- await opts.onReorg(reorg, { cursor: rewind });
1010
- handledReorgs.add(reorgKey(reorg));
1011
- }
1012
- cursor = rewind;
1013
- emptyPolls = 0;
1014
- continue;
1015
- }
1016
- }
1017
- const emitted = finalizedOnly ? envelope.events.filter((event) => event.finalized) : envelope.events;
1018
- const checkpoint = finalizedOnly ? emitted.at(-1)?.cursor ?? cursor : envelope.next_cursor;
1019
- const returnedCursor = await opts.onBatch(emitted, envelope, {
1020
- cursor: checkpoint
1021
- });
1022
- const nextCursor = returnedCursor ?? checkpoint;
1023
- if (nextCursor && nextCursor !== cursor) {
1024
- cursor = nextCursor;
1025
- emptyPolls = 0;
1026
- continue;
1027
- }
1028
- if (emitted.length === 0) {
1029
- emptyPolls++;
1030
- if (mode === "bounded") {
1031
- return { cursor, pages, emptyPolls };
1032
- }
1033
- await sleep(emptyBackoffMs, opts.signal);
1034
- continue;
1035
- }
1036
- return { cursor, pages, emptyPolls };
1037
- }
1038
- return { cursor, pages, emptyPolls };
1039
- }
1040
- async function* iterateStreamsBatches(opts) {
1041
- const sleep = opts.sleep ?? defaultSleep;
1042
- let cursor = opts.fromCursor ?? null;
1043
- while (!opts.signal?.aborted) {
1044
- const envelope = await opts.fetchEvents({
1045
- cursor,
1046
- limit: opts.batchSize,
1047
- types: opts.types,
1048
- notTypes: opts.notTypes,
1049
- contractId: opts.contractId,
1050
- sender: opts.sender,
1051
- recipient: opts.recipient,
1052
- assetIdentifier: opts.assetIdentifier
1053
- });
1054
- const checkpoint = envelope.next_cursor ?? cursor;
1055
- if (envelope.events.length > 0 || envelope.reorgs.length > 0) {
1056
- yield {
1057
- events: envelope.events,
1058
- cursor: checkpoint,
1059
- tip: envelope.tip,
1060
- reorgs: envelope.reorgs
1061
- };
1062
- }
1063
- const advanced = checkpoint !== null && checkpoint !== cursor;
1064
- cursor = checkpoint;
1065
- if (!advanced && envelope.events.length === 0) {
1066
- if (opts.signal?.aborted)
1067
- return;
1068
- await sleep(opts.intervalMs, opts.signal);
1069
- }
1070
- }
1071
- }
1072
- async function* streamStreamsEvents(opts) {
1073
- const sleep = opts.sleep ?? defaultSleep;
1074
- const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
1075
- const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
1076
- const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
1077
- let cursor = opts.fromCursor ?? null;
1078
- let pages = 0;
1079
- let emptyPolls = 0;
1080
- while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
1081
- const envelope = await opts.fetchEvents({
1082
- cursor,
1083
- limit: opts.batchSize,
1084
- types: opts.types,
1085
- notTypes: opts.notTypes,
1086
- contractId: opts.contractId,
1087
- sender: opts.sender,
1088
- recipient: opts.recipient,
1089
- assetIdentifier: opts.assetIdentifier
1090
- });
1091
- pages++;
1092
- for (const event of envelope.events) {
1093
- if (opts.signal?.aborted)
1094
- return;
1095
- yield event;
1096
- }
1097
- const nextCursor = envelope.next_cursor;
1098
- if (nextCursor && nextCursor !== cursor) {
1099
- cursor = nextCursor;
1100
- emptyPolls = 0;
1101
- continue;
1102
- }
1103
- if (envelope.events.length === 0) {
1104
- emptyPolls++;
1105
- if (emptyPolls >= maxEmptyPolls || pages >= maxPages)
1106
- return;
1107
- await sleep(emptyBackoffMs, opts.signal);
1108
- continue;
1109
- }
1110
- return;
1111
- }
1112
- }
1113
-
1114
1212
  // src/streams/dumps.ts
1115
1213
  import { createHash } from "node:crypto";
1116
1214
  import { verifyStreamsBulkManifestSignature } from "@secondlayer/shared/streams-bulk-manifest";
@@ -1718,5 +1816,5 @@ export {
1718
1816
  Subgraphs
1719
1817
  };
1720
1818
 
1721
- //# debugId=0E36F58DBAA5692064756E2164756E21
1819
+ //# debugId=2D66AE98BBED076B64756E2164756E21
1722
1820
  //# sourceMappingURL=index.js.map