@unicitylabs/sphere-sdk 0.6.5 → 0.6.6

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
@@ -6619,7 +6619,7 @@ function normalizeToHex(value) {
6619
6619
  return String(value);
6620
6620
  }
6621
6621
  function normalizeSdkTokenToStorage(sdkTokenJson) {
6622
- const txf = JSON.parse(JSON.stringify(sdkTokenJson));
6622
+ const txf = structuredClone(sdkTokenJson);
6623
6623
  if (txf.genesis?.data) {
6624
6624
  const data = txf.genesis.data;
6625
6625
  if (data.tokenId !== void 0) {
@@ -7910,35 +7910,45 @@ async function parseTokenInfo(tokenData) {
7910
7910
  }
7911
7911
  return defaultInfo;
7912
7912
  }
7913
- function extractTokenIdFromSdkData(sdkData) {
7914
- if (!sdkData) return null;
7915
- try {
7916
- const txf = JSON.parse(sdkData);
7917
- return txf.genesis?.data?.tokenId || null;
7918
- } catch {
7919
- return null;
7920
- }
7921
- }
7922
- function extractStateHashFromSdkData(sdkData) {
7923
- if (!sdkData) return "";
7913
+ var sdkDataCache = /* @__PURE__ */ new Map();
7914
+ var SDK_DATA_CACHE_MAX = 2e3;
7915
+ function parseSdkDataCached(sdkData) {
7916
+ const cached = sdkDataCache.get(sdkData);
7917
+ if (cached) return cached;
7918
+ let tokenId = null;
7919
+ let stateHash = "";
7924
7920
  try {
7925
7921
  const txf = JSON.parse(sdkData);
7926
- const stateHash = getCurrentStateHash(txf);
7922
+ tokenId = txf.genesis?.data?.tokenId || null;
7923
+ stateHash = getCurrentStateHash(txf) || "";
7927
7924
  if (!stateHash) {
7928
7925
  if (txf.state?.hash) {
7929
- return txf.state.hash;
7930
- }
7931
- if (txf.stateHash) {
7932
- return txf.stateHash;
7933
- }
7934
- if (txf.currentStateHash) {
7935
- return txf.currentStateHash;
7926
+ stateHash = txf.state.hash;
7927
+ } else if (txf.stateHash) {
7928
+ stateHash = txf.stateHash;
7929
+ } else if (txf.currentStateHash) {
7930
+ stateHash = txf.currentStateHash;
7936
7931
  }
7937
7932
  }
7938
- return stateHash || "";
7939
7933
  } catch {
7940
- return "";
7941
7934
  }
7935
+ const entry = { tokenId, stateHash };
7936
+ if (sdkDataCache.size >= SDK_DATA_CACHE_MAX) {
7937
+ sdkDataCache.clear();
7938
+ }
7939
+ sdkDataCache.set(sdkData, entry);
7940
+ return entry;
7941
+ }
7942
+ function clearSdkDataCache() {
7943
+ sdkDataCache.clear();
7944
+ }
7945
+ function extractTokenIdFromSdkData(sdkData) {
7946
+ if (!sdkData) return null;
7947
+ return parseSdkDataCached(sdkData).tokenId;
7948
+ }
7949
+ function extractStateHashFromSdkData(sdkData) {
7950
+ if (!sdkData) return "";
7951
+ return parseSdkDataCached(sdkData).stateHash;
7942
7952
  }
7943
7953
  function createTokenStateKey(tokenId, stateHash) {
7944
7954
  return `${tokenId}_${stateHash}`;
@@ -8048,6 +8058,8 @@ var PaymentsModule = class _PaymentsModule {
8048
8058
  pendingBackgroundTasks = [];
8049
8059
  // Repository State (tombstones, archives, forked, history)
8050
8060
  tombstones = [];
8061
+ // O(1) lookup set derived from tombstones array. Rebuilt via rebuildTombstoneKeySet().
8062
+ tombstoneKeySet = /* @__PURE__ */ new Set();
8051
8063
  archivedTokens = /* @__PURE__ */ new Map();
8052
8064
  forkedTokens = /* @__PURE__ */ new Map();
8053
8065
  _historyCache = [];
@@ -8132,8 +8144,10 @@ var PaymentsModule = class _PaymentsModule {
8132
8144
  }
8133
8145
  this.pendingResponseResolvers.clear();
8134
8146
  this.tokens.clear();
8147
+ clearSdkDataCache();
8135
8148
  this.pendingTransfers.clear();
8136
8149
  this.tombstones = [];
8150
+ this.tombstoneKeySet.clear();
8137
8151
  this.archivedTokens.clear();
8138
8152
  this.forkedTokens.clear();
8139
8153
  this._historyCache = [];
@@ -10254,11 +10268,10 @@ var PaymentsModule = class _PaymentsModule {
10254
10268
  await this.archiveToken(token);
10255
10269
  const tombstone = createTombstoneFromToken(token);
10256
10270
  if (tombstone) {
10257
- const alreadyTombstoned = this.tombstones.some(
10258
- (t) => t.tokenId === tombstone.tokenId && t.stateHash === tombstone.stateHash
10259
- );
10260
- if (!alreadyTombstoned) {
10271
+ const key = `${tombstone.tokenId}:${tombstone.stateHash}`;
10272
+ if (!this.tombstoneKeySet.has(key)) {
10261
10273
  this.tombstones.push(tombstone);
10274
+ this.tombstoneKeySet.add(key);
10262
10275
  logger.debug("Payments", `Created tombstone for ${tombstone.tokenId.slice(0, 8)}..._${tombstone.stateHash.slice(0, 8)}...`);
10263
10276
  }
10264
10277
  } else {
@@ -10283,15 +10296,20 @@ var PaymentsModule = class _PaymentsModule {
10283
10296
  }
10284
10297
  /**
10285
10298
  * Check whether a specific `(tokenId, stateHash)` combination is tombstoned.
10299
+ * Uses O(1) Set lookup instead of O(n) linear scan.
10286
10300
  *
10287
10301
  * @param tokenId - The genesis token ID.
10288
10302
  * @param stateHash - The state hash of the token version to check.
10289
10303
  * @returns `true` if the exact combination has been tombstoned.
10290
10304
  */
10291
10305
  isStateTombstoned(tokenId, stateHash) {
10292
- return this.tombstones.some(
10293
- (t) => t.tokenId === tokenId && t.stateHash === stateHash
10294
- );
10306
+ return this.tombstoneKeySet.has(`${tokenId}:${stateHash}`);
10307
+ }
10308
+ rebuildTombstoneKeySet() {
10309
+ this.tombstoneKeySet.clear();
10310
+ for (const t of this.tombstones) {
10311
+ this.tombstoneKeySet.add(`${t.tokenId}:${t.stateHash}`);
10312
+ }
10295
10313
  }
10296
10314
  /**
10297
10315
  * Merge tombstones received from a remote sync source.
@@ -10323,11 +10341,10 @@ var PaymentsModule = class _PaymentsModule {
10323
10341
  removedCount++;
10324
10342
  }
10325
10343
  for (const remoteTombstone of remoteTombstones) {
10326
- const alreadyExists = this.tombstones.some(
10327
- (t) => t.tokenId === remoteTombstone.tokenId && t.stateHash === remoteTombstone.stateHash
10328
- );
10329
- if (!alreadyExists) {
10344
+ const key = `${remoteTombstone.tokenId}:${remoteTombstone.stateHash}`;
10345
+ if (!this.tombstoneKeySet.has(key)) {
10330
10346
  this.tombstones.push(remoteTombstone);
10347
+ this.tombstoneKeySet.add(key);
10331
10348
  }
10332
10349
  }
10333
10350
  if (removedCount > 0) {
@@ -10343,6 +10360,7 @@ var PaymentsModule = class _PaymentsModule {
10343
10360
  async pruneTombstones(maxAge) {
10344
10361
  const originalCount = this.tombstones.length;
10345
10362
  this.tombstones = pruneTombstonesByAge(this.tombstones, maxAge);
10363
+ this.rebuildTombstoneKeySet();
10346
10364
  if (this.tombstones.length < originalCount) {
10347
10365
  await this.save();
10348
10366
  logger.debug("Payments", `Pruned tombstones from ${originalCount} to ${this.tombstones.length}`);
@@ -10829,6 +10847,11 @@ var PaymentsModule = class _PaymentsModule {
10829
10847
  }
10830
10848
  const savedTokens = new Map(this.tokens);
10831
10849
  this.loadFromStorageData(result.merged);
10850
+ const existingGenesisIds = /* @__PURE__ */ new Set();
10851
+ for (const existing of this.tokens.values()) {
10852
+ const gid = extractTokenIdFromSdkData(existing.sdkData);
10853
+ if (gid) existingGenesisIds.add(gid);
10854
+ }
10832
10855
  let restoredCount = 0;
10833
10856
  for (const [tokenId, token] of savedTokens) {
10834
10857
  if (this.tokens.has(tokenId)) continue;
@@ -10837,17 +10860,11 @@ var PaymentsModule = class _PaymentsModule {
10837
10860
  if (sdkTokenId && stateHash && this.isStateTombstoned(sdkTokenId, stateHash)) {
10838
10861
  continue;
10839
10862
  }
10840
- if (sdkTokenId) {
10841
- let hasEquivalent = false;
10842
- for (const existing of this.tokens.values()) {
10843
- if (extractTokenIdFromSdkData(existing.sdkData) === sdkTokenId) {
10844
- hasEquivalent = true;
10845
- break;
10846
- }
10847
- }
10848
- if (hasEquivalent) continue;
10863
+ if (sdkTokenId && existingGenesisIds.has(sdkTokenId)) {
10864
+ continue;
10849
10865
  }
10850
10866
  this.tokens.set(tokenId, token);
10867
+ if (sdkTokenId) existingGenesisIds.add(sdkTokenId);
10851
10868
  restoredCount++;
10852
10869
  }
10853
10870
  if (restoredCount > 0) {
@@ -11594,6 +11611,7 @@ var PaymentsModule = class _PaymentsModule {
11594
11611
  const parsed = parseTxfStorageData(data);
11595
11612
  logger.debug("Payments", `loadFromStorageData: parsed ${parsed.tokens.length} tokens, ${parsed.tombstones.length} tombstones, errors=[${parsed.validationErrors.join("; ")}]`);
11596
11613
  this.tombstones = parsed.tombstones;
11614
+ this.rebuildTombstoneKeySet();
11597
11615
  this.tokens.clear();
11598
11616
  for (const token of parsed.tokens) {
11599
11617
  const sdkTokenId = extractTokenIdFromSdkData(token.sdkData);
@@ -18149,9 +18167,16 @@ var Sphere = class _Sphere {
18149
18167
  emitEvent
18150
18168
  });
18151
18169
  await payments.load();
18152
- await communications.load();
18153
- await groupChat?.load();
18154
- await market?.load();
18170
+ const results = await Promise.allSettled([
18171
+ communications.load(),
18172
+ groupChat?.load(),
18173
+ market?.load()
18174
+ ]);
18175
+ for (const r of results) {
18176
+ if (r.status === "rejected") {
18177
+ logger.warn("Sphere", "Module load failed:", r.reason);
18178
+ }
18179
+ }
18155
18180
  const moduleSet = {
18156
18181
  index,
18157
18182
  identity,
@@ -19366,9 +19391,9 @@ var Sphere = class _Sphere {
19366
19391
  await this._transport.connect();
19367
19392
  }
19368
19393
  await this._oracle.initialize();
19369
- for (const provider of this._tokenStorageProviders.values()) {
19370
- await provider.initialize();
19371
- }
19394
+ await Promise.all(
19395
+ [...this._tokenStorageProviders.values()].map((p) => p.initialize())
19396
+ );
19372
19397
  this.subscribeToProviderEvents();
19373
19398
  }
19374
19399
  /**
@@ -19474,10 +19499,17 @@ var Sphere = class _Sphere {
19474
19499
  identity: this._identity,
19475
19500
  emitEvent
19476
19501
  });
19477
- await this._payments.load();
19478
- await this._communications.load();
19479
- await this._groupChat?.load();
19480
- await this._market?.load();
19502
+ const results = await Promise.allSettled([
19503
+ this._payments.load(),
19504
+ this._communications.load(),
19505
+ this._groupChat?.load(),
19506
+ this._market?.load()
19507
+ ]);
19508
+ for (const r of results) {
19509
+ if (r.status === "rejected") {
19510
+ logger.warn("Sphere", "Module load failed:", r.reason);
19511
+ }
19512
+ }
19481
19513
  this._addressModules.set(this._currentAddressIndex, {
19482
19514
  index: this._currentAddressIndex,
19483
19515
  identity: this._identity,