@unicitylabs/sphere-sdk 0.3.7 → 0.3.8

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.
@@ -90,7 +90,11 @@ var STORAGE_KEYS_GLOBAL = {
90
90
  /** Cached token registry JSON (fetched from remote) */
91
91
  TOKEN_REGISTRY_CACHE: "token_registry_cache",
92
92
  /** Timestamp of last token registry cache update (ms since epoch) */
93
- TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts"
93
+ TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
94
+ /** Cached price data JSON (from CoinGecko or other provider) */
95
+ PRICE_CACHE: "price_cache",
96
+ /** Timestamp of last price cache update (ms since epoch) */
97
+ PRICE_CACHE_TS: "price_cache_ts"
94
98
  };
95
99
  var STORAGE_KEYS_ADDRESS = {
96
100
  /** Pending transfers for this address */
@@ -215,7 +219,6 @@ var TIMEOUTS = {
215
219
  /** Sync interval */
216
220
  SYNC_INTERVAL: 6e4
217
221
  };
218
- var DEFAULT_MARKET_API_URL = "https://market-api.unicity.network";
219
222
 
220
223
  // impl/nodejs/storage/FileStorageProvider.ts
221
224
  var FileStorageProvider = class {
@@ -1196,8 +1199,6 @@ var NostrTransportProvider = class {
1196
1199
  transferHandlers = /* @__PURE__ */ new Set();
1197
1200
  paymentRequestHandlers = /* @__PURE__ */ new Set();
1198
1201
  paymentRequestResponseHandlers = /* @__PURE__ */ new Set();
1199
- readReceiptHandlers = /* @__PURE__ */ new Set();
1200
- typingIndicatorHandlers = /* @__PURE__ */ new Set();
1201
1202
  broadcastHandlers = /* @__PURE__ */ new Map();
1202
1203
  eventCallbacks = /* @__PURE__ */ new Set();
1203
1204
  constructor(config) {
@@ -1449,18 +1450,6 @@ var NostrTransportProvider = class {
1449
1450
  const wrappedContent = senderNametag ? JSON.stringify({ senderNametag, text: content }) : content;
1450
1451
  const giftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, nostrRecipient, wrappedContent);
1451
1452
  await this.publishEvent(giftWrap);
1452
- const selfWrapContent = JSON.stringify({
1453
- selfWrap: true,
1454
- originalId: giftWrap.id,
1455
- recipientPubkey,
1456
- senderNametag,
1457
- text: content
1458
- });
1459
- const selfPubkey = this.keyManager.getPublicKeyHex();
1460
- const selfGiftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, selfPubkey, selfWrapContent);
1461
- this.publishEvent(selfGiftWrap).catch((err) => {
1462
- this.log("Self-wrap publish failed:", err);
1463
- });
1464
1453
  this.emitEvent({
1465
1454
  type: "message:sent",
1466
1455
  timestamp: Date.now(),
@@ -1559,37 +1548,6 @@ var NostrTransportProvider = class {
1559
1548
  this.paymentRequestResponseHandlers.add(handler);
1560
1549
  return () => this.paymentRequestResponseHandlers.delete(handler);
1561
1550
  }
1562
- // ===========================================================================
1563
- // Read Receipts
1564
- // ===========================================================================
1565
- async sendReadReceipt(recipientTransportPubkey, messageEventId) {
1566
- if (!this.keyManager) throw new Error("Not initialized");
1567
- const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
1568
- const event = import_nostr_js_sdk.NIP17.createReadReceipt(this.keyManager, nostrRecipient, messageEventId);
1569
- await this.publishEvent(event);
1570
- this.log("Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
1571
- }
1572
- onReadReceipt(handler) {
1573
- this.readReceiptHandlers.add(handler);
1574
- return () => this.readReceiptHandlers.delete(handler);
1575
- }
1576
- // ===========================================================================
1577
- // Typing Indicators
1578
- // ===========================================================================
1579
- async sendTypingIndicator(recipientTransportPubkey) {
1580
- if (!this.keyManager) throw new Error("Not initialized");
1581
- const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
1582
- const content = JSON.stringify({
1583
- type: "typing",
1584
- senderNametag: this.identity?.nametag
1585
- });
1586
- const event = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, nostrRecipient, content);
1587
- await this.publishEvent(event);
1588
- }
1589
- onTypingIndicator(handler) {
1590
- this.typingIndicatorHandlers.add(handler);
1591
- return () => this.typingIndicatorHandlers.delete(handler);
1592
- }
1593
1551
  /**
1594
1552
  * Resolve any identifier to full peer information.
1595
1553
  * Routes to the appropriate specific resolve method based on identifier format.
@@ -2043,74 +2001,11 @@ var NostrTransportProvider = class {
2043
2001
  const pm = import_nostr_js_sdk.NIP17.unwrap(event, this.keyManager);
2044
2002
  this.log("Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
2045
2003
  if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
2046
- try {
2047
- const parsed = JSON.parse(pm.content);
2048
- if (parsed?.selfWrap && parsed.recipientPubkey) {
2049
- this.log("Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
2050
- const message2 = {
2051
- id: parsed.originalId || pm.eventId,
2052
- senderTransportPubkey: pm.senderPubkey,
2053
- senderNametag: parsed.senderNametag,
2054
- recipientTransportPubkey: parsed.recipientPubkey,
2055
- content: parsed.text ?? "",
2056
- timestamp: pm.timestamp * 1e3,
2057
- encrypted: true,
2058
- isSelfWrap: true
2059
- };
2060
- for (const handler of this.messageHandlers) {
2061
- try {
2062
- handler(message2);
2063
- } catch (e) {
2064
- this.log("Self-wrap handler error:", e);
2065
- }
2066
- }
2067
- return;
2068
- }
2069
- } catch {
2070
- }
2071
- this.log("Skipping own non-self-wrap message");
2072
- return;
2073
- }
2074
- if ((0, import_nostr_js_sdk.isReadReceipt)(pm)) {
2075
- this.log("Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
2076
- if (pm.replyToEventId) {
2077
- const receipt = {
2078
- senderTransportPubkey: pm.senderPubkey,
2079
- messageEventId: pm.replyToEventId,
2080
- timestamp: pm.timestamp * 1e3
2081
- };
2082
- for (const handler of this.readReceiptHandlers) {
2083
- try {
2084
- handler(receipt);
2085
- } catch (e) {
2086
- this.log("Read receipt handler error:", e);
2087
- }
2088
- }
2089
- }
2004
+ this.log("Skipping own message");
2090
2005
  return;
2091
2006
  }
2092
- try {
2093
- const parsed = JSON.parse(pm.content);
2094
- if (parsed?.type === "typing") {
2095
- this.log("Typing indicator from:", pm.senderPubkey?.slice(0, 16));
2096
- const indicator = {
2097
- senderTransportPubkey: pm.senderPubkey,
2098
- senderNametag: parsed.senderNametag,
2099
- timestamp: pm.timestamp * 1e3
2100
- };
2101
- for (const handler of this.typingIndicatorHandlers) {
2102
- try {
2103
- handler(indicator);
2104
- } catch (e) {
2105
- this.log("Typing handler error:", e);
2106
- }
2107
- }
2108
- return;
2109
- }
2110
- } catch {
2111
- }
2112
- if (!(0, import_nostr_js_sdk.isChatMessage)(pm)) {
2113
- this.log("Skipping unknown message kind:", pm.kind);
2007
+ if (pm.kind !== import_nostr_js_sdk.EventKinds.CHAT_MESSAGE) {
2008
+ this.log("Skipping non-chat message, kind:", pm.kind);
2114
2009
  return;
2115
2010
  }
2116
2011
  let content = pm.content;
@@ -2125,9 +2020,7 @@ var NostrTransportProvider = class {
2125
2020
  }
2126
2021
  this.log("DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
2127
2022
  const message = {
2128
- // Use outer gift wrap event.id so it matches the sender's stored giftWrap.id.
2129
- // This ensures read receipts reference an ID the sender recognizes.
2130
- id: event.id,
2023
+ id: pm.eventId,
2131
2024
  senderTransportPubkey: pm.senderPubkey,
2132
2025
  senderNametag,
2133
2026
  content,
@@ -3152,6 +3045,7 @@ async function loadIpnsModule() {
3152
3045
  async function createSignedRecord(keyPair, cid, sequenceNumber, lifetimeMs = DEFAULT_LIFETIME_MS) {
3153
3046
  const { createIPNSRecord, marshalIPNSRecord } = await loadIpnsModule();
3154
3047
  const record = await createIPNSRecord(
3048
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3155
3049
  keyPair,
3156
3050
  `/ipfs/${cid}`,
3157
3051
  sequenceNumber,
@@ -4893,26 +4787,37 @@ var CoinGeckoPriceProvider = class {
4893
4787
  timeout;
4894
4788
  debug;
4895
4789
  baseUrl;
4790
+ storage;
4791
+ /** In-flight fetch promise for deduplication of concurrent getPrices() calls */
4792
+ fetchPromise = null;
4793
+ /** Token names being fetched in the current in-flight request */
4794
+ fetchNames = null;
4795
+ /** Whether persistent cache has been loaded into memory */
4796
+ persistentCacheLoaded = false;
4797
+ /** Promise for loading persistent cache (deduplication) */
4798
+ loadCachePromise = null;
4896
4799
  constructor(config) {
4897
4800
  this.apiKey = config?.apiKey;
4898
4801
  this.cacheTtlMs = config?.cacheTtlMs ?? 6e4;
4899
4802
  this.timeout = config?.timeout ?? 1e4;
4900
4803
  this.debug = config?.debug ?? false;
4804
+ this.storage = config?.storage ?? null;
4901
4805
  this.baseUrl = config?.baseUrl ?? (this.apiKey ? "https://pro-api.coingecko.com/api/v3" : "https://api.coingecko.com/api/v3");
4902
4806
  }
4903
4807
  async getPrices(tokenNames) {
4904
4808
  if (tokenNames.length === 0) {
4905
4809
  return /* @__PURE__ */ new Map();
4906
4810
  }
4811
+ if (!this.persistentCacheLoaded && this.storage) {
4812
+ await this.loadFromStorage();
4813
+ }
4907
4814
  const now = Date.now();
4908
4815
  const result = /* @__PURE__ */ new Map();
4909
4816
  const uncachedNames = [];
4910
4817
  for (const name of tokenNames) {
4911
4818
  const cached = this.cache.get(name);
4912
4819
  if (cached && cached.expiresAt > now) {
4913
- if (cached.price !== null) {
4914
- result.set(name, cached.price);
4915
- }
4820
+ result.set(name, cached.price);
4916
4821
  } else {
4917
4822
  uncachedNames.push(name);
4918
4823
  }
@@ -4920,6 +4825,41 @@ var CoinGeckoPriceProvider = class {
4920
4825
  if (uncachedNames.length === 0) {
4921
4826
  return result;
4922
4827
  }
4828
+ if (this.fetchPromise && this.fetchNames) {
4829
+ const allCovered = uncachedNames.every((n) => this.fetchNames.has(n));
4830
+ if (allCovered) {
4831
+ if (this.debug) {
4832
+ console.log(`[CoinGecko] Deduplicating request, reusing in-flight fetch`);
4833
+ }
4834
+ const fetched = await this.fetchPromise;
4835
+ for (const name of uncachedNames) {
4836
+ const price = fetched.get(name);
4837
+ if (price) {
4838
+ result.set(name, price);
4839
+ }
4840
+ }
4841
+ return result;
4842
+ }
4843
+ }
4844
+ const fetchPromise = this.doFetch(uncachedNames);
4845
+ this.fetchPromise = fetchPromise;
4846
+ this.fetchNames = new Set(uncachedNames);
4847
+ try {
4848
+ const fetched = await fetchPromise;
4849
+ for (const [name, price] of fetched) {
4850
+ result.set(name, price);
4851
+ }
4852
+ } finally {
4853
+ if (this.fetchPromise === fetchPromise) {
4854
+ this.fetchPromise = null;
4855
+ this.fetchNames = null;
4856
+ }
4857
+ }
4858
+ return result;
4859
+ }
4860
+ async doFetch(uncachedNames) {
4861
+ const result = /* @__PURE__ */ new Map();
4862
+ const now = Date.now();
4923
4863
  try {
4924
4864
  const ids = uncachedNames.join(",");
4925
4865
  const url = `${this.baseUrl}/simple/price?ids=${encodeURIComponent(ids)}&vs_currencies=usd,eur&include_24hr_change=true`;
@@ -4935,6 +4875,9 @@ var CoinGeckoPriceProvider = class {
4935
4875
  signal: AbortSignal.timeout(this.timeout)
4936
4876
  });
4937
4877
  if (!response.ok) {
4878
+ if (response.status === 429) {
4879
+ this.extendCacheOnRateLimit(uncachedNames);
4880
+ }
4938
4881
  throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
4939
4882
  }
4940
4883
  const data = await response.json();
@@ -4953,25 +4896,113 @@ var CoinGeckoPriceProvider = class {
4953
4896
  }
4954
4897
  for (const name of uncachedNames) {
4955
4898
  if (!result.has(name)) {
4956
- this.cache.set(name, { price: null, expiresAt: now + this.cacheTtlMs });
4899
+ const zeroPrice = {
4900
+ tokenName: name,
4901
+ priceUsd: 0,
4902
+ priceEur: 0,
4903
+ change24h: 0,
4904
+ timestamp: now
4905
+ };
4906
+ this.cache.set(name, { price: zeroPrice, expiresAt: now + this.cacheTtlMs });
4907
+ result.set(name, zeroPrice);
4957
4908
  }
4958
4909
  }
4959
4910
  if (this.debug) {
4960
4911
  console.log(`[CoinGecko] Fetched ${result.size} prices`);
4961
4912
  }
4913
+ this.saveToStorage();
4962
4914
  } catch (error) {
4963
4915
  if (this.debug) {
4964
4916
  console.warn("[CoinGecko] Fetch failed, using stale cache:", error);
4965
4917
  }
4966
4918
  for (const name of uncachedNames) {
4967
4919
  const stale = this.cache.get(name);
4968
- if (stale?.price) {
4920
+ if (stale) {
4969
4921
  result.set(name, stale.price);
4970
4922
  }
4971
4923
  }
4972
4924
  }
4973
4925
  return result;
4974
4926
  }
4927
+ // ===========================================================================
4928
+ // Persistent Storage
4929
+ // ===========================================================================
4930
+ /**
4931
+ * Load cached prices from StorageProvider into in-memory cache.
4932
+ * Only loads entries that are still within cacheTtlMs.
4933
+ */
4934
+ async loadFromStorage() {
4935
+ if (this.loadCachePromise) {
4936
+ return this.loadCachePromise;
4937
+ }
4938
+ this.loadCachePromise = this.doLoadFromStorage();
4939
+ try {
4940
+ await this.loadCachePromise;
4941
+ } finally {
4942
+ this.loadCachePromise = null;
4943
+ }
4944
+ }
4945
+ async doLoadFromStorage() {
4946
+ this.persistentCacheLoaded = true;
4947
+ if (!this.storage) return;
4948
+ try {
4949
+ const [cached, cachedTs] = await Promise.all([
4950
+ this.storage.get(STORAGE_KEYS_GLOBAL.PRICE_CACHE),
4951
+ this.storage.get(STORAGE_KEYS_GLOBAL.PRICE_CACHE_TS)
4952
+ ]);
4953
+ if (!cached || !cachedTs) return;
4954
+ const ts = parseInt(cachedTs, 10);
4955
+ if (isNaN(ts)) return;
4956
+ const age = Date.now() - ts;
4957
+ if (age > this.cacheTtlMs) return;
4958
+ const data = JSON.parse(cached);
4959
+ const expiresAt = ts + this.cacheTtlMs;
4960
+ for (const [name, price] of Object.entries(data)) {
4961
+ if (!this.cache.has(name)) {
4962
+ this.cache.set(name, { price, expiresAt });
4963
+ }
4964
+ }
4965
+ if (this.debug) {
4966
+ console.log(`[CoinGecko] Loaded ${Object.keys(data).length} prices from persistent cache`);
4967
+ }
4968
+ } catch {
4969
+ }
4970
+ }
4971
+ /**
4972
+ * Save current prices to StorageProvider (fire-and-forget).
4973
+ */
4974
+ saveToStorage() {
4975
+ if (!this.storage) return;
4976
+ const data = {};
4977
+ for (const [name, entry] of this.cache) {
4978
+ data[name] = entry.price;
4979
+ }
4980
+ Promise.all([
4981
+ this.storage.set(STORAGE_KEYS_GLOBAL.PRICE_CACHE, JSON.stringify(data)),
4982
+ this.storage.set(STORAGE_KEYS_GLOBAL.PRICE_CACHE_TS, String(Date.now()))
4983
+ ]).catch(() => {
4984
+ });
4985
+ }
4986
+ // ===========================================================================
4987
+ // Rate-limit handling
4988
+ // ===========================================================================
4989
+ /**
4990
+ * On 429 rate-limit, extend stale cache entries so subsequent calls
4991
+ * don't immediately retry and hammer the API.
4992
+ */
4993
+ extendCacheOnRateLimit(names) {
4994
+ const backoffMs = 6e4;
4995
+ const extendedExpiry = Date.now() + backoffMs;
4996
+ for (const name of names) {
4997
+ const existing = this.cache.get(name);
4998
+ if (existing) {
4999
+ existing.expiresAt = Math.max(existing.expiresAt, extendedExpiry);
5000
+ }
5001
+ }
5002
+ if (this.debug) {
5003
+ console.warn(`[CoinGecko] Rate-limited (429), extended cache TTL by ${backoffMs / 1e3}s`);
5004
+ }
5005
+ }
4975
5006
  async getPrice(tokenName) {
4976
5007
  const prices = await this.getPrices([tokenName]);
4977
5008
  return prices.get(tokenName) ?? null;
@@ -5005,6 +5036,7 @@ var TokenRegistry = class _TokenRegistry {
5005
5036
  refreshTimer = null;
5006
5037
  lastRefreshAt = 0;
5007
5038
  refreshPromise = null;
5039
+ initialLoadPromise = null;
5008
5040
  constructor() {
5009
5041
  this.definitionsById = /* @__PURE__ */ new Map();
5010
5042
  this.definitionsBySymbol = /* @__PURE__ */ new Map();
@@ -5043,13 +5075,8 @@ var TokenRegistry = class _TokenRegistry {
5043
5075
  if (options.refreshIntervalMs !== void 0) {
5044
5076
  instance.refreshIntervalMs = options.refreshIntervalMs;
5045
5077
  }
5046
- if (instance.storage) {
5047
- instance.loadFromCache();
5048
- }
5049
5078
  const autoRefresh = options.autoRefresh ?? true;
5050
- if (autoRefresh && instance.remoteUrl) {
5051
- instance.startAutoRefresh();
5052
- }
5079
+ instance.initialLoadPromise = instance.performInitialLoad(autoRefresh);
5053
5080
  }
5054
5081
  /**
5055
5082
  * Reset the singleton instance (useful for testing).
@@ -5067,6 +5094,53 @@ var TokenRegistry = class _TokenRegistry {
5067
5094
  static destroy() {
5068
5095
  _TokenRegistry.resetInstance();
5069
5096
  }
5097
+ /**
5098
+ * Wait for the initial data load (cache or remote) to complete.
5099
+ * Returns true if data was loaded, false if not (timeout or no data source).
5100
+ *
5101
+ * @param timeoutMs - Maximum wait time in ms (default: 10s). Set to 0 for no timeout.
5102
+ */
5103
+ static async waitForReady(timeoutMs = 1e4) {
5104
+ const instance = _TokenRegistry.getInstance();
5105
+ if (!instance.initialLoadPromise) {
5106
+ return instance.definitionsById.size > 0;
5107
+ }
5108
+ if (timeoutMs <= 0) {
5109
+ return instance.initialLoadPromise;
5110
+ }
5111
+ return Promise.race([
5112
+ instance.initialLoadPromise,
5113
+ new Promise((resolve) => setTimeout(() => resolve(false), timeoutMs))
5114
+ ]);
5115
+ }
5116
+ // ===========================================================================
5117
+ // Initial Load
5118
+ // ===========================================================================
5119
+ /**
5120
+ * Perform initial data load: try cache first, fall back to remote fetch.
5121
+ * After initial data is available, start periodic auto-refresh if configured.
5122
+ */
5123
+ async performInitialLoad(autoRefresh) {
5124
+ let loaded = false;
5125
+ if (this.storage) {
5126
+ loaded = await this.loadFromCache();
5127
+ }
5128
+ if (loaded) {
5129
+ if (autoRefresh && this.remoteUrl) {
5130
+ this.startAutoRefresh();
5131
+ }
5132
+ return true;
5133
+ }
5134
+ if (autoRefresh && this.remoteUrl) {
5135
+ loaded = await this.refreshFromRemote();
5136
+ this.stopAutoRefresh();
5137
+ this.refreshTimer = setInterval(() => {
5138
+ this.refreshFromRemote();
5139
+ }, this.refreshIntervalMs);
5140
+ return loaded;
5141
+ }
5142
+ return false;
5143
+ }
5070
5144
  // ===========================================================================
5071
5145
  // Cache (StorageProvider)
5072
5146
  // ===========================================================================
@@ -5396,7 +5470,7 @@ function resolveL1Config(network, config) {
5396
5470
  enableVesting: config.enableVesting
5397
5471
  };
5398
5472
  }
5399
- function resolvePriceConfig(config) {
5473
+ function resolvePriceConfig(config, storage) {
5400
5474
  if (config === void 0) {
5401
5475
  return void 0;
5402
5476
  }
@@ -5406,7 +5480,8 @@ function resolvePriceConfig(config) {
5406
5480
  baseUrl: config.baseUrl,
5407
5481
  cacheTtlMs: config.cacheTtlMs,
5408
5482
  timeout: config.timeout,
5409
- debug: config.debug
5483
+ debug: config.debug,
5484
+ storage
5410
5485
  };
5411
5486
  }
5412
5487
  function resolveGroupChatConfig(network, config) {
@@ -5423,16 +5498,6 @@ function resolveGroupChatConfig(network, config) {
5423
5498
  relays: config.relays ?? [...netConfig.groupRelays]
5424
5499
  };
5425
5500
  }
5426
- function resolveMarketConfig(config) {
5427
- if (!config) return void 0;
5428
- if (config === true) {
5429
- return { apiUrl: DEFAULT_MARKET_API_URL };
5430
- }
5431
- return {
5432
- apiUrl: config.apiUrl ?? DEFAULT_MARKET_API_URL,
5433
- timeout: config.timeout
5434
- };
5435
- }
5436
5501
 
5437
5502
  // impl/nodejs/index.ts
5438
5503
  function createNodeProviders(config) {
@@ -5440,21 +5505,19 @@ function createNodeProviders(config) {
5440
5505
  const transportConfig = resolveTransportConfig(network, config?.transport);
5441
5506
  const oracleConfig = resolveOracleConfig(network, config?.oracle);
5442
5507
  const l1Config = resolveL1Config(network, config?.l1);
5443
- const priceConfig = resolvePriceConfig(config?.price);
5444
5508
  const storage = createFileStorageProvider({
5445
5509
  dataDir: config?.dataDir ?? "./sphere-data",
5446
5510
  ...config?.walletFileName ? { fileName: config.walletFileName } : {}
5447
5511
  });
5512
+ const priceConfig = resolvePriceConfig(config?.price, storage);
5448
5513
  const ipfsSync = config?.tokenSync?.ipfs;
5449
5514
  const ipfsTokenStorage = ipfsSync?.enabled ? createNodeIpfsStorageProvider(ipfsSync.config, storage) : void 0;
5450
5515
  const groupChat = resolveGroupChatConfig(network, config?.groupChat);
5451
5516
  const networkConfig = getNetworkConfig(network);
5452
5517
  TokenRegistry.configure({ remoteUrl: networkConfig.tokenRegistryUrl, storage });
5453
- const market = resolveMarketConfig(config?.market);
5454
5518
  return {
5455
5519
  storage,
5456
5520
  groupChat,
5457
- market,
5458
5521
  tokenStorage: createFileTokenStorageProvider({
5459
5522
  tokensDir: config?.tokensDir ?? "./sphere-tokens"
5460
5523
  }),