@interfold/sdk 0.12.0 → 0.13.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/dist/index.cjs CHANGED
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  FailureReason: () => FailureReason,
41
41
  InterfoldEventType: () => InterfoldEventType,
42
42
  InterfoldSDK: () => InterfoldSDK,
43
+ RandomnessProviderEventType: () => RandomnessProviderEventType,
43
44
  RegistryEventType: () => RegistryEventType,
44
45
  SDKError: () => SDKError,
45
46
  ThresholdBfvParamsPresetNames: () => ThresholdBfvParamsPresetNames,
@@ -547,6 +548,8 @@ var InterfoldEventType = /* @__PURE__ */ ((InterfoldEventType2) => {
547
548
  })(InterfoldEventType || {});
548
549
  var RegistryEventType = /* @__PURE__ */ ((RegistryEventType2) => {
549
550
  RegistryEventType2["COMMITTEE_REQUESTED"] = "CommitteeRequested";
551
+ RegistryEventType2["COMMITTEE_RANDOMNESS_REQUESTED"] = "CommitteeRandomnessRequested";
552
+ RegistryEventType2["RANDOMNESS_CIRCUIT_BREAKER_TRIPPED"] = "RandomnessCircuitBreakerTripped";
550
553
  RegistryEventType2["COMMITTEE_PUBLISHED"] = "CommitteePublished";
551
554
  RegistryEventType2["COMMITTEE_FINALIZED"] = "SortitionCommitteeFinalized";
552
555
  RegistryEventType2["INTERFOLD_SET"] = "InterfoldSet";
@@ -554,11 +557,20 @@ var RegistryEventType = /* @__PURE__ */ ((RegistryEventType2) => {
554
557
  RegistryEventType2["INITIALIZED"] = "Initialized";
555
558
  return RegistryEventType2;
556
559
  })(RegistryEventType || {});
560
+ var RandomnessProviderEventType = /* @__PURE__ */ ((RandomnessProviderEventType2) => {
561
+ RandomnessProviderEventType2["RANDOMNESS_FULFILLED"] = "RandomnessFulfilled";
562
+ return RandomnessProviderEventType2;
563
+ })(RandomnessProviderEventType || {});
557
564
 
558
565
  // src/events/event-listener.ts
559
566
  var EventListener = class _EventListener {
567
+ static DEFAULT_HISTORICAL_BLOCK_RANGE = 10000n;
568
+ static MAX_REMEMBERED_LOGS = 1e4;
560
569
  listeners = /* @__PURE__ */ new Map();
561
570
  activeWatchers = /* @__PURE__ */ new Map();
571
+ watcherStartBlocks = /* @__PURE__ */ new Map();
572
+ randomnessProviderListeners = /* @__PURE__ */ new Map();
573
+ seenLiveLogs = /* @__PURE__ */ new Map();
562
574
  isPolling = false;
563
575
  lastBlockNumber = BigInt(0);
564
576
  publicClient;
@@ -575,6 +587,8 @@ var EventListener = class _EventListener {
575
587
  // runtime; those default to the Interfold contract.
576
588
  static REGISTRY_ONLY_EVENTS = /* @__PURE__ */ new Set([
577
589
  "CommitteeRequested" /* COMMITTEE_REQUESTED */,
590
+ "CommitteeRandomnessRequested" /* COMMITTEE_RANDOMNESS_REQUESTED */,
591
+ "RandomnessCircuitBreakerTripped" /* RANDOMNESS_CIRCUIT_BREAKER_TRIPPED */,
578
592
  "CommitteePublished" /* COMMITTEE_PUBLISHED */,
579
593
  "SortitionCommitteeFinalized" /* COMMITTEE_FINALIZED */,
580
594
  "InterfoldSet" /* INTERFOLD_SET */
@@ -590,6 +604,93 @@ var EventListener = class _EventListener {
590
604
  const { address, abi } = this.resolveContract(eventType);
591
605
  return this.watchContractEvent(address, eventType, abi, callback);
592
606
  }
607
+ async onRandomnessProviderEvent(provider, eventType, callback, fromBlock) {
608
+ const listenerKey = `${provider.toLowerCase()}:${eventType}`;
609
+ const watcherKey = `randomness-provider:${listenerKey}`;
610
+ const requestedStartBlock = fromBlock ?? this.config.fromBlock;
611
+ let callbacks = this.randomnessProviderListeners.get(listenerKey);
612
+ if (!callbacks) {
613
+ callbacks = /* @__PURE__ */ new Set();
614
+ this.randomnessProviderListeners.set(listenerKey, callbacks);
615
+ }
616
+ if (this.activeWatchers.has(watcherKey)) {
617
+ const activeStartBlock = this.watcherStartBlocks.get(watcherKey);
618
+ if (fromBlock !== void 0 && requestedStartBlock !== activeStartBlock) {
619
+ throw new SDKError(
620
+ `Randomness provider watcher for ${eventType} on ${provider} already starts at ${activeStartBlock ?? "latest"}; requested ${requestedStartBlock ?? "latest"}`,
621
+ "INVALID_EVENT_CONFIG"
622
+ );
623
+ }
624
+ callbacks.add(callback);
625
+ return;
626
+ }
627
+ callbacks.add(callback);
628
+ try {
629
+ const unwatch = this.publicClient.watchContractEvent({
630
+ address: provider,
631
+ abi: import_types3.IRandomnessProvider__factory.abi,
632
+ eventName: eventType,
633
+ fromBlock: requestedStartBlock,
634
+ onLogs: (logs) => {
635
+ for (const log of logs) {
636
+ if (!this.rememberLiveLog(log)) continue;
637
+ const event = {
638
+ type: eventType,
639
+ data: log.args,
640
+ provider,
641
+ log,
642
+ timestamp: /* @__PURE__ */ new Date(),
643
+ blockNumber: log.blockNumber ?? 0n,
644
+ transactionHash: log.transactionHash ?? "0x"
645
+ };
646
+ const currentCallbacks = this.randomnessProviderListeners.get(listenerKey);
647
+ currentCallbacks?.forEach((currentCallback) => {
648
+ try {
649
+ const result = currentCallback(event);
650
+ if (result) {
651
+ void result.catch((error) => {
652
+ console.error(`Error in randomness provider callback for ${eventType}:`, error);
653
+ });
654
+ }
655
+ } catch (error) {
656
+ console.error(`Error in randomness provider callback for ${eventType}:`, error);
657
+ }
658
+ });
659
+ }
660
+ }
661
+ });
662
+ this.activeWatchers.set(watcherKey, unwatch);
663
+ this.watcherStartBlocks.set(watcherKey, requestedStartBlock);
664
+ } catch (error) {
665
+ callbacks.delete(callback);
666
+ if (callbacks.size === 0) this.randomnessProviderListeners.delete(listenerKey);
667
+ throw new SDKError(`Failed to watch randomness provider event ${eventType} on ${provider}: ${error}`, "WATCH_EVENT_FAILED");
668
+ }
669
+ }
670
+ offRandomnessProviderEvent(provider, eventType, callback) {
671
+ const listenerKey = `${provider.toLowerCase()}:${eventType}`;
672
+ const callbacks = this.randomnessProviderListeners.get(listenerKey);
673
+ callbacks?.delete(callback);
674
+ if (callbacks && callbacks.size === 0) {
675
+ this.randomnessProviderListeners.delete(listenerKey);
676
+ const watcherKey = `randomness-provider:${listenerKey}`;
677
+ const unwatch = this.activeWatchers.get(watcherKey);
678
+ if (unwatch) unwatch();
679
+ this.activeWatchers.delete(watcherKey);
680
+ this.watcherStartBlocks.delete(watcherKey);
681
+ }
682
+ }
683
+ async getHistoricalRandomnessProviderEvents(provider, eventType, fromBlock, toBlock) {
684
+ const start = fromBlock ?? this.config.fromBlock;
685
+ if (start === void 0) {
686
+ throw new SDKError("Randomness provider history requires fromBlock or EventListenerConfig.fromBlock", "INVALID_EVENT_CONFIG");
687
+ }
688
+ try {
689
+ return await this.getHistoricalContractEvents(provider, import_types3.IRandomnessProvider__factory.abi, eventType, start, toBlock);
690
+ } catch (error) {
691
+ throw new SDKError(`Failed to get randomness provider events from ${provider}: ${error}`, "HISTORICAL_EVENTS_FAILED");
692
+ }
693
+ }
593
694
  async once(type, callback) {
594
695
  const handler = (event) => {
595
696
  this.off(type, handler);
@@ -618,6 +719,7 @@ var EventListener = class _EventListener {
618
719
  for (let i = 0; i < logs.length; i++) {
619
720
  const log = logs[i];
620
721
  if (!log) break;
722
+ if (!emitter.rememberLiveLog(log)) continue;
621
723
  const event = {
622
724
  type: eventType,
623
725
  data: log.args,
@@ -671,13 +773,7 @@ var EventListener = class _EventListener {
671
773
  async getHistoricalEvents(eventType, fromBlock, toBlock) {
672
774
  const { address, abi } = this.resolveContract(eventType);
673
775
  try {
674
- return await this.publicClient.getContractEvents({
675
- address,
676
- abi,
677
- eventName: eventType,
678
- fromBlock: fromBlock ?? this.config.fromBlock,
679
- toBlock: toBlock ?? this.config.toBlock
680
- });
776
+ return await this.getHistoricalContractEvents(address, abi, eventType, fromBlock, toBlock);
681
777
  } catch (error) {
682
778
  throw new SDKError(`Failed to get historical events: ${error}`, "HISTORICAL_EVENTS_FAILED");
683
779
  }
@@ -736,7 +832,65 @@ var EventListener = class _EventListener {
736
832
  }
737
833
  });
738
834
  this.activeWatchers.clear();
835
+ this.watcherStartBlocks.clear();
739
836
  this.listeners.clear();
837
+ this.randomnessProviderListeners.clear();
838
+ this.seenLiveLogs.clear();
839
+ }
840
+ logIdentity(log) {
841
+ if (log.blockHash && log.transactionHash && log.logIndex !== null && log.logIndex !== void 0) {
842
+ return `${log.blockHash}:${log.transactionHash}:${log.logIndex}:${Boolean(log.removed)}`;
843
+ }
844
+ return void 0;
845
+ }
846
+ rememberLiveLog(log) {
847
+ const identity = this.logIdentity(log);
848
+ if (!identity) return true;
849
+ if (this.seenLiveLogs.has(identity)) return false;
850
+ this.seenLiveLogs.set(identity, true);
851
+ if (this.seenLiveLogs.size > _EventListener.MAX_REMEMBERED_LOGS) {
852
+ const oldest = this.seenLiveLogs.keys().next().value;
853
+ if (oldest !== void 0) this.seenLiveLogs.delete(oldest);
854
+ }
855
+ return true;
856
+ }
857
+ async getHistoricalContractEvents(address, abi, eventName, fromBlock, toBlock) {
858
+ const start = fromBlock ?? this.config.fromBlock;
859
+ const configuredEnd = toBlock ?? this.config.toBlock;
860
+ if (start === void 0) {
861
+ return await this.publicClient.getContractEvents({
862
+ address,
863
+ abi,
864
+ eventName,
865
+ toBlock: configuredEnd
866
+ });
867
+ }
868
+ const end = configuredEnd ?? await this.publicClient.getBlockNumber({ cacheTime: 0 });
869
+ if (end < start) return [];
870
+ const range = this.config.historicalBlockRange ?? _EventListener.DEFAULT_HISTORICAL_BLOCK_RANGE;
871
+ if (range <= 0n) throw new SDKError("Historical block range must be greater than zero", "INVALID_EVENT_CONFIG");
872
+ const logs = [];
873
+ const seen = /* @__PURE__ */ new Set();
874
+ for (let cursor = start; cursor <= end; cursor += range) {
875
+ const chunkEnd = cursor + range - 1n < end ? cursor + range - 1n : end;
876
+ const chunk = await this.publicClient.getContractEvents({
877
+ address,
878
+ abi,
879
+ eventName,
880
+ fromBlock: cursor,
881
+ toBlock: chunkEnd
882
+ });
883
+ for (const log of chunk) {
884
+ const identity = this.logIdentity(log);
885
+ if (identity && seen.has(identity)) continue;
886
+ if (identity) {
887
+ seen.add(identity);
888
+ this.rememberLiveLog(log);
889
+ }
890
+ logs.push(log);
891
+ }
892
+ }
893
+ return logs;
740
894
  }
741
895
  async pollForEvents() {
742
896
  while (this.isPolling) {
@@ -1102,6 +1256,15 @@ var InterfoldSDK = class _InterfoldSDK {
1102
1256
  async onInterfoldEvent(eventType, callback) {
1103
1257
  return this.eventListener.onInterfoldEvent(eventType, callback);
1104
1258
  }
1259
+ async onRandomnessProviderEvent(provider, eventType, callback, fromBlock) {
1260
+ return this.eventListener.onRandomnessProviderEvent(provider, eventType, callback, fromBlock);
1261
+ }
1262
+ offRandomnessProviderEvent(provider, eventType, callback) {
1263
+ this.eventListener.offRandomnessProviderEvent(provider, eventType, callback);
1264
+ }
1265
+ async getHistoricalRandomnessProviderEvents(provider, eventType, fromBlock, toBlock) {
1266
+ return this.eventListener.getHistoricalRandomnessProviderEvents(provider, eventType, fromBlock, toBlock);
1267
+ }
1105
1268
  off(eventType, callback) {
1106
1269
  this.eventListener.off(eventType, callback);
1107
1270
  }
@@ -1161,6 +1324,7 @@ var InterfoldSDK = class _InterfoldSDK {
1161
1324
  FailureReason,
1162
1325
  InterfoldEventType,
1163
1326
  InterfoldSDK,
1327
+ RandomnessProviderEventType,
1164
1328
  RegistryEventType,
1165
1329
  SDKError,
1166
1330
  ThresholdBfvParamsPresetNames,