@unicitylabs/sphere-sdk 0.4.3 → 0.4.5

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.
Files changed (41) hide show
  1. package/dist/connect/index.cjs +10 -10
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.js +10 -10
  4. package/dist/connect/index.js.map +1 -1
  5. package/dist/core/index.cjs +76 -28
  6. package/dist/core/index.cjs.map +1 -1
  7. package/dist/core/index.d.cts +6 -0
  8. package/dist/core/index.d.ts +6 -0
  9. package/dist/core/index.js +76 -28
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/impl/browser/connect/index.cjs +10 -10
  12. package/dist/impl/browser/connect/index.cjs.map +1 -1
  13. package/dist/impl/browser/connect/index.js +10 -10
  14. package/dist/impl/browser/connect/index.js.map +1 -1
  15. package/dist/impl/browser/index.cjs +173 -108
  16. package/dist/impl/browser/index.cjs.map +1 -1
  17. package/dist/impl/browser/index.js +173 -108
  18. package/dist/impl/browser/index.js.map +1 -1
  19. package/dist/impl/browser/ipfs.cjs +10 -10
  20. package/dist/impl/browser/ipfs.cjs.map +1 -1
  21. package/dist/impl/browser/ipfs.js +10 -10
  22. package/dist/impl/browser/ipfs.js.map +1 -1
  23. package/dist/impl/nodejs/connect/index.cjs +10 -10
  24. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  25. package/dist/impl/nodejs/connect/index.js +10 -10
  26. package/dist/impl/nodejs/connect/index.js.map +1 -1
  27. package/dist/impl/nodejs/index.cjs +10 -10
  28. package/dist/impl/nodejs/index.cjs.map +1 -1
  29. package/dist/impl/nodejs/index.js +10 -10
  30. package/dist/impl/nodejs/index.js.map +1 -1
  31. package/dist/index.cjs +76 -28
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +24 -18
  34. package/dist/index.d.ts +24 -18
  35. package/dist/index.js +76 -28
  36. package/dist/index.js.map +1 -1
  37. package/dist/l1/index.cjs +21 -3
  38. package/dist/l1/index.cjs.map +1 -1
  39. package/dist/l1/index.js +21 -3
  40. package/dist/l1/index.js.map +1 -1
  41. package/package.json +1 -1
@@ -2621,6 +2621,7 @@ declare class CommunicationsModule {
2621
2621
  private dmHandlers;
2622
2622
  private composingHandlers;
2623
2623
  private broadcastHandlers;
2624
+ private initializedAt;
2624
2625
  constructor(config?: CommunicationsModuleConfig);
2625
2626
  /**
2626
2627
  * Initialize module with dependencies
@@ -2748,6 +2749,11 @@ declare class GroupChatModule {
2748
2749
  private destroyConnection;
2749
2750
  connect(): Promise<void>;
2750
2751
  getConnectionStatus(): boolean;
2752
+ /**
2753
+ * Refresh subscriptions after load() switched to a different address.
2754
+ * Clears old subscriptions, restores groups if needed, and re-subscribes.
2755
+ */
2756
+ private refreshSubscriptions;
2751
2757
  private doConnect;
2752
2758
  private scheduleReconnect;
2753
2759
  private subscribeToJoinedGroups;
@@ -2621,6 +2621,7 @@ declare class CommunicationsModule {
2621
2621
  private dmHandlers;
2622
2622
  private composingHandlers;
2623
2623
  private broadcastHandlers;
2624
+ private initializedAt;
2624
2625
  constructor(config?: CommunicationsModuleConfig);
2625
2626
  /**
2626
2627
  * Initialize module with dependencies
@@ -2748,6 +2749,11 @@ declare class GroupChatModule {
2748
2749
  private destroyConnection;
2749
2750
  connect(): Promise<void>;
2750
2751
  getConnectionStatus(): boolean;
2752
+ /**
2753
+ * Refresh subscriptions after load() switched to a different address.
2754
+ * Clears old subscriptions, restores groups if needed, and re-subscribes.
2755
+ */
2756
+ private refreshSubscriptions;
2751
2757
  private doConnect;
2752
2758
  private scheduleReconnect;
2753
2759
  private subscribeToJoinedGroups;
@@ -699,6 +699,12 @@ var VestingClassifier = class {
699
699
  };
700
700
  request.onsuccess = (event) => {
701
701
  this.db = event.target.result;
702
+ this.db.onversionchange = () => {
703
+ if (this.db) {
704
+ this.db.close();
705
+ this.db = null;
706
+ }
707
+ };
702
708
  resolve();
703
709
  };
704
710
  request.onerror = () => reject(request.error);
@@ -907,9 +913,21 @@ var VestingClassifier = class {
907
913
  if (typeof indexedDB !== "undefined") {
908
914
  await new Promise((resolve) => {
909
915
  const req = indexedDB.deleteDatabase(this.dbName);
910
- req.onsuccess = () => resolve();
911
- req.onerror = () => resolve();
912
- req.onblocked = () => resolve();
916
+ const timer = setTimeout(() => {
917
+ console.warn(`[VestingClassifier] destroy: deleteDatabase timed out for ${this.dbName}`);
918
+ resolve();
919
+ }, 3e3);
920
+ req.onsuccess = () => {
921
+ clearTimeout(timer);
922
+ resolve();
923
+ };
924
+ req.onerror = () => {
925
+ clearTimeout(timer);
926
+ resolve();
927
+ };
928
+ req.onblocked = () => {
929
+ console.warn(`[VestingClassifier] destroy: deleteDatabase blocked for ${this.dbName}, waiting...`);
930
+ };
913
931
  });
914
932
  }
915
933
  }
@@ -2330,15 +2348,7 @@ var STORAGE_KEYS_GLOBAL = {
2330
2348
  TRACKED_ADDRESSES: "tracked_addresses",
2331
2349
  /** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
2332
2350
  LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
2333
- /** Group chat: joined groups */
2334
- GROUP_CHAT_GROUPS: "group_chat_groups",
2335
- /** Group chat: messages */
2336
- GROUP_CHAT_MESSAGES: "group_chat_messages",
2337
- /** Group chat: members */
2338
- GROUP_CHAT_MEMBERS: "group_chat_members",
2339
- /** Group chat: processed event IDs for deduplication */
2340
- GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events",
2341
- /** Group chat: last used relay URL (stale data detection) */
2351
+ /** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
2342
2352
  GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
2343
2353
  /** Cached token registry JSON (fetched from remote) */
2344
2354
  TOKEN_REGISTRY_CACHE: "token_registry_cache",
@@ -2361,7 +2371,15 @@ var STORAGE_KEYS_ADDRESS = {
2361
2371
  /** Transaction history for this address */
2362
2372
  TRANSACTION_HISTORY: "transaction_history",
2363
2373
  /** Pending V5 finalization tokens (unconfirmed instant split tokens) */
2364
- PENDING_V5_TOKENS: "pending_v5_tokens"
2374
+ PENDING_V5_TOKENS: "pending_v5_tokens",
2375
+ /** Group chat: joined groups for this address */
2376
+ GROUP_CHAT_GROUPS: "group_chat_groups",
2377
+ /** Group chat: messages for this address */
2378
+ GROUP_CHAT_MESSAGES: "group_chat_messages",
2379
+ /** Group chat: members for this address */
2380
+ GROUP_CHAT_MEMBERS: "group_chat_members",
2381
+ /** Group chat: processed event IDs for deduplication */
2382
+ GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
2365
2383
  };
2366
2384
  var STORAGE_KEYS = {
2367
2385
  ...STORAGE_KEYS_GLOBAL,
@@ -7332,6 +7350,8 @@ var CommunicationsModule = class {
7332
7350
  dmHandlers = /* @__PURE__ */ new Set();
7333
7351
  composingHandlers = /* @__PURE__ */ new Set();
7334
7352
  broadcastHandlers = /* @__PURE__ */ new Set();
7353
+ // Timestamp of module initialization — messages older than this are historical
7354
+ initializedAt = 0;
7335
7355
  constructor(config) {
7336
7356
  this.config = {
7337
7357
  autoSave: config?.autoSave ?? true,
@@ -7350,6 +7370,7 @@ var CommunicationsModule = class {
7350
7370
  this.unsubscribeMessages?.();
7351
7371
  this.unsubscribeComposing?.();
7352
7372
  this.deps = deps;
7373
+ this.initializedAt = Date.now();
7353
7374
  this.unsubscribeMessages = deps.transport.onMessage((msg) => {
7354
7375
  this.handleIncomingMessage(msg);
7355
7376
  });
@@ -7641,6 +7662,7 @@ var CommunicationsModule = class {
7641
7662
  // Private: Message Handling
7642
7663
  // ===========================================================================
7643
7664
  handleIncomingMessage(msg) {
7665
+ const isHistorical = msg.timestamp < this.initializedAt;
7644
7666
  if (msg.isSelfWrap && msg.recipientTransportPubkey) {
7645
7667
  if (this.messages.has(msg.id)) return;
7646
7668
  const message2 = {
@@ -7650,7 +7672,7 @@ var CommunicationsModule = class {
7650
7672
  recipientPubkey: msg.recipientTransportPubkey,
7651
7673
  content: msg.content,
7652
7674
  timestamp: msg.timestamp,
7653
- isRead: false
7675
+ isRead: isHistorical
7654
7676
  };
7655
7677
  this.messages.set(message2.id, message2);
7656
7678
  this.deps.emitEvent("message:dm", message2);
@@ -7668,7 +7690,7 @@ var CommunicationsModule = class {
7668
7690
  recipientPubkey: this.deps.identity.chainPubkey,
7669
7691
  content: msg.content,
7670
7692
  timestamp: msg.timestamp,
7671
- isRead: false
7693
+ isRead: isHistorical
7672
7694
  };
7673
7695
  this.messages.set(message.id, message);
7674
7696
  this.deps.emitEvent("message:dm", message);
@@ -7844,22 +7866,24 @@ var GroupChatModule = class {
7844
7866
  async load() {
7845
7867
  this.ensureInitialized();
7846
7868
  const storage = this.deps.storage;
7847
- const groupsJson = await storage.get(STORAGE_KEYS_GLOBAL.GROUP_CHAT_GROUPS);
7869
+ this.groups.clear();
7870
+ this.messages.clear();
7871
+ this.members.clear();
7872
+ this.processedEventIds.clear();
7873
+ const groupsJson = await storage.get(STORAGE_KEYS_ADDRESS.GROUP_CHAT_GROUPS);
7848
7874
  if (groupsJson) {
7849
7875
  try {
7850
7876
  const parsed = JSON.parse(groupsJson);
7851
- this.groups.clear();
7852
7877
  for (const g of parsed) {
7853
7878
  this.groups.set(g.id, g);
7854
7879
  }
7855
7880
  } catch {
7856
7881
  }
7857
7882
  }
7858
- const messagesJson = await storage.get(STORAGE_KEYS_GLOBAL.GROUP_CHAT_MESSAGES);
7883
+ const messagesJson = await storage.get(STORAGE_KEYS_ADDRESS.GROUP_CHAT_MESSAGES);
7859
7884
  if (messagesJson) {
7860
7885
  try {
7861
7886
  const parsed = JSON.parse(messagesJson);
7862
- this.messages.clear();
7863
7887
  for (const m of parsed) {
7864
7888
  const groupId = m.groupId;
7865
7889
  if (!this.messages.has(groupId)) {
@@ -7870,11 +7894,10 @@ var GroupChatModule = class {
7870
7894
  } catch {
7871
7895
  }
7872
7896
  }
7873
- const membersJson = await storage.get(STORAGE_KEYS_GLOBAL.GROUP_CHAT_MEMBERS);
7897
+ const membersJson = await storage.get(STORAGE_KEYS_ADDRESS.GROUP_CHAT_MEMBERS);
7874
7898
  if (membersJson) {
7875
7899
  try {
7876
7900
  const parsed = JSON.parse(membersJson);
7877
- this.members.clear();
7878
7901
  for (const m of parsed) {
7879
7902
  const groupId = m.groupId;
7880
7903
  if (!this.members.has(groupId)) {
@@ -7885,7 +7908,7 @@ var GroupChatModule = class {
7885
7908
  } catch {
7886
7909
  }
7887
7910
  }
7888
- const processedJson = await storage.get(STORAGE_KEYS_GLOBAL.GROUP_CHAT_PROCESSED_EVENTS);
7911
+ const processedJson = await storage.get(STORAGE_KEYS_ADDRESS.GROUP_CHAT_PROCESSED_EVENTS);
7889
7912
  if (processedJson) {
7890
7913
  try {
7891
7914
  const parsed = JSON.parse(processedJson);
@@ -7939,7 +7962,10 @@ var GroupChatModule = class {
7939
7962
  // Connection
7940
7963
  // ===========================================================================
7941
7964
  async connect() {
7942
- if (this.connected) return;
7965
+ if (this.connected) {
7966
+ await this.refreshSubscriptions();
7967
+ return;
7968
+ }
7943
7969
  if (this.connectPromise) {
7944
7970
  return this.connectPromise;
7945
7971
  }
@@ -7953,6 +7979,28 @@ var GroupChatModule = class {
7953
7979
  getConnectionStatus() {
7954
7980
  return this.connected;
7955
7981
  }
7982
+ /**
7983
+ * Refresh subscriptions after load() switched to a different address.
7984
+ * Clears old subscriptions, restores groups if needed, and re-subscribes.
7985
+ */
7986
+ async refreshSubscriptions() {
7987
+ if (!this.client) return;
7988
+ for (const subId of this.subscriptionIds) {
7989
+ try {
7990
+ this.client.unsubscribe(subId);
7991
+ } catch {
7992
+ }
7993
+ }
7994
+ this.subscriptionIds = [];
7995
+ const secretKey = Buffer.from(this.deps.identity.privateKey, "hex");
7996
+ this.keyManager = NostrKeyManager.fromPrivateKey(secretKey);
7997
+ if (this.groups.size === 0) {
7998
+ await this.restoreJoinedGroups();
7999
+ } else {
8000
+ await this.subscribeToJoinedGroups();
8001
+ }
8002
+ this.deps.emitEvent("groupchat:connection", { connected: true });
8003
+ }
7956
8004
  async doConnect() {
7957
8005
  this.ensureInitialized();
7958
8006
  if (!this.keyManager) {
@@ -7968,12 +8016,12 @@ var GroupChatModule = class {
7968
8016
  await this.client.connect(...this.config.relays);
7969
8017
  this.connected = true;
7970
8018
  this.reconnectAttempts = 0;
7971
- this.deps.emitEvent("groupchat:connection", { connected: true });
7972
8019
  if (this.groups.size === 0) {
7973
8020
  await this.restoreJoinedGroups();
7974
8021
  } else {
7975
8022
  await this.subscribeToJoinedGroups();
7976
8023
  }
8024
+ this.deps.emitEvent("groupchat:connection", { connected: true });
7977
8025
  } catch (error) {
7978
8026
  console.error("[GroupChat] Failed to connect to relays", error);
7979
8027
  this.deps.emitEvent("groupchat:connection", { connected: false });
@@ -8956,7 +9004,7 @@ var GroupChatModule = class {
8956
9004
  async persistGroups() {
8957
9005
  if (!this.deps) return;
8958
9006
  const data = Array.from(this.groups.values());
8959
- await this.deps.storage.set(STORAGE_KEYS_GLOBAL.GROUP_CHAT_GROUPS, JSON.stringify(data));
9007
+ await this.deps.storage.set(STORAGE_KEYS_ADDRESS.GROUP_CHAT_GROUPS, JSON.stringify(data));
8960
9008
  }
8961
9009
  async persistMessages() {
8962
9010
  if (!this.deps) return;
@@ -8964,7 +9012,7 @@ var GroupChatModule = class {
8964
9012
  for (const msgs of this.messages.values()) {
8965
9013
  allMessages.push(...msgs);
8966
9014
  }
8967
- await this.deps.storage.set(STORAGE_KEYS_GLOBAL.GROUP_CHAT_MESSAGES, JSON.stringify(allMessages));
9015
+ await this.deps.storage.set(STORAGE_KEYS_ADDRESS.GROUP_CHAT_MESSAGES, JSON.stringify(allMessages));
8968
9016
  }
8969
9017
  async persistMembers() {
8970
9018
  if (!this.deps) return;
@@ -8972,12 +9020,12 @@ var GroupChatModule = class {
8972
9020
  for (const mems of this.members.values()) {
8973
9021
  allMembers.push(...mems);
8974
9022
  }
8975
- await this.deps.storage.set(STORAGE_KEYS_GLOBAL.GROUP_CHAT_MEMBERS, JSON.stringify(allMembers));
9023
+ await this.deps.storage.set(STORAGE_KEYS_ADDRESS.GROUP_CHAT_MEMBERS, JSON.stringify(allMembers));
8976
9024
  }
8977
9025
  async persistProcessedEvents() {
8978
9026
  if (!this.deps) return;
8979
9027
  const arr = Array.from(this.processedEventIds);
8980
- await this.deps.storage.set(STORAGE_KEYS_GLOBAL.GROUP_CHAT_PROCESSED_EVENTS, JSON.stringify(arr));
9028
+ await this.deps.storage.set(STORAGE_KEYS_ADDRESS.GROUP_CHAT_PROCESSED_EVENTS, JSON.stringify(arr));
8981
9029
  }
8982
9030
  // ===========================================================================
8983
9031
  // Private — Relay URL Change Detection