@unicitylabs/sphere-sdk 0.13.2-dev.1 → 0.13.2-dev.2

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.d.cts CHANGED
@@ -447,8 +447,9 @@ interface TokenStorageProvider<TData = unknown> extends BaseProvider {
447
447
  createForAddress?(sharedClient?: unknown): TokenStorageProvider<TData>;
448
448
  /**
449
449
  * Subscribe to storage events
450
- */
451
- onEvent?(callback: StorageEventCallback): () => void;
450
+
451
+ // --- History operations (optional — not supported by all providers, e.g. IPFS) ---
452
+
452
453
  /** Store a history entry (upsert by dedupKey) */
453
454
  addHistoryEntry?(entry: HistoryRecord): Promise<void>;
454
455
  /** Get all history entries sorted by timestamp descending */
@@ -2201,8 +2202,7 @@ declare class PaymentsModule {
2201
2202
  private serverSeenHistoryKeys;
2202
2203
  private incrementalHistoryPulls;
2203
2204
  private hydrationEpoch;
2204
- private storageEventUnsubscribers;
2205
- private syncDebounceTimer;
2205
+ private inventoryDebounceTimer;
2206
2206
  private static readonly SYNC_DEBOUNCE_MS;
2207
2207
  /** Quiet-then-escalate logging for the background wallet-api pumps (#630). */
2208
2208
  private readonly pumpHealth;
@@ -2856,33 +2856,18 @@ declare class PaymentsModule {
2856
2856
  */
2857
2857
  private mintFungibleTokenV2;
2858
2858
  /**
2859
- * Sync local token state with all configured token storage providers (IPFS, file, etc.).
2860
- *
2861
- * For each provider, the local data is packaged into TXF storage format, sent
2862
- * to the provider's `sync()` method, and the merged result is applied locally.
2863
- * Emits `sync:started`, `sync:completed`, and `sync:error` events.
2859
+ * Flush local token state to every configured token storage provider.
2864
2860
  *
2865
- * @returns Summary with counts of tokens added and removed during sync.
2861
+ * Named `sync` for history: it once merged remote TXF state back in, which
2862
+ * only IPFS ever supplied. The remaining providers all implement `sync()` as
2863
+ * "save and return the input unchanged", so this is a write, and the returned
2864
+ * counts are always zero.
2866
2865
  */
2867
2866
  sync(): Promise<{
2868
2867
  added: number;
2869
2868
  removed: number;
2870
2869
  }>;
2871
- private _doSync;
2872
- /**
2873
- * Subscribe to 'storage:remote-updated' events from all token storage providers.
2874
- * When a provider emits this event, a debounced sync is triggered.
2875
- */
2876
- private subscribeToStorageEvents;
2877
- /**
2878
- * Unsubscribe from all storage provider events and clear debounce timer.
2879
- */
2880
- private unsubscribeStorageEvents;
2881
- /**
2882
- * Debounced sync triggered by a storage:remote-updated event.
2883
- * Waits 500ms to batch rapid updates, then performs sync.
2884
- */
2885
- private debouncedSyncFromRemoteUpdate;
2870
+ private _doFlush;
2886
2871
  /**
2887
2872
  * Get all active (non-disabled) token storage providers
2888
2873
  */
@@ -4758,7 +4743,7 @@ interface TrackedAddress extends TrackedAddressEntry {
4758
4743
  /** Primary nametag (from nametag cache, without @ prefix) */
4759
4744
  readonly nametag?: string;
4760
4745
  }
4761
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'transfer:delivery_pending' | 'transfer:invalid' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:expired' | 'payment_request:settling' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'storage:degraded' | 'inventory:conflict' | 'split:checkpoint-stuck' | 'send:partial-remainder' | 'delivery:undeliverable' | 'delivery:deferred' | 'walletapi:session' | 'realtime:status' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated' | 'invoice:created' | 'invoice:payment' | 'invoice:asset_covered' | 'invoice:target_covered' | 'invoice:covered' | 'invoice:closed' | 'invoice:cancelled' | 'invoice:expired' | 'invoice:unknown_reference' | 'invoice:overpayment' | 'invoice:irrelevant' | 'invoice:auto_returned' | 'invoice:auto_return_failed' | 'invoice:return_received' | 'invoice:over_refund_warning' | 'invoice:receipt_sent' | 'invoice:receipt_received' | 'invoice:cancellation_sent' | 'invoice:cancellation_received' | 'swap:proposal_received' | 'swap:proposed' | 'swap:accepted' | 'swap:rejected' | 'swap:announced' | 'swap:deposit_sent' | 'swap:deposit_confirmed' | 'swap:deposits_covered' | 'swap:concluding' | 'swap:payout_received' | 'swap:completed' | 'swap:cancelled' | 'swap:failed' | 'swap:deposit_returned' | 'swap:bounce_received';
4746
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'transfer:delivery_pending' | 'transfer:invalid' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:expired' | 'payment_request:settling' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:error' | 'storage:degraded' | 'inventory:conflict' | 'split:checkpoint-stuck' | 'send:partial-remainder' | 'delivery:undeliverable' | 'delivery:deferred' | 'walletapi:session' | 'realtime:status' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated' | 'invoice:created' | 'invoice:payment' | 'invoice:asset_covered' | 'invoice:target_covered' | 'invoice:covered' | 'invoice:closed' | 'invoice:cancelled' | 'invoice:expired' | 'invoice:unknown_reference' | 'invoice:overpayment' | 'invoice:irrelevant' | 'invoice:auto_returned' | 'invoice:auto_return_failed' | 'invoice:return_received' | 'invoice:over_refund_warning' | 'invoice:receipt_sent' | 'invoice:receipt_received' | 'invoice:cancellation_sent' | 'invoice:cancellation_received' | 'swap:proposal_received' | 'swap:proposed' | 'swap:accepted' | 'swap:rejected' | 'swap:announced' | 'swap:deposit_sent' | 'swap:deposit_confirmed' | 'swap:deposits_covered' | 'swap:concluding' | 'swap:payout_received' | 'swap:completed' | 'swap:cancelled' | 'swap:failed' | 'swap:deposit_returned' | 'swap:bounce_received';
4762
4747
  interface SphereEventMap {
4763
4748
  'transfer:incoming': IncomingTransfer;
4764
4749
  'transfer:confirmed': TransferResult;
@@ -4812,13 +4797,6 @@ interface SphereEventMap {
4812
4797
  source: string;
4813
4798
  count: number;
4814
4799
  };
4815
- 'sync:provider': {
4816
- providerId: string;
4817
- success: boolean;
4818
- added?: number;
4819
- removed?: number;
4820
- error?: string;
4821
- };
4822
4800
  'sync:error': {
4823
4801
  source: string;
4824
4802
  error: string;
package/dist/index.d.ts CHANGED
@@ -447,8 +447,9 @@ interface TokenStorageProvider<TData = unknown> extends BaseProvider {
447
447
  createForAddress?(sharedClient?: unknown): TokenStorageProvider<TData>;
448
448
  /**
449
449
  * Subscribe to storage events
450
- */
451
- onEvent?(callback: StorageEventCallback): () => void;
450
+
451
+ // --- History operations (optional — not supported by all providers, e.g. IPFS) ---
452
+
452
453
  /** Store a history entry (upsert by dedupKey) */
453
454
  addHistoryEntry?(entry: HistoryRecord): Promise<void>;
454
455
  /** Get all history entries sorted by timestamp descending */
@@ -2201,8 +2202,7 @@ declare class PaymentsModule {
2201
2202
  private serverSeenHistoryKeys;
2202
2203
  private incrementalHistoryPulls;
2203
2204
  private hydrationEpoch;
2204
- private storageEventUnsubscribers;
2205
- private syncDebounceTimer;
2205
+ private inventoryDebounceTimer;
2206
2206
  private static readonly SYNC_DEBOUNCE_MS;
2207
2207
  /** Quiet-then-escalate logging for the background wallet-api pumps (#630). */
2208
2208
  private readonly pumpHealth;
@@ -2856,33 +2856,18 @@ declare class PaymentsModule {
2856
2856
  */
2857
2857
  private mintFungibleTokenV2;
2858
2858
  /**
2859
- * Sync local token state with all configured token storage providers (IPFS, file, etc.).
2860
- *
2861
- * For each provider, the local data is packaged into TXF storage format, sent
2862
- * to the provider's `sync()` method, and the merged result is applied locally.
2863
- * Emits `sync:started`, `sync:completed`, and `sync:error` events.
2859
+ * Flush local token state to every configured token storage provider.
2864
2860
  *
2865
- * @returns Summary with counts of tokens added and removed during sync.
2861
+ * Named `sync` for history: it once merged remote TXF state back in, which
2862
+ * only IPFS ever supplied. The remaining providers all implement `sync()` as
2863
+ * "save and return the input unchanged", so this is a write, and the returned
2864
+ * counts are always zero.
2866
2865
  */
2867
2866
  sync(): Promise<{
2868
2867
  added: number;
2869
2868
  removed: number;
2870
2869
  }>;
2871
- private _doSync;
2872
- /**
2873
- * Subscribe to 'storage:remote-updated' events from all token storage providers.
2874
- * When a provider emits this event, a debounced sync is triggered.
2875
- */
2876
- private subscribeToStorageEvents;
2877
- /**
2878
- * Unsubscribe from all storage provider events and clear debounce timer.
2879
- */
2880
- private unsubscribeStorageEvents;
2881
- /**
2882
- * Debounced sync triggered by a storage:remote-updated event.
2883
- * Waits 500ms to batch rapid updates, then performs sync.
2884
- */
2885
- private debouncedSyncFromRemoteUpdate;
2870
+ private _doFlush;
2886
2871
  /**
2887
2872
  * Get all active (non-disabled) token storage providers
2888
2873
  */
@@ -4758,7 +4743,7 @@ interface TrackedAddress extends TrackedAddressEntry {
4758
4743
  /** Primary nametag (from nametag cache, without @ prefix) */
4759
4744
  readonly nametag?: string;
4760
4745
  }
4761
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'transfer:delivery_pending' | 'transfer:invalid' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:expired' | 'payment_request:settling' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'storage:degraded' | 'inventory:conflict' | 'split:checkpoint-stuck' | 'send:partial-remainder' | 'delivery:undeliverable' | 'delivery:deferred' | 'walletapi:session' | 'realtime:status' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated' | 'invoice:created' | 'invoice:payment' | 'invoice:asset_covered' | 'invoice:target_covered' | 'invoice:covered' | 'invoice:closed' | 'invoice:cancelled' | 'invoice:expired' | 'invoice:unknown_reference' | 'invoice:overpayment' | 'invoice:irrelevant' | 'invoice:auto_returned' | 'invoice:auto_return_failed' | 'invoice:return_received' | 'invoice:over_refund_warning' | 'invoice:receipt_sent' | 'invoice:receipt_received' | 'invoice:cancellation_sent' | 'invoice:cancellation_received' | 'swap:proposal_received' | 'swap:proposed' | 'swap:accepted' | 'swap:rejected' | 'swap:announced' | 'swap:deposit_sent' | 'swap:deposit_confirmed' | 'swap:deposits_covered' | 'swap:concluding' | 'swap:payout_received' | 'swap:completed' | 'swap:cancelled' | 'swap:failed' | 'swap:deposit_returned' | 'swap:bounce_received';
4746
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'transfer:delivery_pending' | 'transfer:invalid' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:expired' | 'payment_request:settling' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:error' | 'storage:degraded' | 'inventory:conflict' | 'split:checkpoint-stuck' | 'send:partial-remainder' | 'delivery:undeliverable' | 'delivery:deferred' | 'walletapi:session' | 'realtime:status' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated' | 'invoice:created' | 'invoice:payment' | 'invoice:asset_covered' | 'invoice:target_covered' | 'invoice:covered' | 'invoice:closed' | 'invoice:cancelled' | 'invoice:expired' | 'invoice:unknown_reference' | 'invoice:overpayment' | 'invoice:irrelevant' | 'invoice:auto_returned' | 'invoice:auto_return_failed' | 'invoice:return_received' | 'invoice:over_refund_warning' | 'invoice:receipt_sent' | 'invoice:receipt_received' | 'invoice:cancellation_sent' | 'invoice:cancellation_received' | 'swap:proposal_received' | 'swap:proposed' | 'swap:accepted' | 'swap:rejected' | 'swap:announced' | 'swap:deposit_sent' | 'swap:deposit_confirmed' | 'swap:deposits_covered' | 'swap:concluding' | 'swap:payout_received' | 'swap:completed' | 'swap:cancelled' | 'swap:failed' | 'swap:deposit_returned' | 'swap:bounce_received';
4762
4747
  interface SphereEventMap {
4763
4748
  'transfer:incoming': IncomingTransfer;
4764
4749
  'transfer:confirmed': TransferResult;
@@ -4812,13 +4797,6 @@ interface SphereEventMap {
4812
4797
  source: string;
4813
4798
  count: number;
4814
4799
  };
4815
- 'sync:provider': {
4816
- providerId: string;
4817
- success: boolean;
4818
- added?: number;
4819
- removed?: number;
4820
- error?: string;
4821
- };
4822
4800
  'sync:error': {
4823
4801
  source: string;
4824
4802
  error: string;
package/dist/index.js CHANGED
@@ -11595,8 +11595,7 @@ var PaymentsModule = class _PaymentsModule {
11595
11595
  incrementalHistoryPulls = 0;
11596
11596
  hydrationEpoch = 0;
11597
11597
  // Storage event subscriptions (push-based sync)
11598
- storageEventUnsubscribers = [];
11599
- syncDebounceTimer = null;
11598
+ inventoryDebounceTimer = null;
11600
11599
  static SYNC_DEBOUNCE_MS = 500;
11601
11600
  /** Quiet-then-escalate logging for the background wallet-api pumps (#630). */
11602
11601
  pumpHealth = new PumpHealth();
@@ -11721,7 +11720,6 @@ var PaymentsModule = class _PaymentsModule {
11721
11720
  assertLegalCustodyComposition(deps);
11722
11721
  this.teardownDeliveryPump();
11723
11722
  this.teardownPaymentRequestPump();
11724
- this.unsubscribeStorageEvents();
11725
11723
  for (const [, resolver] of this.pendingResponseResolvers) {
11726
11724
  clearTimeout(resolver.timeout);
11727
11725
  resolver.reject(new Error("Address switched"));
@@ -11790,7 +11788,6 @@ var PaymentsModule = class _PaymentsModule {
11790
11788
  this.pumpHealth.run("payment-requests", () => this.pumpPaymentRequests());
11791
11789
  }, DELIVERY_POLL_INTERVAL_MS);
11792
11790
  }
11793
- this.subscribeToStorageEvents();
11794
11791
  }
11795
11792
  /**
11796
11793
  * Load all token data from storage providers and restore wallet state.
@@ -11963,7 +11960,6 @@ var PaymentsModule = class _PaymentsModule {
11963
11960
  this.reservationLedger.clear();
11964
11961
  this.parsedTokenCache.clear();
11965
11962
  this.tokens.clear();
11966
- this.unsubscribeStorageEvents();
11967
11963
  }
11968
11964
  // ===========================================================================
11969
11965
  // Public API - Send
@@ -13957,115 +13953,29 @@ var PaymentsModule = class _PaymentsModule {
13957
13953
  // Public API - Sync & Validate
13958
13954
  // ===========================================================================
13959
13955
  /**
13960
- * Sync local token state with all configured token storage providers (IPFS, file, etc.).
13956
+ * Flush local token state to every configured token storage provider.
13961
13957
  *
13962
- * For each provider, the local data is packaged into TXF storage format, sent
13963
- * to the provider's `sync()` method, and the merged result is applied locally.
13964
- * Emits `sync:started`, `sync:completed`, and `sync:error` events.
13965
- *
13966
- * @returns Summary with counts of tokens added and removed during sync.
13958
+ * Named `sync` for history: it once merged remote TXF state back in, which
13959
+ * only IPFS ever supplied. The remaining providers all implement `sync()` as
13960
+ * "save and return the input unchanged", so this is a write, and the returned
13961
+ * counts are always zero.
13967
13962
  */
13968
13963
  async sync() {
13969
13964
  this.ensureInitialized();
13970
- if (this._syncInProgress) {
13971
- return this._syncInProgress;
13972
- }
13973
- this._syncInProgress = this._doSync();
13965
+ if (this._syncInProgress) return this._syncInProgress;
13966
+ this._syncInProgress = this._doFlush();
13974
13967
  try {
13975
13968
  return await this._syncInProgress;
13976
13969
  } finally {
13977
13970
  this._syncInProgress = null;
13978
13971
  }
13979
13972
  }
13980
- async _doSync() {
13973
+ async _doFlush() {
13981
13974
  this.deps.emitEvent("sync:started", { source: "payments" });
13982
13975
  try {
13983
- const providers = this.getTokenStorageProviders();
13984
- if (providers.size === 0) {
13985
- await this.save();
13986
- this.deps.emitEvent("sync:completed", {
13987
- source: "payments",
13988
- count: this.tokens.size
13989
- });
13990
- return { added: 0, removed: 0 };
13991
- }
13992
- const localData = await this.createStorageData();
13993
- let totalAdded = 0;
13994
- let totalRemoved = 0;
13995
- const savedNametags = [...this.nametags];
13996
- for (const [providerId, provider] of providers) {
13997
- try {
13998
- const result = await provider.sync(localData);
13999
- if (result.success && result.merged) {
14000
- const mergedMeta = result.merged?._meta;
14001
- const currentChain = this.deps.identity.chainPubkey;
14002
- const isLegacyAlpha = mergedMeta?.address?.startsWith("alpha1") ?? false;
14003
- if (mergedMeta?.address && currentChain && !isLegacyAlpha && mergedMeta.address !== currentChain) {
14004
- logger.warn("Payments", `Sync: rejecting data from provider ${providerId} \u2014 address mismatch (got=${mergedMeta.address.slice(0, 20)}... expected=${currentChain.slice(0, 20)}...)`);
14005
- continue;
14006
- }
14007
- const savedTokens = new Map(this.tokens);
14008
- this.loadFromStorageData(result.merged);
14009
- const existingGenesisIds = /* @__PURE__ */ new Set();
14010
- for (const existing of this.tokens.values()) {
14011
- const gid = extractTokenIdFromSdkData(existing.sdkData);
14012
- if (gid) existingGenesisIds.add(gid);
14013
- }
14014
- let restoredCount = 0;
14015
- for (const [tokenId, token] of savedTokens) {
14016
- if (this.tokens.has(tokenId)) continue;
14017
- const sdkTokenId = extractTokenIdFromSdkData(token.sdkData);
14018
- const stateHash = extractStateHashFromSdkData(token.sdkData);
14019
- if (sdkTokenId && stateHash && this.isStateTombstoned(sdkTokenId, stateHash)) {
14020
- continue;
14021
- }
14022
- if (sdkTokenId && existingGenesisIds.has(sdkTokenId)) {
14023
- continue;
14024
- }
14025
- this.tokens.set(tokenId, token);
14026
- if (sdkTokenId) existingGenesisIds.add(sdkTokenId);
14027
- restoredCount++;
14028
- }
14029
- if (restoredCount > 0) {
14030
- logger.debug("Payments", `Sync: restored ${restoredCount} token(s) lost by loadFromStorageData`);
14031
- }
14032
- if (this.nametags.length === 0 && savedNametags.length > 0) {
14033
- this.nametags = savedNametags;
14034
- }
14035
- await this.rebuildParsedTokenCache();
14036
- const txfData = result.merged;
14037
- if (txfData._history && txfData._history.length > 0) {
14038
- const imported = await this.importRemoteHistoryEntries(txfData._history);
14039
- if (imported > 0) {
14040
- logger.debug("Payments", `Imported ${imported} history entries from IPFS sync`);
14041
- }
14042
- }
14043
- totalAdded += result.added;
14044
- totalRemoved += result.removed;
14045
- }
14046
- this.deps.emitEvent("sync:provider", {
14047
- providerId,
14048
- success: result.success,
14049
- added: result.added,
14050
- removed: result.removed
14051
- });
14052
- } catch (providerError) {
14053
- logger.warn("Payments", `Sync failed for provider ${providerId}:`, providerError);
14054
- this.deps.emitEvent("sync:provider", {
14055
- providerId,
14056
- success: false,
14057
- error: providerError instanceof Error ? providerError.message : String(providerError)
14058
- });
14059
- }
14060
- }
14061
- if (totalAdded > 0 || totalRemoved > 0) {
14062
- await this.save();
14063
- }
14064
- this.deps.emitEvent("sync:completed", {
14065
- source: "payments",
14066
- count: this.tokens.size
14067
- });
14068
- return { added: totalAdded, removed: totalRemoved };
13976
+ await this.save();
13977
+ this.deps.emitEvent("sync:completed", { source: "payments", count: this.tokens.size });
13978
+ return { added: 0, removed: 0 };
14069
13979
  } catch (error) {
14070
13980
  this.deps.emitEvent("sync:error", {
14071
13981
  source: "payments",
@@ -14074,66 +13984,6 @@ var PaymentsModule = class _PaymentsModule {
14074
13984
  throw error;
14075
13985
  }
14076
13986
  }
14077
- // ===========================================================================
14078
- // Storage Event Subscription (Push-Based Sync)
14079
- // ===========================================================================
14080
- /**
14081
- * Subscribe to 'storage:remote-updated' events from all token storage providers.
14082
- * When a provider emits this event, a debounced sync is triggered.
14083
- */
14084
- subscribeToStorageEvents() {
14085
- this.unsubscribeStorageEvents();
14086
- const providers = this.getTokenStorageProviders();
14087
- for (const [providerId, provider] of providers) {
14088
- if (provider.onEvent) {
14089
- const unsub = provider.onEvent((event) => {
14090
- if (event.type === "storage:remote-updated") {
14091
- logger.debug("Payments", "Remote update detected from provider", providerId, event.data);
14092
- this.debouncedSyncFromRemoteUpdate(providerId, event.data);
14093
- }
14094
- });
14095
- this.storageEventUnsubscribers.push(unsub);
14096
- }
14097
- }
14098
- }
14099
- /**
14100
- * Unsubscribe from all storage provider events and clear debounce timer.
14101
- */
14102
- unsubscribeStorageEvents() {
14103
- for (const unsub of this.storageEventUnsubscribers) {
14104
- unsub();
14105
- }
14106
- this.storageEventUnsubscribers = [];
14107
- if (this.syncDebounceTimer) {
14108
- clearTimeout(this.syncDebounceTimer);
14109
- this.syncDebounceTimer = null;
14110
- }
14111
- }
14112
- /**
14113
- * Debounced sync triggered by a storage:remote-updated event.
14114
- * Waits 500ms to batch rapid updates, then performs sync.
14115
- */
14116
- debouncedSyncFromRemoteUpdate(providerId, eventData) {
14117
- if (this.syncDebounceTimer) {
14118
- clearTimeout(this.syncDebounceTimer);
14119
- }
14120
- this.syncDebounceTimer = setTimeout(() => {
14121
- this.syncDebounceTimer = null;
14122
- this.sync().then((result) => {
14123
- const data = eventData;
14124
- this.deps?.emitEvent("sync:remote-update", {
14125
- providerId,
14126
- name: data?.name ?? "",
14127
- sequence: data?.sequence ?? 0,
14128
- cid: data?.cid ?? "",
14129
- added: result.added,
14130
- removed: result.removed
14131
- });
14132
- }).catch((err) => {
14133
- logger.debug("Payments", "Auto-sync from remote update failed:", err);
14134
- });
14135
- }, _PaymentsModule.SYNC_DEBOUNCE_MS);
14136
- }
14137
13987
  /**
14138
13988
  * Get all active (non-disabled) token storage providers
14139
13989
  */
@@ -14178,7 +14028,6 @@ var PaymentsModule = class _PaymentsModule {
14178
14028
  updateTokenStorageProviders(providers) {
14179
14029
  if (this.deps) {
14180
14030
  this.deps.tokenStorageProviders = providers;
14181
- this.subscribeToStorageEvents();
14182
14031
  }
14183
14032
  }
14184
14033
  /**
@@ -14340,6 +14189,10 @@ var PaymentsModule = class _PaymentsModule {
14340
14189
  teardownDeliveryPump() {
14341
14190
  this.deliveryWakeUnsub?.();
14342
14191
  this.deliveryWakeUnsub = null;
14192
+ if (this.inventoryDebounceTimer !== null) {
14193
+ clearTimeout(this.inventoryDebounceTimer);
14194
+ this.inventoryDebounceTimer = null;
14195
+ }
14343
14196
  if (this.deliveryPollTimer !== null) {
14344
14197
  clearInterval(this.deliveryPollTimer);
14345
14198
  this.deliveryPollTimer = null;
@@ -14379,11 +14232,11 @@ var PaymentsModule = class _PaymentsModule {
14379
14232
  * without waiting for the next poll tick.
14380
14233
  */
14381
14234
  debouncedInventorySyncFromWake() {
14382
- if (this.syncDebounceTimer) {
14383
- clearTimeout(this.syncDebounceTimer);
14235
+ if (this.inventoryDebounceTimer) {
14236
+ clearTimeout(this.inventoryDebounceTimer);
14384
14237
  }
14385
- this.syncDebounceTimer = setTimeout(() => {
14386
- this.syncDebounceTimer = null;
14238
+ this.inventoryDebounceTimer = setTimeout(() => {
14239
+ this.inventoryDebounceTimer = null;
14387
14240
  this.pumpHealth.run("inventory", () => this.resyncInventory(true));
14388
14241
  }, _PaymentsModule.SYNC_DEBOUNCE_MS);
14389
14242
  }
@@ -30526,16 +30379,6 @@ var Sphere = class _Sphere {
30526
30379
  });
30527
30380
  if (unsub) this._providerEventCleanups.push(unsub);
30528
30381
  }
30529
- for (const [providerId, provider] of this._tokenStorageProviders) {
30530
- if (typeof provider.onEvent === "function") {
30531
- const unsub = provider.onEvent((event) => {
30532
- if (event.type === "storage:error" || event.type === "sync:error") {
30533
- this.emitConnectionChanged(providerId, provider.isConnected(), provider.getStatus(), event.error);
30534
- }
30535
- });
30536
- if (unsub) this._providerEventCleanups.push(unsub);
30537
- }
30538
- }
30539
30382
  }
30540
30383
  /**
30541
30384
  * Emit connection:changed with deduplication — only emits if status actually changed.