@unicitylabs/sphere-sdk 0.4.0 → 0.4.3

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.
@@ -2419,6 +2419,13 @@ declare class PaymentsModule {
2419
2419
  * Remove all nametag data from memory and storage.
2420
2420
  */
2421
2421
  clearNametag(): Promise<void>;
2422
+ /**
2423
+ * Reload nametag data from storage providers into memory.
2424
+ *
2425
+ * Used as a recovery mechanism when `this.nametags` is unexpectedly empty
2426
+ * (e.g., wiped by sync or race condition) but nametag data exists in storage.
2427
+ */
2428
+ private reloadNametagsFromStorage;
2422
2429
  /**
2423
2430
  * Mint a nametag token on-chain (like Sphere wallet and lottery)
2424
2431
  * This creates the nametag token required for receiving tokens via PROXY addresses
@@ -2419,6 +2419,13 @@ declare class PaymentsModule {
2419
2419
  * Remove all nametag data from memory and storage.
2420
2420
  */
2421
2421
  clearNametag(): Promise<void>;
2422
+ /**
2423
+ * Reload nametag data from storage providers into memory.
2424
+ *
2425
+ * Used as a recovery mechanism when `this.nametags` is unexpectedly empty
2426
+ * (e.g., wiped by sync or race condition) but nametag data exists in storage.
2427
+ */
2428
+ private reloadNametagsFromStorage;
2422
2429
  /**
2423
2430
  * Mint a nametag token on-chain (like Sphere wallet and lottery)
2424
2431
  * This creates the nametag token required for receiving tokens via PROXY addresses
@@ -6280,6 +6280,29 @@ var PaymentsModule = class _PaymentsModule {
6280
6280
  this.nametags = [];
6281
6281
  await this.save();
6282
6282
  }
6283
+ /**
6284
+ * Reload nametag data from storage providers into memory.
6285
+ *
6286
+ * Used as a recovery mechanism when `this.nametags` is unexpectedly empty
6287
+ * (e.g., wiped by sync or race condition) but nametag data exists in storage.
6288
+ */
6289
+ async reloadNametagsFromStorage() {
6290
+ const providers = this.getTokenStorageProviders();
6291
+ for (const [, provider] of providers) {
6292
+ try {
6293
+ const result = await provider.load();
6294
+ if (result.success && result.data) {
6295
+ const parsed = parseTxfStorageData(result.data);
6296
+ if (parsed.nametags.length > 0) {
6297
+ this.nametags = parsed.nametags;
6298
+ this.log(`Reloaded ${parsed.nametags.length} nametag(s) from storage`);
6299
+ return;
6300
+ }
6301
+ }
6302
+ } catch {
6303
+ }
6304
+ }
6305
+ }
6283
6306
  /**
6284
6307
  * Mint a nametag token on-chain (like Sphere wallet and lottery)
6285
6308
  * This creates the nametag token required for receiving tokens via PROXY addresses
@@ -6404,11 +6427,15 @@ var PaymentsModule = class _PaymentsModule {
6404
6427
  const localData = await this.createStorageData();
6405
6428
  let totalAdded = 0;
6406
6429
  let totalRemoved = 0;
6430
+ const savedNametags = [...this.nametags];
6407
6431
  for (const [providerId, provider] of providers) {
6408
6432
  try {
6409
6433
  const result = await provider.sync(localData);
6410
6434
  if (result.success && result.merged) {
6411
6435
  this.loadFromStorageData(result.merged);
6436
+ if (this.nametags.length === 0 && savedNametags.length > 0) {
6437
+ this.nametags = savedNametags;
6438
+ }
6412
6439
  totalAdded += result.added;
6413
6440
  totalRemoved += result.removed;
6414
6441
  }
@@ -6796,7 +6823,12 @@ var PaymentsModule = class _PaymentsModule {
6796
6823
  let nametagTokens = [];
6797
6824
  if (addressScheme === AddressScheme.PROXY) {
6798
6825
  const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
6799
- const proxyNametag = this.getNametag();
6826
+ let proxyNametag = this.getNametag();
6827
+ if (!proxyNametag?.token) {
6828
+ this.log("Nametag missing in memory, attempting reload from storage...");
6829
+ await this.reloadNametagsFromStorage();
6830
+ proxyNametag = this.getNametag();
6831
+ }
6800
6832
  if (!proxyNametag?.token) {
6801
6833
  throw new Error("Cannot finalize PROXY transfer - no nametag token");
6802
6834
  }
@@ -7401,13 +7433,14 @@ var CommunicationsModule = class {
7401
7433
  */
7402
7434
  async sendDM(recipient, content) {
7403
7435
  this.ensureInitialized();
7404
- const recipientPubkey = await this.resolveRecipient(recipient);
7405
- const eventId = await this.deps.transport.sendMessage(recipientPubkey, content);
7436
+ const resolved = await this.resolveRecipient(recipient);
7437
+ const eventId = await this.deps.transport.sendMessage(resolved.pubkey, content);
7406
7438
  const message = {
7407
7439
  id: eventId,
7408
7440
  senderPubkey: this.deps.identity.chainPubkey,
7409
7441
  senderNametag: this.deps.identity.nametag,
7410
- recipientPubkey,
7442
+ recipientPubkey: resolved.pubkey,
7443
+ ...resolved.nametag ? { recipientNametag: resolved.nametag } : {},
7411
7444
  content,
7412
7445
  timestamp: Date.now(),
7413
7446
  isRead: false
@@ -7525,12 +7558,12 @@ var CommunicationsModule = class {
7525
7558
  */
7526
7559
  async sendComposingIndicator(recipientPubkeyOrNametag) {
7527
7560
  this.ensureInitialized();
7528
- const recipientPubkey = await this.resolveRecipient(recipientPubkeyOrNametag);
7561
+ const resolved = await this.resolveRecipient(recipientPubkeyOrNametag);
7529
7562
  const content = JSON.stringify({
7530
7563
  senderNametag: this.deps.identity.nametag,
7531
7564
  expiresIn: 3e4
7532
7565
  });
7533
- await this.deps.transport.sendComposingIndicator?.(recipientPubkey, content);
7566
+ await this.deps.transport.sendComposingIndicator?.(resolved.pubkey, content);
7534
7567
  }
7535
7568
  /**
7536
7569
  * Subscribe to incoming composing indicators
@@ -7718,13 +7751,14 @@ var CommunicationsModule = class {
7718
7751
  // ===========================================================================
7719
7752
  async resolveRecipient(recipient) {
7720
7753
  if (recipient.startsWith("@")) {
7721
- const pubkey = await this.deps.transport.resolveNametag?.(recipient.slice(1));
7754
+ const nametag = recipient.slice(1);
7755
+ const pubkey = await this.deps.transport.resolveNametag?.(nametag);
7722
7756
  if (!pubkey) {
7723
7757
  throw new Error(`Nametag not found: ${recipient}`);
7724
7758
  }
7725
- return pubkey;
7759
+ return { pubkey, nametag };
7726
7760
  }
7727
- return recipient;
7761
+ return { pubkey: recipient };
7728
7762
  }
7729
7763
  ensureInitialized() {
7730
7764
  if (!this.deps) {
@@ -12494,14 +12528,17 @@ var Sphere = class _Sphere {
12494
12528
  if (!wasConnected) {
12495
12529
  await storage.connect();
12496
12530
  }
12497
- const mnemonic = await storage.get(STORAGE_KEYS_GLOBAL.MNEMONIC);
12498
- if (mnemonic) return true;
12499
- const masterKey = await storage.get(STORAGE_KEYS_GLOBAL.MASTER_KEY);
12500
- if (masterKey) return true;
12501
- if (!wasConnected) {
12502
- await storage.disconnect();
12531
+ try {
12532
+ const mnemonic = await storage.get(STORAGE_KEYS_GLOBAL.MNEMONIC);
12533
+ if (mnemonic) return true;
12534
+ const masterKey = await storage.get(STORAGE_KEYS_GLOBAL.MASTER_KEY);
12535
+ if (masterKey) return true;
12536
+ return false;
12537
+ } finally {
12538
+ if (!wasConnected) {
12539
+ await storage.disconnect();
12540
+ }
12503
12541
  }
12504
- return false;
12505
12542
  } catch {
12506
12543
  return false;
12507
12544
  }
@@ -12635,6 +12672,9 @@ var Sphere = class _Sphere {
12635
12672
  if (await _Sphere.exists(options.storage)) {
12636
12673
  throw new Error("Wallet already exists. Use Sphere.load() or Sphere.clear() first.");
12637
12674
  }
12675
+ if (!options.storage.isConnected()) {
12676
+ await options.storage.connect();
12677
+ }
12638
12678
  _Sphere.configureTokenRegistry(options.storage, options.network);
12639
12679
  const groupChatConfig = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
12640
12680
  const marketConfig = _Sphere.resolveMarketConfig(options.market);
@@ -12686,6 +12726,9 @@ var Sphere = class _Sphere {
12686
12726
  marketConfig
12687
12727
  );
12688
12728
  sphere._password = options.password ?? null;
12729
+ if (!options.storage.isConnected()) {
12730
+ await options.storage.connect();
12731
+ }
12689
12732
  await sphere.loadIdentityFromStorage();
12690
12733
  await sphere.initializeProviders();
12691
12734
  await sphere.initializeModules();
@@ -12824,45 +12867,22 @@ var Sphere = class _Sphere {
12824
12867
  await _Sphere.instance.destroy();
12825
12868
  console.log("[Sphere.clear] Sphere instance destroyed");
12826
12869
  }
12870
+ console.log("[Sphere.clear] Clearing L1 vesting cache...");
12827
12871
  await vestingClassifier.destroy();
12828
- if (typeof indexedDB !== "undefined" && typeof indexedDB.databases === "function") {
12829
- console.log("[Sphere.clear] Deleting all sphere IndexedDB databases...");
12830
- try {
12831
- const dbs = await Promise.race([
12832
- indexedDB.databases(),
12833
- new Promise(
12834
- (_, reject) => setTimeout(() => reject(new Error("timeout")), 2e3)
12835
- )
12836
- ]);
12837
- const sphereDbs = dbs.filter((db) => db.name?.startsWith("sphere"));
12838
- if (sphereDbs.length > 0) {
12839
- await Promise.all(sphereDbs.map(
12840
- (db) => new Promise((resolve) => {
12841
- const req = indexedDB.deleteDatabase(db.name);
12842
- req.onsuccess = () => {
12843
- console.log(`[Sphere.clear] Deleted ${db.name}`);
12844
- resolve();
12845
- };
12846
- req.onerror = () => resolve();
12847
- req.onblocked = () => {
12848
- console.warn(`[Sphere.clear] deleteDatabase blocked: ${db.name}`);
12849
- resolve();
12850
- };
12851
- })
12852
- ));
12853
- }
12854
- console.log("[Sphere.clear] IndexedDB cleanup done");
12855
- } catch {
12856
- console.warn("[Sphere.clear] IndexedDB enumeration failed");
12857
- }
12858
- }
12872
+ console.log("[Sphere.clear] Yielding 50ms for IDB transaction settlement...");
12873
+ await new Promise((r) => setTimeout(r, 50));
12859
12874
  if (tokenStorage?.clear) {
12875
+ console.log("[Sphere.clear] Clearing token storage...");
12860
12876
  try {
12861
12877
  await tokenStorage.clear();
12878
+ console.log("[Sphere.clear] Token storage cleared");
12862
12879
  } catch (err) {
12863
12880
  console.warn("[Sphere.clear] Token storage clear failed:", err);
12864
12881
  }
12882
+ } else {
12883
+ console.log("[Sphere.clear] No token storage provider to clear");
12865
12884
  }
12885
+ console.log("[Sphere.clear] Clearing KV storage...");
12866
12886
  if (!storage.isConnected()) {
12867
12887
  try {
12868
12888
  await storage.connect();
@@ -12871,7 +12891,11 @@ var Sphere = class _Sphere {
12871
12891
  }
12872
12892
  if (storage.isConnected()) {
12873
12893
  await storage.clear();
12894
+ console.log("[Sphere.clear] KV storage cleared");
12895
+ } else {
12896
+ console.log("[Sphere.clear] KV storage not connected, skipping");
12874
12897
  }
12898
+ console.log("[Sphere.clear] Done");
12875
12899
  }
12876
12900
  /**
12877
12901
  * Get current instance
@@ -13719,8 +13743,12 @@ var Sphere = class _Sphere {
13719
13743
  await this._storage.set(STORAGE_KEYS_GLOBAL.CURRENT_ADDRESS_INDEX, index.toString());
13720
13744
  this._storage.setIdentity(this._identity);
13721
13745
  await this._transport.setIdentity(this._identity);
13722
- for (const provider of this._tokenStorageProviders.values()) {
13746
+ console.log(`[Sphere] switchToAddress(${index}): re-initializing ${this._tokenStorageProviders.size} token storage provider(s)`);
13747
+ for (const [providerId, provider] of this._tokenStorageProviders.entries()) {
13748
+ console.log(`[Sphere] switchToAddress(${index}): shutdown provider=${providerId}`);
13749
+ await provider.shutdown();
13723
13750
  provider.setIdentity(this._identity);
13751
+ console.log(`[Sphere] switchToAddress(${index}): initialize provider=${providerId}`);
13724
13752
  await provider.initialize();
13725
13753
  }
13726
13754
  await this.reinitializeModulesForNewAddress();
@@ -13802,6 +13830,9 @@ var Sphere = class _Sphere {
13802
13830
  await this._communications.load();
13803
13831
  await this._groupChat?.load();
13804
13832
  await this._market?.load();
13833
+ this._payments.sync().catch((err) => {
13834
+ console.warn("[Sphere] Post-switch sync failed:", err);
13835
+ });
13805
13836
  }
13806
13837
  /**
13807
13838
  * Derive address at a specific index