@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.d.cts CHANGED
@@ -2724,6 +2724,7 @@ declare class PaymentsModule {
2724
2724
  private pendingTransfers;
2725
2725
  private pendingBackgroundTasks;
2726
2726
  private tombstones;
2727
+ private tombstoneKeySet;
2727
2728
  private archivedTokens;
2728
2729
  private forkedTokens;
2729
2730
  private _historyCache;
@@ -3174,12 +3175,14 @@ declare class PaymentsModule {
3174
3175
  getTombstones(): TombstoneEntry[];
3175
3176
  /**
3176
3177
  * Check whether a specific `(tokenId, stateHash)` combination is tombstoned.
3178
+ * Uses O(1) Set lookup instead of O(n) linear scan.
3177
3179
  *
3178
3180
  * @param tokenId - The genesis token ID.
3179
3181
  * @param stateHash - The state hash of the token version to check.
3180
3182
  * @returns `true` if the exact combination has been tombstoned.
3181
3183
  */
3182
3184
  isStateTombstoned(tokenId: string, stateHash: string): boolean;
3185
+ private rebuildTombstoneKeySet;
3183
3186
  /**
3184
3187
  * Merge tombstones received from a remote sync source.
3185
3188
  *
package/dist/index.d.ts CHANGED
@@ -2724,6 +2724,7 @@ declare class PaymentsModule {
2724
2724
  private pendingTransfers;
2725
2725
  private pendingBackgroundTasks;
2726
2726
  private tombstones;
2727
+ private tombstoneKeySet;
2727
2728
  private archivedTokens;
2728
2729
  private forkedTokens;
2729
2730
  private _historyCache;
@@ -3174,12 +3175,14 @@ declare class PaymentsModule {
3174
3175
  getTombstones(): TombstoneEntry[];
3175
3176
  /**
3176
3177
  * Check whether a specific `(tokenId, stateHash)` combination is tombstoned.
3178
+ * Uses O(1) Set lookup instead of O(n) linear scan.
3177
3179
  *
3178
3180
  * @param tokenId - The genesis token ID.
3179
3181
  * @param stateHash - The state hash of the token version to check.
3180
3182
  * @returns `true` if the exact combination has been tombstoned.
3181
3183
  */
3182
3184
  isStateTombstoned(tokenId: string, stateHash: string): boolean;
3185
+ private rebuildTombstoneKeySet;
3183
3186
  /**
3184
3187
  * Merge tombstones received from a remote sync source.
3185
3188
  *
package/dist/index.js CHANGED
@@ -6468,7 +6468,7 @@ function normalizeToHex(value) {
6468
6468
  return String(value);
6469
6469
  }
6470
6470
  function normalizeSdkTokenToStorage(sdkTokenJson) {
6471
- const txf = JSON.parse(JSON.stringify(sdkTokenJson));
6471
+ const txf = structuredClone(sdkTokenJson);
6472
6472
  if (txf.genesis?.data) {
6473
6473
  const data = txf.genesis.data;
6474
6474
  if (data.tokenId !== void 0) {
@@ -7759,35 +7759,45 @@ async function parseTokenInfo(tokenData) {
7759
7759
  }
7760
7760
  return defaultInfo;
7761
7761
  }
7762
- function extractTokenIdFromSdkData(sdkData) {
7763
- if (!sdkData) return null;
7764
- try {
7765
- const txf = JSON.parse(sdkData);
7766
- return txf.genesis?.data?.tokenId || null;
7767
- } catch {
7768
- return null;
7769
- }
7770
- }
7771
- function extractStateHashFromSdkData(sdkData) {
7772
- if (!sdkData) return "";
7762
+ var sdkDataCache = /* @__PURE__ */ new Map();
7763
+ var SDK_DATA_CACHE_MAX = 2e3;
7764
+ function parseSdkDataCached(sdkData) {
7765
+ const cached = sdkDataCache.get(sdkData);
7766
+ if (cached) return cached;
7767
+ let tokenId = null;
7768
+ let stateHash = "";
7773
7769
  try {
7774
7770
  const txf = JSON.parse(sdkData);
7775
- const stateHash = getCurrentStateHash(txf);
7771
+ tokenId = txf.genesis?.data?.tokenId || null;
7772
+ stateHash = getCurrentStateHash(txf) || "";
7776
7773
  if (!stateHash) {
7777
7774
  if (txf.state?.hash) {
7778
- return txf.state.hash;
7779
- }
7780
- if (txf.stateHash) {
7781
- return txf.stateHash;
7782
- }
7783
- if (txf.currentStateHash) {
7784
- return txf.currentStateHash;
7775
+ stateHash = txf.state.hash;
7776
+ } else if (txf.stateHash) {
7777
+ stateHash = txf.stateHash;
7778
+ } else if (txf.currentStateHash) {
7779
+ stateHash = txf.currentStateHash;
7785
7780
  }
7786
7781
  }
7787
- return stateHash || "";
7788
7782
  } catch {
7789
- return "";
7790
7783
  }
7784
+ const entry = { tokenId, stateHash };
7785
+ if (sdkDataCache.size >= SDK_DATA_CACHE_MAX) {
7786
+ sdkDataCache.clear();
7787
+ }
7788
+ sdkDataCache.set(sdkData, entry);
7789
+ return entry;
7790
+ }
7791
+ function clearSdkDataCache() {
7792
+ sdkDataCache.clear();
7793
+ }
7794
+ function extractTokenIdFromSdkData(sdkData) {
7795
+ if (!sdkData) return null;
7796
+ return parseSdkDataCached(sdkData).tokenId;
7797
+ }
7798
+ function extractStateHashFromSdkData(sdkData) {
7799
+ if (!sdkData) return "";
7800
+ return parseSdkDataCached(sdkData).stateHash;
7791
7801
  }
7792
7802
  function createTokenStateKey(tokenId, stateHash) {
7793
7803
  return `${tokenId}_${stateHash}`;
@@ -7897,6 +7907,8 @@ var PaymentsModule = class _PaymentsModule {
7897
7907
  pendingBackgroundTasks = [];
7898
7908
  // Repository State (tombstones, archives, forked, history)
7899
7909
  tombstones = [];
7910
+ // O(1) lookup set derived from tombstones array. Rebuilt via rebuildTombstoneKeySet().
7911
+ tombstoneKeySet = /* @__PURE__ */ new Set();
7900
7912
  archivedTokens = /* @__PURE__ */ new Map();
7901
7913
  forkedTokens = /* @__PURE__ */ new Map();
7902
7914
  _historyCache = [];
@@ -7981,8 +7993,10 @@ var PaymentsModule = class _PaymentsModule {
7981
7993
  }
7982
7994
  this.pendingResponseResolvers.clear();
7983
7995
  this.tokens.clear();
7996
+ clearSdkDataCache();
7984
7997
  this.pendingTransfers.clear();
7985
7998
  this.tombstones = [];
7999
+ this.tombstoneKeySet.clear();
7986
8000
  this.archivedTokens.clear();
7987
8001
  this.forkedTokens.clear();
7988
8002
  this._historyCache = [];
@@ -10103,11 +10117,10 @@ var PaymentsModule = class _PaymentsModule {
10103
10117
  await this.archiveToken(token);
10104
10118
  const tombstone = createTombstoneFromToken(token);
10105
10119
  if (tombstone) {
10106
- const alreadyTombstoned = this.tombstones.some(
10107
- (t) => t.tokenId === tombstone.tokenId && t.stateHash === tombstone.stateHash
10108
- );
10109
- if (!alreadyTombstoned) {
10120
+ const key = `${tombstone.tokenId}:${tombstone.stateHash}`;
10121
+ if (!this.tombstoneKeySet.has(key)) {
10110
10122
  this.tombstones.push(tombstone);
10123
+ this.tombstoneKeySet.add(key);
10111
10124
  logger.debug("Payments", `Created tombstone for ${tombstone.tokenId.slice(0, 8)}..._${tombstone.stateHash.slice(0, 8)}...`);
10112
10125
  }
10113
10126
  } else {
@@ -10132,15 +10145,20 @@ var PaymentsModule = class _PaymentsModule {
10132
10145
  }
10133
10146
  /**
10134
10147
  * Check whether a specific `(tokenId, stateHash)` combination is tombstoned.
10148
+ * Uses O(1) Set lookup instead of O(n) linear scan.
10135
10149
  *
10136
10150
  * @param tokenId - The genesis token ID.
10137
10151
  * @param stateHash - The state hash of the token version to check.
10138
10152
  * @returns `true` if the exact combination has been tombstoned.
10139
10153
  */
10140
10154
  isStateTombstoned(tokenId, stateHash) {
10141
- return this.tombstones.some(
10142
- (t) => t.tokenId === tokenId && t.stateHash === stateHash
10143
- );
10155
+ return this.tombstoneKeySet.has(`${tokenId}:${stateHash}`);
10156
+ }
10157
+ rebuildTombstoneKeySet() {
10158
+ this.tombstoneKeySet.clear();
10159
+ for (const t of this.tombstones) {
10160
+ this.tombstoneKeySet.add(`${t.tokenId}:${t.stateHash}`);
10161
+ }
10144
10162
  }
10145
10163
  /**
10146
10164
  * Merge tombstones received from a remote sync source.
@@ -10172,11 +10190,10 @@ var PaymentsModule = class _PaymentsModule {
10172
10190
  removedCount++;
10173
10191
  }
10174
10192
  for (const remoteTombstone of remoteTombstones) {
10175
- const alreadyExists = this.tombstones.some(
10176
- (t) => t.tokenId === remoteTombstone.tokenId && t.stateHash === remoteTombstone.stateHash
10177
- );
10178
- if (!alreadyExists) {
10193
+ const key = `${remoteTombstone.tokenId}:${remoteTombstone.stateHash}`;
10194
+ if (!this.tombstoneKeySet.has(key)) {
10179
10195
  this.tombstones.push(remoteTombstone);
10196
+ this.tombstoneKeySet.add(key);
10180
10197
  }
10181
10198
  }
10182
10199
  if (removedCount > 0) {
@@ -10192,6 +10209,7 @@ var PaymentsModule = class _PaymentsModule {
10192
10209
  async pruneTombstones(maxAge) {
10193
10210
  const originalCount = this.tombstones.length;
10194
10211
  this.tombstones = pruneTombstonesByAge(this.tombstones, maxAge);
10212
+ this.rebuildTombstoneKeySet();
10195
10213
  if (this.tombstones.length < originalCount) {
10196
10214
  await this.save();
10197
10215
  logger.debug("Payments", `Pruned tombstones from ${originalCount} to ${this.tombstones.length}`);
@@ -10678,6 +10696,11 @@ var PaymentsModule = class _PaymentsModule {
10678
10696
  }
10679
10697
  const savedTokens = new Map(this.tokens);
10680
10698
  this.loadFromStorageData(result.merged);
10699
+ const existingGenesisIds = /* @__PURE__ */ new Set();
10700
+ for (const existing of this.tokens.values()) {
10701
+ const gid = extractTokenIdFromSdkData(existing.sdkData);
10702
+ if (gid) existingGenesisIds.add(gid);
10703
+ }
10681
10704
  let restoredCount = 0;
10682
10705
  for (const [tokenId, token] of savedTokens) {
10683
10706
  if (this.tokens.has(tokenId)) continue;
@@ -10686,17 +10709,11 @@ var PaymentsModule = class _PaymentsModule {
10686
10709
  if (sdkTokenId && stateHash && this.isStateTombstoned(sdkTokenId, stateHash)) {
10687
10710
  continue;
10688
10711
  }
10689
- if (sdkTokenId) {
10690
- let hasEquivalent = false;
10691
- for (const existing of this.tokens.values()) {
10692
- if (extractTokenIdFromSdkData(existing.sdkData) === sdkTokenId) {
10693
- hasEquivalent = true;
10694
- break;
10695
- }
10696
- }
10697
- if (hasEquivalent) continue;
10712
+ if (sdkTokenId && existingGenesisIds.has(sdkTokenId)) {
10713
+ continue;
10698
10714
  }
10699
10715
  this.tokens.set(tokenId, token);
10716
+ if (sdkTokenId) existingGenesisIds.add(sdkTokenId);
10700
10717
  restoredCount++;
10701
10718
  }
10702
10719
  if (restoredCount > 0) {
@@ -11443,6 +11460,7 @@ var PaymentsModule = class _PaymentsModule {
11443
11460
  const parsed = parseTxfStorageData(data);
11444
11461
  logger.debug("Payments", `loadFromStorageData: parsed ${parsed.tokens.length} tokens, ${parsed.tombstones.length} tombstones, errors=[${parsed.validationErrors.join("; ")}]`);
11445
11462
  this.tombstones = parsed.tombstones;
11463
+ this.rebuildTombstoneKeySet();
11446
11464
  this.tokens.clear();
11447
11465
  for (const token of parsed.tokens) {
11448
11466
  const sdkTokenId = extractTokenIdFromSdkData(token.sdkData);
@@ -18002,9 +18020,16 @@ var Sphere = class _Sphere {
18002
18020
  emitEvent
18003
18021
  });
18004
18022
  await payments.load();
18005
- await communications.load();
18006
- await groupChat?.load();
18007
- await market?.load();
18023
+ const results = await Promise.allSettled([
18024
+ communications.load(),
18025
+ groupChat?.load(),
18026
+ market?.load()
18027
+ ]);
18028
+ for (const r of results) {
18029
+ if (r.status === "rejected") {
18030
+ logger.warn("Sphere", "Module load failed:", r.reason);
18031
+ }
18032
+ }
18008
18033
  const moduleSet = {
18009
18034
  index,
18010
18035
  identity,
@@ -19219,9 +19244,9 @@ var Sphere = class _Sphere {
19219
19244
  await this._transport.connect();
19220
19245
  }
19221
19246
  await this._oracle.initialize();
19222
- for (const provider of this._tokenStorageProviders.values()) {
19223
- await provider.initialize();
19224
- }
19247
+ await Promise.all(
19248
+ [...this._tokenStorageProviders.values()].map((p) => p.initialize())
19249
+ );
19225
19250
  this.subscribeToProviderEvents();
19226
19251
  }
19227
19252
  /**
@@ -19327,10 +19352,17 @@ var Sphere = class _Sphere {
19327
19352
  identity: this._identity,
19328
19353
  emitEvent
19329
19354
  });
19330
- await this._payments.load();
19331
- await this._communications.load();
19332
- await this._groupChat?.load();
19333
- await this._market?.load();
19355
+ const results = await Promise.allSettled([
19356
+ this._payments.load(),
19357
+ this._communications.load(),
19358
+ this._groupChat?.load(),
19359
+ this._market?.load()
19360
+ ]);
19361
+ for (const r of results) {
19362
+ if (r.status === "rejected") {
19363
+ logger.warn("Sphere", "Module load failed:", r.reason);
19364
+ }
19365
+ }
19334
19366
  this._addressModules.set(this._currentAddressIndex, {
19335
19367
  index: this._currentAddressIndex,
19336
19368
  identity: this._identity,