@unicitylabs/sphere-sdk 0.5.4 → 0.5.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 (39) hide show
  1. package/dist/connect/index.cjs +128 -22
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.js +128 -22
  4. package/dist/connect/index.js.map +1 -1
  5. package/dist/core/index.cjs +670 -473
  6. package/dist/core/index.cjs.map +1 -1
  7. package/dist/core/index.d.cts +123 -2
  8. package/dist/core/index.d.ts +123 -2
  9. package/dist/core/index.js +667 -473
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/impl/browser/index.cjs +306 -193
  12. package/dist/impl/browser/index.cjs.map +1 -1
  13. package/dist/impl/browser/index.js +306 -193
  14. package/dist/impl/browser/index.js.map +1 -1
  15. package/dist/impl/browser/ipfs.cjs +134 -19
  16. package/dist/impl/browser/ipfs.cjs.map +1 -1
  17. package/dist/impl/browser/ipfs.js +134 -19
  18. package/dist/impl/browser/ipfs.js.map +1 -1
  19. package/dist/impl/nodejs/connect/index.cjs +101 -6
  20. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  21. package/dist/impl/nodejs/connect/index.js +101 -6
  22. package/dist/impl/nodejs/connect/index.js.map +1 -1
  23. package/dist/impl/nodejs/index.cjs +267 -152
  24. package/dist/impl/nodejs/index.cjs.map +1 -1
  25. package/dist/impl/nodejs/index.d.cts +2 -1
  26. package/dist/impl/nodejs/index.d.ts +2 -1
  27. package/dist/impl/nodejs/index.js +267 -152
  28. package/dist/impl/nodejs/index.js.map +1 -1
  29. package/dist/index.cjs +682 -493
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +124 -8
  32. package/dist/index.d.ts +124 -8
  33. package/dist/index.js +680 -493
  34. package/dist/index.js.map +1 -1
  35. package/dist/l1/index.cjs +139 -32
  36. package/dist/l1/index.cjs.map +1 -1
  37. package/dist/l1/index.js +139 -32
  38. package/dist/l1/index.js.map +1 -1
  39. package/package.json +1 -1
@@ -1,6 +1,110 @@
1
1
  // impl/browser/index.ts
2
2
  import { Buffer as Buffer3 } from "buffer";
3
3
 
4
+ // core/logger.ts
5
+ var LOGGER_KEY = "__sphere_sdk_logger__";
6
+ function getState() {
7
+ const g = globalThis;
8
+ if (!g[LOGGER_KEY]) {
9
+ g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
10
+ }
11
+ return g[LOGGER_KEY];
12
+ }
13
+ function isEnabled(tag) {
14
+ const state = getState();
15
+ if (tag in state.tags) return state.tags[tag];
16
+ return state.debug;
17
+ }
18
+ var logger = {
19
+ /**
20
+ * Configure the logger. Can be called multiple times (last write wins).
21
+ * Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
22
+ */
23
+ configure(config) {
24
+ const state = getState();
25
+ if (config.debug !== void 0) state.debug = config.debug;
26
+ if (config.handler !== void 0) state.handler = config.handler;
27
+ },
28
+ /**
29
+ * Enable/disable debug logging for a specific tag.
30
+ * Per-tag setting overrides the global debug flag.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * logger.setTagDebug('Nostr', true); // enable only Nostr logs
35
+ * logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
36
+ * ```
37
+ */
38
+ setTagDebug(tag, enabled) {
39
+ getState().tags[tag] = enabled;
40
+ },
41
+ /**
42
+ * Clear per-tag override, falling back to global debug flag.
43
+ */
44
+ clearTagDebug(tag) {
45
+ delete getState().tags[tag];
46
+ },
47
+ /** Returns true if debug mode is enabled for the given tag (or globally). */
48
+ isDebugEnabled(tag) {
49
+ if (tag) return isEnabled(tag);
50
+ return getState().debug;
51
+ },
52
+ /**
53
+ * Debug-level log. Only shown when debug is enabled (globally or for this tag).
54
+ * Use for detailed operational information.
55
+ */
56
+ debug(tag, message, ...args) {
57
+ if (!isEnabled(tag)) return;
58
+ const state = getState();
59
+ if (state.handler) {
60
+ state.handler("debug", tag, message, ...args);
61
+ } else {
62
+ console.log(`[${tag}]`, message, ...args);
63
+ }
64
+ },
65
+ /**
66
+ * Warning-level log. ALWAYS shown regardless of debug flag.
67
+ * Use for important but non-critical issues (timeouts, retries, degraded state).
68
+ */
69
+ warn(tag, message, ...args) {
70
+ const state = getState();
71
+ if (state.handler) {
72
+ state.handler("warn", tag, message, ...args);
73
+ } else {
74
+ console.warn(`[${tag}]`, message, ...args);
75
+ }
76
+ },
77
+ /**
78
+ * Error-level log. ALWAYS shown regardless of debug flag.
79
+ * Use for critical failures that should never be silenced.
80
+ */
81
+ error(tag, message, ...args) {
82
+ const state = getState();
83
+ if (state.handler) {
84
+ state.handler("error", tag, message, ...args);
85
+ } else {
86
+ console.error(`[${tag}]`, message, ...args);
87
+ }
88
+ },
89
+ /** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
90
+ reset() {
91
+ const g = globalThis;
92
+ delete g[LOGGER_KEY];
93
+ }
94
+ };
95
+
96
+ // core/errors.ts
97
+ var SphereError = class extends Error {
98
+ code;
99
+ cause;
100
+ constructor(message, code, cause) {
101
+ super(message);
102
+ this.name = "SphereError";
103
+ this.code = code;
104
+ this.cause = cause;
105
+ }
106
+ };
107
+
4
108
  // constants.ts
5
109
  var STORAGE_KEYS_GLOBAL = {
6
110
  /** Encrypted BIP39 mnemonic */
@@ -205,7 +309,7 @@ var LocalStorageProvider = class {
205
309
  this.log("Connected to localStorage");
206
310
  } catch (error) {
207
311
  this.status = "error";
208
- throw new Error(`LocalStorage not available: ${error}`);
312
+ throw new SphereError(`LocalStorage not available: ${error}`, "STORAGE_ERROR");
209
313
  }
210
314
  }
211
315
  async disconnect() {
@@ -312,7 +416,7 @@ var LocalStorageProvider = class {
312
416
  }
313
417
  ensureConnected() {
314
418
  if (this.status !== "connected") {
315
- throw new Error("LocalStorageProvider not connected");
419
+ throw new SphereError("LocalStorageProvider not connected", "STORAGE_ERROR");
316
420
  }
317
421
  }
318
422
  getStorageSafe() {
@@ -321,10 +425,8 @@ var LocalStorageProvider = class {
321
425
  }
322
426
  return createInMemoryStorage();
323
427
  }
324
- log(...args) {
325
- if (this.config.debug) {
326
- console.log("[LocalStorageProvider]", ...args);
327
- }
428
+ log(message, ...args) {
429
+ logger.debug("LocalStorage", message, ...args);
328
430
  }
329
431
  };
330
432
  function createInMemoryStorage() {
@@ -385,7 +487,7 @@ var IndexedDBStorageProvider = class {
385
487
  for (let attempt = 0; attempt < 2; attempt++) {
386
488
  this.status = "connecting";
387
489
  const t0 = Date.now();
388
- console.log(`[IndexedDBStorage] connect: opening db=${this.dbName}, attempt=${attempt + 1}/2`);
490
+ logger.debug("IndexedDB", ` connect: opening db=${this.dbName}, attempt=${attempt + 1}/2`);
389
491
  try {
390
492
  this.db = await Promise.race([
391
493
  this.openDatabase(),
@@ -394,23 +496,23 @@ var IndexedDBStorageProvider = class {
394
496
  )
395
497
  ]);
396
498
  this.status = "connected";
397
- console.log(`[IndexedDBStorage] connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
499
+ logger.debug("IndexedDB", ` connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
398
500
  return;
399
501
  } catch (error) {
400
- console.warn(`[IndexedDBStorage] connect: open failed db=${this.dbName} attempt=${attempt + 1} (${Date.now() - t0}ms):`, error);
502
+ logger.warn("IndexedDB", ` connect: open failed db=${this.dbName} attempt=${attempt + 1} (${Date.now() - t0}ms):`, error);
401
503
  if (attempt === 0) {
402
504
  this.status = "disconnected";
403
505
  await new Promise((r) => setTimeout(r, 1e3));
404
506
  continue;
405
507
  }
406
508
  this.status = "error";
407
- throw new Error(`IndexedDB not available: ${error}`);
509
+ throw new SphereError(`IndexedDB not available: ${error}`, "STORAGE_ERROR");
408
510
  }
409
511
  }
410
512
  }
411
513
  async disconnect() {
412
514
  const cid = this.connId;
413
- console.log(`[IndexedDBStorage] disconnect: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
515
+ logger.debug("IndexedDB", ` disconnect: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
414
516
  if (this.db) {
415
517
  this.db.close();
416
518
  this.db = null;
@@ -469,15 +571,15 @@ var IndexedDBStorageProvider = class {
469
571
  if (!prefix) {
470
572
  const t0 = Date.now();
471
573
  const prevConnId = this.connId;
472
- console.log(`[IndexedDBStorage] clear: starting db=${this.dbName} connId=${prevConnId} status=${this.status} hasDb=${!!this.db}`);
574
+ logger.debug("IndexedDB", ` clear: starting db=${this.dbName} connId=${prevConnId} status=${this.status} hasDb=${!!this.db}`);
473
575
  try {
474
576
  if (!this.db || this.status !== "connected") {
475
577
  if (this.db) {
476
- console.log(`[IndexedDBStorage] clear: closing stale handle connId=${prevConnId}`);
578
+ logger.debug("IndexedDB", ` clear: closing stale handle connId=${prevConnId}`);
477
579
  this.db.close();
478
580
  this.db = null;
479
581
  }
480
- console.log(`[IndexedDBStorage] clear: opening fresh connection for wipe`);
582
+ logger.debug("IndexedDB", ` clear: opening fresh connection for wipe`);
481
583
  this.db = await Promise.race([
482
584
  this.openDatabase(),
483
585
  new Promise(
@@ -487,9 +589,9 @@ var IndexedDBStorageProvider = class {
487
589
  this.status = "connected";
488
590
  }
489
591
  await this.idbClear();
490
- console.log(`[IndexedDBStorage] clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
592
+ logger.debug("IndexedDB", ` clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
491
593
  } catch (err) {
492
- console.warn(`[IndexedDBStorage] clear: failed db=${this.dbName} (${Date.now() - t0}ms)`, err);
594
+ logger.warn("IndexedDB", ` clear: failed db=${this.dbName} (${Date.now() - t0}ms)`, err);
493
595
  } finally {
494
596
  if (this.db) {
495
597
  this.db.close();
@@ -552,7 +654,7 @@ var IndexedDBStorageProvider = class {
552
654
  }
553
655
  ensureConnected() {
554
656
  if (this.status !== "connected" || !this.db) {
555
- throw new Error("IndexedDBStorageProvider not connected");
657
+ throw new SphereError("IndexedDBStorageProvider not connected", "STORAGE_ERROR");
556
658
  }
557
659
  }
558
660
  // ===========================================================================
@@ -567,7 +669,7 @@ var IndexedDBStorageProvider = class {
567
669
  const cid = ++connectionSeq;
568
670
  this.connId = cid;
569
671
  db.onversionchange = () => {
570
- console.log(`[IndexedDBStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
672
+ logger.debug("IndexedDB", ` onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
571
673
  db.close();
572
674
  if (this.db === db) {
573
675
  this.db = null;
@@ -577,7 +679,7 @@ var IndexedDBStorageProvider = class {
577
679
  resolve(db);
578
680
  };
579
681
  request.onblocked = () => {
580
- console.warn(`[IndexedDBStorage] open blocked by another connection, db=${this.dbName}`);
682
+ logger.warn("IndexedDB", ` open blocked by another connection, db=${this.dbName}`);
581
683
  };
582
684
  request.onupgradeneeded = (event) => {
583
685
  const db = event.target.result;
@@ -641,10 +743,8 @@ var IndexedDBStorageProvider = class {
641
743
  request.onsuccess = () => resolve();
642
744
  });
643
745
  }
644
- log(...args) {
645
- if (this.debug) {
646
- console.log("[IndexedDBStorageProvider]", ...args);
647
- }
746
+ log(message, ...args) {
747
+ logger.debug("IndexedDB", message, ...args);
648
748
  }
649
749
  };
650
750
  function createIndexedDBStorageProvider(config) {
@@ -681,31 +781,31 @@ var IndexedDBTokenStorageProvider = class {
681
781
  const addressId = getAddressId(identity.directAddress);
682
782
  this.dbName = `${this.dbNamePrefix}-${addressId}`;
683
783
  }
684
- console.log(`[IndexedDBTokenStorage] setIdentity: db=${this.dbName}`);
784
+ logger.debug("IndexedDBToken", `setIdentity: db=${this.dbName}`);
685
785
  }
686
786
  async initialize() {
687
787
  const prevConnId = this.connId;
688
788
  const t0 = Date.now();
689
789
  try {
690
790
  if (this.db) {
691
- console.log(`[IndexedDBTokenStorage] initialize: closing existing connId=${prevConnId} before re-open (db=${this.dbName})`);
791
+ logger.debug("IndexedDBToken", `initialize: closing existing connId=${prevConnId} before re-open (db=${this.dbName})`);
692
792
  this.db.close();
693
793
  this.db = null;
694
794
  }
695
- console.log(`[IndexedDBTokenStorage] initialize: opening db=${this.dbName}`);
795
+ logger.debug("IndexedDBToken", `initialize: opening db=${this.dbName}`);
696
796
  this.db = await this.openDatabase();
697
797
  this.status = "connected";
698
- console.log(`[IndexedDBTokenStorage] initialize: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
798
+ logger.debug("IndexedDBToken", `initialize: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
699
799
  return true;
700
800
  } catch (error) {
701
- console.error(`[IndexedDBTokenStorage] initialize: failed db=${this.dbName} (${Date.now() - t0}ms):`, error);
801
+ logger.error("IndexedDBToken", `initialize: failed db=${this.dbName} (${Date.now() - t0}ms):`, error);
702
802
  this.status = "error";
703
803
  return false;
704
804
  }
705
805
  }
706
806
  async shutdown() {
707
807
  const cid = this.connId;
708
- console.log(`[IndexedDBTokenStorage] shutdown: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
808
+ logger.debug("IndexedDBToken", `shutdown: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
709
809
  if (this.db) {
710
810
  this.db.close();
711
811
  this.db = null;
@@ -726,7 +826,7 @@ var IndexedDBTokenStorageProvider = class {
726
826
  }
727
827
  async load() {
728
828
  if (!this.db) {
729
- console.warn(`[IndexedDBTokenStorage] load: db not initialized (db=${this.dbName})`);
829
+ logger.warn("IndexedDBToken", `load: db not initialized (db=${this.dbName})`);
730
830
  return {
731
831
  success: false,
732
832
  error: "Database not initialized",
@@ -776,7 +876,7 @@ var IndexedDBTokenStorageProvider = class {
776
876
  data._invalid = invalid;
777
877
  }
778
878
  const tokenKeys = Object.keys(data).filter((k) => k.startsWith("_") && !["_meta", "_tombstones", "_outbox", "_sent", "_invalid"].includes(k));
779
- console.log(`[IndexedDBTokenStorage] load: db=${this.dbName}, tokens=${tokenKeys.length}`);
879
+ logger.debug("IndexedDBToken", `load: db=${this.dbName}, tokens=${tokenKeys.length}`);
780
880
  return {
781
881
  success: true,
782
882
  data,
@@ -784,7 +884,7 @@ var IndexedDBTokenStorageProvider = class {
784
884
  timestamp: Date.now()
785
885
  };
786
886
  } catch (error) {
787
- console.error(`[IndexedDBTokenStorage] load failed: db=${this.dbName}`, error);
887
+ logger.error("IndexedDBToken", `load failed: db=${this.dbName}`, error);
788
888
  return {
789
889
  success: false,
790
890
  error: error instanceof Error ? error.message : "Unknown error",
@@ -795,7 +895,7 @@ var IndexedDBTokenStorageProvider = class {
795
895
  }
796
896
  async save(data) {
797
897
  if (!this.db) {
798
- console.warn(`[IndexedDBTokenStorage] save: db not initialized (db=${this.dbName})`);
898
+ logger.warn("IndexedDBToken", `save: db not initialized (db=${this.dbName})`);
799
899
  return {
800
900
  success: false,
801
901
  error: "Database not initialized",
@@ -805,7 +905,7 @@ var IndexedDBTokenStorageProvider = class {
805
905
  try {
806
906
  const tokenKeys = Object.keys(data).filter((k) => k.startsWith("_") && !["_meta", "_tombstones", "_outbox", "_sent", "_invalid"].includes(k));
807
907
  const archivedKeys = Object.keys(data).filter((k) => k.startsWith("archived-"));
808
- console.log(`[IndexedDBTokenStorage] save: db=${this.dbName}, tokens=${tokenKeys.length}, archived=${archivedKeys.length}, tombstones=${data._tombstones?.length ?? 0}`);
908
+ logger.debug("IndexedDBToken", `save: db=${this.dbName}, tokens=${tokenKeys.length}, archived=${archivedKeys.length}, tombstones=${data._tombstones?.length ?? 0}`);
809
909
  await this.putToStore(STORE_META, "meta", data._meta);
810
910
  if (data._tombstones) {
811
911
  await this.putToStore(STORE_META, "tombstones", data._tombstones);
@@ -874,21 +974,22 @@ var IndexedDBTokenStorageProvider = class {
874
974
  for (const name of await this.findPrefixedDatabases()) {
875
975
  dbNames.add(name);
876
976
  }
877
- console.log(`[IndexedDBTokenStorage] clear: clearing ${dbNames.size} database(s) (${[...dbNames].join(", ")})`);
977
+ logger.debug("IndexedDBToken", `clear: clearing ${dbNames.size} database(s) (${[...dbNames].join(", ")})`);
878
978
  const results = await Promise.allSettled(
879
979
  [...dbNames].map((name) => this.clearDatabaseStores(name))
880
980
  );
881
981
  const failed = results.filter((r) => r.status === "rejected");
882
982
  if (failed.length > 0) {
883
- console.warn(
884
- `[IndexedDBTokenStorage] clear: ${failed.length}/${dbNames.size} failed (${Date.now() - t0}ms)`,
983
+ logger.warn(
984
+ "IndexedDBToken",
985
+ `clear: ${failed.length}/${dbNames.size} failed (${Date.now() - t0}ms)`,
885
986
  failed.map((r) => r.reason)
886
987
  );
887
988
  }
888
- console.log(`[IndexedDBTokenStorage] clear: done ${dbNames.size} database(s) (${Date.now() - t0}ms)`);
989
+ logger.debug("IndexedDBToken", `clear: done ${dbNames.size} database(s) (${Date.now() - t0}ms)`);
889
990
  return failed.length === 0;
890
991
  } catch (err) {
891
- console.warn(`[IndexedDBTokenStorage] clear: failed (${Date.now() - t0}ms)`, err);
992
+ logger.warn("IndexedDBToken", `clear: failed (${Date.now() - t0}ms)`, err);
892
993
  return false;
893
994
  }
894
995
  }
@@ -904,7 +1005,7 @@ var IndexedDBTokenStorageProvider = class {
904
1005
  const cid = ++connectionSeq2;
905
1006
  this.connId = cid;
906
1007
  db.onversionchange = () => {
907
- console.log(`[IndexedDBTokenStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
1008
+ logger.debug("IndexedDBToken", `onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
908
1009
  db.close();
909
1010
  if (this.db === db) {
910
1011
  this.db = null;
@@ -914,7 +1015,7 @@ var IndexedDBTokenStorageProvider = class {
914
1015
  resolve(db);
915
1016
  };
916
1017
  request.onblocked = () => {
917
- console.warn(`[IndexedDBTokenStorage] open blocked by another connection, db=${this.dbName}`);
1018
+ logger.warn("IndexedDBToken", `open blocked by another connection, db=${this.dbName}`);
918
1019
  };
919
1020
  request.onupgradeneeded = (event) => {
920
1021
  const db = event.target.result;
@@ -1671,11 +1772,11 @@ function bech32Checksum(hrp, data) {
1671
1772
  }
1672
1773
  function encodeBech32(hrp, version, program) {
1673
1774
  if (version < 0 || version > 16) {
1674
- throw new Error("Invalid witness version");
1775
+ throw new SphereError("Invalid witness version", "VALIDATION_ERROR");
1675
1776
  }
1676
1777
  const converted = convertBits(Array.from(program), 8, 5, true);
1677
1778
  if (!converted) {
1678
- throw new Error("Failed to convert bits");
1779
+ throw new SphereError("Failed to convert bits", "VALIDATION_ERROR");
1679
1780
  }
1680
1781
  const data = [version].concat(converted);
1681
1782
  const checksum = bech32Checksum(hrp, data);
@@ -1868,18 +1969,18 @@ var NostrTransportProvider = class {
1868
1969
  });
1869
1970
  this.nostrClient.addConnectionListener({
1870
1971
  onConnect: (url) => {
1871
- this.log("NostrClient connected to relay:", url);
1972
+ logger.debug("Nostr", "NostrClient connected to relay:", url);
1872
1973
  this.emitEvent({ type: "transport:connected", timestamp: Date.now() });
1873
1974
  },
1874
1975
  onDisconnect: (url, reason) => {
1875
- this.log("NostrClient disconnected from relay:", url, "reason:", reason);
1976
+ logger.debug("Nostr", "NostrClient disconnected from relay:", url, "reason:", reason);
1876
1977
  },
1877
1978
  onReconnecting: (url, attempt) => {
1878
- this.log("NostrClient reconnecting to relay:", url, "attempt:", attempt);
1979
+ logger.debug("Nostr", "NostrClient reconnecting to relay:", url, "attempt:", attempt);
1879
1980
  this.emitEvent({ type: "transport:reconnecting", timestamp: Date.now() });
1880
1981
  },
1881
1982
  onReconnected: (url) => {
1882
- this.log("NostrClient reconnected to relay:", url);
1983
+ logger.debug("Nostr", "NostrClient reconnected to relay:", url);
1883
1984
  this.emitEvent({ type: "transport:connected", timestamp: Date.now() });
1884
1985
  }
1885
1986
  });
@@ -1892,11 +1993,11 @@ var NostrTransportProvider = class {
1892
1993
  )
1893
1994
  ]);
1894
1995
  if (!this.nostrClient.isConnected()) {
1895
- throw new Error("Failed to connect to any relay");
1996
+ throw new SphereError("Failed to connect to any relay", "TRANSPORT_ERROR");
1896
1997
  }
1897
1998
  this.status = "connected";
1898
1999
  this.emitEvent({ type: "transport:connected", timestamp: Date.now() });
1899
- this.log("Connected to", this.nostrClient.getConnectedRelays().size, "relays");
2000
+ logger.debug("Nostr", "Connected to", this.nostrClient.getConnectedRelays().size, "relays");
1900
2001
  if (this.identity) {
1901
2002
  await this.subscribeToEvents();
1902
2003
  }
@@ -1915,7 +2016,7 @@ var NostrTransportProvider = class {
1915
2016
  this.chatSubscriptionId = null;
1916
2017
  this.status = "disconnected";
1917
2018
  this.emitEvent({ type: "transport:disconnected", timestamp: Date.now() });
1918
- this.log("Disconnected from all relays");
2019
+ logger.debug("Nostr", "Disconnected from all relays");
1919
2020
  }
1920
2021
  isConnected() {
1921
2022
  return this.status === "connected" && this.nostrClient?.isConnected() === true;
@@ -1945,14 +2046,14 @@ var NostrTransportProvider = class {
1945
2046
  */
1946
2047
  async addRelay(relayUrl) {
1947
2048
  if (this.config.relays.includes(relayUrl)) {
1948
- this.log("Relay already configured:", relayUrl);
2049
+ logger.debug("Nostr", "Relay already configured:", relayUrl);
1949
2050
  return false;
1950
2051
  }
1951
2052
  this.config.relays.push(relayUrl);
1952
2053
  if (this.status === "connected" && this.nostrClient) {
1953
2054
  try {
1954
2055
  await this.nostrClient.connect(relayUrl);
1955
- this.log("Added and connected to relay:", relayUrl);
2056
+ logger.debug("Nostr", "Added and connected to relay:", relayUrl);
1956
2057
  this.emitEvent({
1957
2058
  type: "transport:relay_added",
1958
2059
  timestamp: Date.now(),
@@ -1960,7 +2061,7 @@ var NostrTransportProvider = class {
1960
2061
  });
1961
2062
  return true;
1962
2063
  } catch (error) {
1963
- this.log("Failed to connect to new relay:", relayUrl, error);
2064
+ logger.debug("Nostr", "Failed to connect to new relay:", relayUrl, error);
1964
2065
  this.emitEvent({
1965
2066
  type: "transport:relay_added",
1966
2067
  timestamp: Date.now(),
@@ -1985,11 +2086,11 @@ var NostrTransportProvider = class {
1985
2086
  async removeRelay(relayUrl) {
1986
2087
  const index = this.config.relays.indexOf(relayUrl);
1987
2088
  if (index === -1) {
1988
- this.log("Relay not found:", relayUrl);
2089
+ logger.debug("Nostr", "Relay not found:", relayUrl);
1989
2090
  return false;
1990
2091
  }
1991
2092
  this.config.relays.splice(index, 1);
1992
- this.log("Removed relay from config:", relayUrl);
2093
+ logger.debug("Nostr", "Removed relay from config:", relayUrl);
1993
2094
  this.emitEvent({
1994
2095
  type: "transport:relay_removed",
1995
2096
  timestamp: Date.now(),
@@ -2026,9 +2127,9 @@ var NostrTransportProvider = class {
2026
2127
  const secretKey = Buffer2.from(identity.privateKey, "hex");
2027
2128
  this.keyManager = NostrKeyManager.fromPrivateKey(secretKey);
2028
2129
  const nostrPubkey = this.keyManager.getPublicKeyHex();
2029
- this.log("Identity set, Nostr pubkey:", nostrPubkey.slice(0, 16) + "...");
2130
+ logger.debug("Nostr", "Identity set, Nostr pubkey:", nostrPubkey.slice(0, 16) + "...");
2030
2131
  if (this.nostrClient && this.status === "connected") {
2031
- this.log("Identity changed while connected - recreating NostrClient");
2132
+ logger.debug("Nostr", "Identity changed while connected - recreating NostrClient");
2032
2133
  const oldClient = this.nostrClient;
2033
2134
  this.nostrClient = new NostrClient(this.keyManager, {
2034
2135
  autoReconnect: this.config.autoReconnect,
@@ -2039,16 +2140,16 @@ var NostrTransportProvider = class {
2039
2140
  });
2040
2141
  this.nostrClient.addConnectionListener({
2041
2142
  onConnect: (url) => {
2042
- this.log("NostrClient connected to relay:", url);
2143
+ logger.debug("Nostr", "NostrClient connected to relay:", url);
2043
2144
  },
2044
2145
  onDisconnect: (url, reason) => {
2045
- this.log("NostrClient disconnected from relay:", url, "reason:", reason);
2146
+ logger.debug("Nostr", "NostrClient disconnected from relay:", url, "reason:", reason);
2046
2147
  },
2047
2148
  onReconnecting: (url, attempt) => {
2048
- this.log("NostrClient reconnecting to relay:", url, "attempt:", attempt);
2149
+ logger.debug("Nostr", "NostrClient reconnecting to relay:", url, "attempt:", attempt);
2049
2150
  },
2050
2151
  onReconnected: (url) => {
2051
- this.log("NostrClient reconnected to relay:", url);
2152
+ logger.debug("Nostr", "NostrClient reconnected to relay:", url);
2052
2153
  }
2053
2154
  });
2054
2155
  await Promise.race([
@@ -2071,7 +2172,7 @@ var NostrTransportProvider = class {
2071
2172
  */
2072
2173
  getNostrPubkey() {
2073
2174
  if (!this.keyManager) {
2074
- throw new Error("KeyManager not initialized - call setIdentity first");
2175
+ throw new SphereError("KeyManager not initialized - call setIdentity first", "NOT_INITIALIZED");
2075
2176
  }
2076
2177
  return this.keyManager.getPublicKeyHex();
2077
2178
  }
@@ -2092,7 +2193,7 @@ var NostrTransportProvider = class {
2092
2193
  const selfPubkey = this.keyManager.getPublicKeyHex();
2093
2194
  const selfGiftWrap = NIP17.createGiftWrap(this.keyManager, selfPubkey, selfWrapContent);
2094
2195
  this.publishEvent(selfGiftWrap).catch((err) => {
2095
- this.log("Self-wrap publish failed:", err);
2196
+ logger.debug("Nostr", "Self-wrap publish failed:", err);
2096
2197
  });
2097
2198
  this.emitEvent({
2098
2199
  type: "message:sent",
@@ -2106,12 +2207,12 @@ var NostrTransportProvider = class {
2106
2207
  if (this.pendingMessages.length > 0) {
2107
2208
  const pending = this.pendingMessages;
2108
2209
  this.pendingMessages = [];
2109
- this.log("Flushing", pending.length, "buffered messages to new handler");
2210
+ logger.debug("Nostr", "Flushing", pending.length, "buffered messages to new handler");
2110
2211
  for (const message of pending) {
2111
2212
  try {
2112
2213
  handler(message);
2113
2214
  } catch (error) {
2114
- this.log("Message handler error (buffered):", error);
2215
+ logger.debug("Nostr", "Message handler error (buffered):", error);
2115
2216
  }
2116
2217
  }
2117
2218
  }
@@ -2170,7 +2271,7 @@ var NostrTransportProvider = class {
2170
2271
  tags
2171
2272
  );
2172
2273
  await this.publishEvent(event);
2173
- this.log("Sent payment request:", event.id);
2274
+ logger.debug("Nostr", "Sent payment request:", event.id);
2174
2275
  return event.id;
2175
2276
  }
2176
2277
  onPaymentRequest(handler) {
@@ -2198,7 +2299,7 @@ var NostrTransportProvider = class {
2198
2299
  ]
2199
2300
  );
2200
2301
  await this.publishEvent(event);
2201
- this.log("Sent payment request response:", event.id, "type:", payload.responseType);
2302
+ logger.debug("Nostr", "Sent payment request response:", event.id, "type:", payload.responseType);
2202
2303
  return event.id;
2203
2304
  }
2204
2305
  onPaymentRequestResponse(handler) {
@@ -2209,11 +2310,11 @@ var NostrTransportProvider = class {
2209
2310
  // Read Receipts
2210
2311
  // ===========================================================================
2211
2312
  async sendReadReceipt(recipientTransportPubkey, messageEventId) {
2212
- if (!this.keyManager) throw new Error("Not initialized");
2313
+ if (!this.keyManager) throw new SphereError("Not initialized", "NOT_INITIALIZED");
2213
2314
  const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
2214
2315
  const event = NIP17.createReadReceipt(this.keyManager, nostrRecipient, messageEventId);
2215
2316
  await this.publishEvent(event);
2216
- this.log("Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
2317
+ logger.debug("Nostr", "Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
2217
2318
  }
2218
2319
  onReadReceipt(handler) {
2219
2320
  this.readReceiptHandlers.add(handler);
@@ -2223,7 +2324,7 @@ var NostrTransportProvider = class {
2223
2324
  // Typing Indicators
2224
2325
  // ===========================================================================
2225
2326
  async sendTypingIndicator(recipientTransportPubkey) {
2226
- if (!this.keyManager) throw new Error("Not initialized");
2327
+ if (!this.keyManager) throw new SphereError("Not initialized", "NOT_INITIALIZED");
2227
2328
  const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
2228
2329
  const content = JSON.stringify({
2229
2330
  type: "typing",
@@ -2310,7 +2411,10 @@ var NostrTransportProvider = class {
2310
2411
  limit: 1
2311
2412
  });
2312
2413
  }
2313
- if (events.length === 0) return null;
2414
+ if (events.length === 0) {
2415
+ logger.debug("Nostr", `resolveNametagInfo: no binding events found for nametag "${nametag}"`);
2416
+ return null;
2417
+ }
2314
2418
  const bindingEvent = events[0];
2315
2419
  try {
2316
2420
  const content = JSON.parse(bindingEvent.content);
@@ -2328,7 +2432,7 @@ var NostrTransportProvider = class {
2328
2432
  timestamp: bindingEvent.created_at * 1e3
2329
2433
  };
2330
2434
  }
2331
- this.log("Legacy nametag event without extended fields:", nametag);
2435
+ logger.debug("Nostr", "Legacy nametag event without extended fields:", nametag);
2332
2436
  const pubkeyTag = bindingEvent.tags.find((t) => t[0] === "pubkey");
2333
2437
  const l1Tag = bindingEvent.tags.find((t) => t[0] === "l1");
2334
2438
  if (pubkeyTag?.[1] && l1Tag?.[1]) {
@@ -2484,10 +2588,10 @@ var NostrTransportProvider = class {
2484
2588
  async recoverNametag() {
2485
2589
  this.ensureReady();
2486
2590
  if (!this.identity || !this.keyManager) {
2487
- throw new Error("Identity not set");
2591
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2488
2592
  }
2489
2593
  const nostrPubkey = this.getNostrPubkey();
2490
- this.log("Searching for nametag events for pubkey:", nostrPubkey.slice(0, 16) + "...");
2594
+ logger.debug("Nostr", "Searching for nametag events for pubkey:", nostrPubkey.slice(0, 16) + "...");
2491
2595
  const events = await this.queryEvents({
2492
2596
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
2493
2597
  authors: [nostrPubkey],
@@ -2495,7 +2599,7 @@ var NostrTransportProvider = class {
2495
2599
  // Get recent events in case of updates
2496
2600
  });
2497
2601
  if (events.length === 0) {
2498
- this.log("No nametag events found for this pubkey");
2602
+ logger.debug("Nostr", "No nametag events found for this pubkey");
2499
2603
  return null;
2500
2604
  }
2501
2605
  events.sort((a, b) => b.created_at - a.created_at);
@@ -2508,7 +2612,7 @@ var NostrTransportProvider = class {
2508
2612
  this.identity.privateKey
2509
2613
  );
2510
2614
  if (decrypted) {
2511
- this.log("Recovered nametag:", decrypted);
2615
+ logger.debug("Nostr", "Recovered nametag:", decrypted);
2512
2616
  return decrypted;
2513
2617
  }
2514
2618
  }
@@ -2516,7 +2620,7 @@ var NostrTransportProvider = class {
2516
2620
  continue;
2517
2621
  }
2518
2622
  }
2519
- this.log("Could not decrypt nametag from any event");
2623
+ logger.debug("Nostr", "Could not decrypt nametag from any event");
2520
2624
  return null;
2521
2625
  }
2522
2626
  /**
@@ -2532,7 +2636,7 @@ var NostrTransportProvider = class {
2532
2636
  async publishIdentityBinding(chainPubkey, l1Address, directAddress, nametag) {
2533
2637
  this.ensureReady();
2534
2638
  if (!this.identity) {
2535
- throw new Error("Identity not set");
2639
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2536
2640
  }
2537
2641
  const nostrPubkey = this.getNostrPubkey();
2538
2642
  const dTagBytes = new TextEncoder().encode("unicity:identity:" + nostrPubkey);
@@ -2551,7 +2655,7 @@ var NostrTransportProvider = class {
2551
2655
  if (nametag) {
2552
2656
  const existing = await this.resolveNametag(nametag);
2553
2657
  if (existing && existing !== nostrPubkey) {
2554
- this.log("Nametag already taken:", nametag, "- owner:", existing);
2658
+ logger.debug("Nostr", "Nametag already taken:", nametag, "- owner:", existing);
2555
2659
  return false;
2556
2660
  }
2557
2661
  const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
@@ -2569,9 +2673,9 @@ var NostrTransportProvider = class {
2569
2673
  const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2570
2674
  await this.publishEvent(event);
2571
2675
  if (nametag) {
2572
- this.log("Published identity binding with nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2676
+ logger.debug("Nostr", "Published identity binding with nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2573
2677
  } else {
2574
- this.log("Published identity binding (no nametag) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2678
+ logger.debug("Nostr", "Published identity binding (no nametag) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2575
2679
  }
2576
2680
  return true;
2577
2681
  }
@@ -2584,18 +2688,18 @@ var NostrTransportProvider = class {
2584
2688
  ["a", address]
2585
2689
  ]);
2586
2690
  await this.publishEvent(event);
2587
- this.log("Published nametag binding:", nametag);
2691
+ logger.debug("Nostr", "Published nametag binding:", nametag);
2588
2692
  }
2589
2693
  async registerNametag(nametag, _publicKey, directAddress = "") {
2590
2694
  this.ensureReady();
2591
2695
  if (!this.identity) {
2592
- throw new Error("Identity not set");
2696
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2593
2697
  }
2594
2698
  const nostrPubkey = this.getNostrPubkey();
2595
2699
  const existing = await this.resolveNametag(nametag);
2596
- this.log("registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
2700
+ logger.debug("Nostr", "registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
2597
2701
  if (existing && existing !== nostrPubkey) {
2598
- this.log("Nametag already taken:", nametag, "- owner:", existing);
2702
+ logger.debug("Nostr", "Nametag already taken:", nametag, "- owner:", existing);
2599
2703
  return false;
2600
2704
  }
2601
2705
  const privateKeyHex = this.identity.privateKey;
@@ -2629,7 +2733,7 @@ var NostrTransportProvider = class {
2629
2733
  ];
2630
2734
  const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2631
2735
  await this.publishEvent(event);
2632
- this.log("Registered nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...", "l1:", l1Address.slice(0, 12) + "...");
2736
+ logger.debug("Nostr", "Registered nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...", "l1:", l1Address.slice(0, 12) + "...");
2633
2737
  return true;
2634
2738
  }
2635
2739
  // Track broadcast subscriptions
@@ -2680,14 +2784,14 @@ var NostrTransportProvider = class {
2680
2784
  if (event.id) {
2681
2785
  this.processedEventIds.add(event.id);
2682
2786
  }
2683
- this.log("Processing event kind:", event.kind, "id:", event.id?.slice(0, 12));
2787
+ logger.debug("Nostr", "Processing event kind:", event.kind, "id:", event.id?.slice(0, 12));
2684
2788
  try {
2685
2789
  switch (event.kind) {
2686
2790
  case EVENT_KINDS.DIRECT_MESSAGE:
2687
2791
  await this.handleDirectMessage(event);
2688
2792
  break;
2689
2793
  case EventKinds.GIFT_WRAP:
2690
- this.log("Handling gift wrap (NIP-17 DM)");
2794
+ logger.debug("Nostr", "Handling gift wrap (NIP-17 DM)");
2691
2795
  await this.handleGiftWrap(event);
2692
2796
  break;
2693
2797
  case EVENT_KINDS.TOKEN_TRANSFER:
@@ -2710,7 +2814,7 @@ var NostrTransportProvider = class {
2710
2814
  }
2711
2815
  }
2712
2816
  } catch (error) {
2713
- this.log("Failed to handle event:", error);
2817
+ logger.debug("Nostr", "Failed to handle event:", error);
2714
2818
  }
2715
2819
  }
2716
2820
  /**
@@ -2725,25 +2829,25 @@ var NostrTransportProvider = class {
2725
2829
  const pubkey = this.keyManager.getPublicKeyHex();
2726
2830
  const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_WALLET_EVENT_TS}_${pubkey.slice(0, 16)}`;
2727
2831
  this.storage.set(storageKey, createdAt.toString()).catch((err) => {
2728
- this.log("Failed to save last event timestamp:", err);
2832
+ logger.debug("Nostr", "Failed to save last event timestamp:", err);
2729
2833
  });
2730
2834
  }
2731
2835
  async handleDirectMessage(event) {
2732
- this.log("Ignoring NIP-04 kind 4 event (DMs use NIP-17):", event.id?.slice(0, 12));
2836
+ logger.debug("Nostr", "Ignoring NIP-04 kind 4 event (DMs use NIP-17):", event.id?.slice(0, 12));
2733
2837
  }
2734
2838
  async handleGiftWrap(event) {
2735
2839
  if (!this.identity || !this.keyManager) {
2736
- this.log("handleGiftWrap: no identity/keyManager");
2840
+ logger.debug("Nostr", "handleGiftWrap: no identity/keyManager");
2737
2841
  return;
2738
2842
  }
2739
2843
  try {
2740
2844
  const pm = NIP17.unwrap(event, this.keyManager);
2741
- this.log("Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
2845
+ logger.debug("Nostr", "Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
2742
2846
  if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
2743
2847
  try {
2744
2848
  const parsed = JSON.parse(pm.content);
2745
2849
  if (parsed?.selfWrap && parsed.recipientPubkey) {
2746
- this.log("Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
2850
+ logger.debug("Nostr", "Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
2747
2851
  const message2 = {
2748
2852
  id: parsed.originalId || pm.eventId,
2749
2853
  senderTransportPubkey: pm.senderPubkey,
@@ -2758,18 +2862,18 @@ var NostrTransportProvider = class {
2758
2862
  try {
2759
2863
  handler(message2);
2760
2864
  } catch (e) {
2761
- this.log("Self-wrap handler error:", e);
2865
+ logger.debug("Nostr", "Self-wrap handler error:", e);
2762
2866
  }
2763
2867
  }
2764
2868
  return;
2765
2869
  }
2766
2870
  } catch {
2767
2871
  }
2768
- this.log("Skipping own non-self-wrap message");
2872
+ logger.debug("Nostr", "Skipping own non-self-wrap message");
2769
2873
  return;
2770
2874
  }
2771
2875
  if (isReadReceipt(pm)) {
2772
- this.log("Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
2876
+ logger.debug("Nostr", "Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
2773
2877
  if (pm.replyToEventId) {
2774
2878
  const receipt = {
2775
2879
  senderTransportPubkey: pm.senderPubkey,
@@ -2780,7 +2884,7 @@ var NostrTransportProvider = class {
2780
2884
  try {
2781
2885
  handler(receipt);
2782
2886
  } catch (e) {
2783
- this.log("Read receipt handler error:", e);
2887
+ logger.debug("Nostr", "Read receipt handler error:", e);
2784
2888
  }
2785
2889
  }
2786
2890
  }
@@ -2800,12 +2904,12 @@ var NostrTransportProvider = class {
2800
2904
  senderNametag: senderNametag2,
2801
2905
  expiresIn
2802
2906
  };
2803
- this.log("Composing indicator from:", indicator.senderNametag || pm.senderPubkey?.slice(0, 16));
2907
+ logger.debug("Nostr", "Composing indicator from:", indicator.senderNametag || pm.senderPubkey?.slice(0, 16));
2804
2908
  for (const handler of this.composingHandlers) {
2805
2909
  try {
2806
2910
  handler(indicator);
2807
2911
  } catch (e) {
2808
- this.log("Composing handler error:", e);
2912
+ logger.debug("Nostr", "Composing handler error:", e);
2809
2913
  }
2810
2914
  }
2811
2915
  return;
@@ -2813,7 +2917,7 @@ var NostrTransportProvider = class {
2813
2917
  try {
2814
2918
  const parsed = JSON.parse(pm.content);
2815
2919
  if (parsed?.type === "typing") {
2816
- this.log("Typing indicator from:", pm.senderPubkey?.slice(0, 16));
2920
+ logger.debug("Nostr", "Typing indicator from:", pm.senderPubkey?.slice(0, 16));
2817
2921
  const indicator = {
2818
2922
  senderTransportPubkey: pm.senderPubkey,
2819
2923
  senderNametag: parsed.senderNametag,
@@ -2823,7 +2927,7 @@ var NostrTransportProvider = class {
2823
2927
  try {
2824
2928
  handler(indicator);
2825
2929
  } catch (e) {
2826
- this.log("Typing handler error:", e);
2930
+ logger.debug("Nostr", "Typing handler error:", e);
2827
2931
  }
2828
2932
  }
2829
2933
  return;
@@ -2831,7 +2935,7 @@ var NostrTransportProvider = class {
2831
2935
  } catch {
2832
2936
  }
2833
2937
  if (!isChatMessage(pm)) {
2834
- this.log("Skipping unknown message kind:", pm.kind);
2938
+ logger.debug("Nostr", "Skipping unknown message kind:", pm.kind);
2835
2939
  return;
2836
2940
  }
2837
2941
  let content = pm.content;
@@ -2844,7 +2948,7 @@ var NostrTransportProvider = class {
2844
2948
  }
2845
2949
  } catch {
2846
2950
  }
2847
- this.log("DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
2951
+ logger.debug("Nostr", "DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
2848
2952
  const message = {
2849
2953
  // Use outer gift wrap event.id so it matches the sender's stored giftWrap.id.
2850
2954
  // This ensures read receipts reference an ID the sender recognizes.
@@ -2857,20 +2961,20 @@ var NostrTransportProvider = class {
2857
2961
  };
2858
2962
  this.emitEvent({ type: "message:received", timestamp: Date.now() });
2859
2963
  if (this.messageHandlers.size === 0) {
2860
- this.log("No message handlers registered, buffering message for later delivery");
2964
+ logger.debug("Nostr", "No message handlers registered, buffering message for later delivery");
2861
2965
  this.pendingMessages.push(message);
2862
2966
  } else {
2863
- this.log("Dispatching to", this.messageHandlers.size, "handlers");
2967
+ logger.debug("Nostr", "Dispatching to", this.messageHandlers.size, "handlers");
2864
2968
  for (const handler of this.messageHandlers) {
2865
2969
  try {
2866
2970
  handler(message);
2867
2971
  } catch (error) {
2868
- this.log("Message handler error:", error);
2972
+ logger.debug("Nostr", "Message handler error:", error);
2869
2973
  }
2870
2974
  }
2871
2975
  }
2872
2976
  } catch (err) {
2873
- this.log("Gift wrap decrypt failed (expected if not for us):", err?.message?.slice(0, 50));
2977
+ logger.debug("Nostr", "Gift wrap decrypt failed (expected if not for us):", err?.message?.slice(0, 50));
2874
2978
  }
2875
2979
  }
2876
2980
  async handleTokenTransfer(event) {
@@ -2888,7 +2992,7 @@ var NostrTransportProvider = class {
2888
2992
  try {
2889
2993
  await handler(transfer);
2890
2994
  } catch (error) {
2891
- this.log("Transfer handler error:", error);
2995
+ logger.debug("Nostr", "Transfer handler error:", error);
2892
2996
  }
2893
2997
  }
2894
2998
  }
@@ -2911,16 +3015,16 @@ var NostrTransportProvider = class {
2911
3015
  },
2912
3016
  timestamp: event.created_at * 1e3
2913
3017
  };
2914
- this.log("Received payment request:", request.id);
3018
+ logger.debug("Nostr", "Received payment request:", request.id);
2915
3019
  for (const handler of this.paymentRequestHandlers) {
2916
3020
  try {
2917
3021
  handler(request);
2918
3022
  } catch (error) {
2919
- this.log("Payment request handler error:", error);
3023
+ logger.debug("Nostr", "Payment request handler error:", error);
2920
3024
  }
2921
3025
  }
2922
3026
  } catch (error) {
2923
- this.log("Failed to handle payment request:", error);
3027
+ logger.debug("Nostr", "Failed to handle payment request:", error);
2924
3028
  }
2925
3029
  }
2926
3030
  async handlePaymentRequestResponse(event) {
@@ -2939,16 +3043,16 @@ var NostrTransportProvider = class {
2939
3043
  },
2940
3044
  timestamp: event.created_at * 1e3
2941
3045
  };
2942
- this.log("Received payment request response:", response.id, "type:", responseData.responseType);
3046
+ logger.debug("Nostr", "Received payment request response:", response.id, "type:", responseData.responseType);
2943
3047
  for (const handler of this.paymentRequestResponseHandlers) {
2944
3048
  try {
2945
3049
  handler(response);
2946
3050
  } catch (error) {
2947
- this.log("Payment request response handler error:", error);
3051
+ logger.debug("Nostr", "Payment request response handler error:", error);
2948
3052
  }
2949
3053
  }
2950
3054
  } catch (error) {
2951
- this.log("Failed to handle payment request response:", error);
3055
+ logger.debug("Nostr", "Failed to handle payment request response:", error);
2952
3056
  }
2953
3057
  }
2954
3058
  handleBroadcast(event) {
@@ -2967,7 +3071,7 @@ var NostrTransportProvider = class {
2967
3071
  try {
2968
3072
  handler(broadcast);
2969
3073
  } catch (error) {
2970
- this.log("Broadcast handler error:", error);
3074
+ logger.debug("Nostr", "Broadcast handler error:", error);
2971
3075
  }
2972
3076
  }
2973
3077
  }
@@ -2977,8 +3081,8 @@ var NostrTransportProvider = class {
2977
3081
  // Private: Event Creation & Publishing
2978
3082
  // ===========================================================================
2979
3083
  async createEvent(kind, content, tags) {
2980
- if (!this.identity) throw new Error("Identity not set");
2981
- if (!this.keyManager) throw new Error("KeyManager not initialized");
3084
+ if (!this.identity) throw new SphereError("Identity not set", "NOT_INITIALIZED");
3085
+ if (!this.keyManager) throw new SphereError("KeyManager not initialized", "NOT_INITIALIZED");
2982
3086
  const signedEvent = NostrEventClass.create(this.keyManager, {
2983
3087
  kind,
2984
3088
  content,
@@ -2996,10 +3100,10 @@ var NostrTransportProvider = class {
2996
3100
  return event;
2997
3101
  }
2998
3102
  async createEncryptedEvent(kind, content, tags) {
2999
- if (!this.keyManager) throw new Error("KeyManager not initialized");
3103
+ if (!this.keyManager) throw new SphereError("KeyManager not initialized", "NOT_INITIALIZED");
3000
3104
  const recipientTag = tags.find((t) => t[0] === "p");
3001
3105
  if (!recipientTag || !recipientTag[1]) {
3002
- throw new Error("No recipient pubkey in tags for encryption");
3106
+ throw new SphereError("No recipient pubkey in tags for encryption", "VALIDATION_ERROR");
3003
3107
  }
3004
3108
  const recipientPubkey = recipientTag[1];
3005
3109
  const encrypted = await NIP04.encryptHex(
@@ -3011,14 +3115,14 @@ var NostrTransportProvider = class {
3011
3115
  }
3012
3116
  async publishEvent(event) {
3013
3117
  if (!this.nostrClient) {
3014
- throw new Error("NostrClient not initialized");
3118
+ throw new SphereError("NostrClient not initialized", "NOT_INITIALIZED");
3015
3119
  }
3016
3120
  const sdkEvent = NostrEventClass.fromJSON(event);
3017
3121
  await this.nostrClient.publishEvent(sdkEvent);
3018
3122
  }
3019
3123
  async fetchPendingEvents() {
3020
3124
  if (!this.nostrClient?.isConnected() || !this.keyManager) {
3021
- throw new Error("Transport not connected");
3125
+ throw new SphereError("Transport not connected", "TRANSPORT_ERROR");
3022
3126
  }
3023
3127
  const nostrPubkey = this.keyManager.getPublicKeyHex();
3024
3128
  const walletFilter = new Filter();
@@ -3061,7 +3165,7 @@ var NostrTransportProvider = class {
3061
3165
  }
3062
3166
  async queryEvents(filterObj) {
3063
3167
  if (!this.nostrClient || !this.nostrClient.isConnected()) {
3064
- throw new Error("No connected relays");
3168
+ throw new SphereError("No connected relays", "TRANSPORT_ERROR");
3065
3169
  }
3066
3170
  const events = [];
3067
3171
  const filter = new Filter(filterObj);
@@ -3070,6 +3174,7 @@ var NostrTransportProvider = class {
3070
3174
  if (subId) {
3071
3175
  this.nostrClient?.unsubscribe(subId);
3072
3176
  }
3177
+ logger.warn("Nostr", `queryEvents timed out after 5s, returning ${events.length} event(s)`, { kinds: filterObj.kinds, limit: filterObj.limit });
3073
3178
  resolve(events);
3074
3179
  }, 5e3);
3075
3180
  const subId = this.nostrClient.subscribe(filter, {
@@ -3099,9 +3204,9 @@ var NostrTransportProvider = class {
3099
3204
  walletSubscriptionId = null;
3100
3205
  chatSubscriptionId = null;
3101
3206
  async subscribeToEvents() {
3102
- this.log("subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
3207
+ logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
3103
3208
  if (!this.identity || !this.keyManager || !this.nostrClient) {
3104
- this.log("subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
3209
+ logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
3105
3210
  return;
3106
3211
  }
3107
3212
  if (this.walletSubscriptionId) {
@@ -3117,7 +3222,7 @@ var NostrTransportProvider = class {
3117
3222
  this.mainSubscriptionId = null;
3118
3223
  }
3119
3224
  const nostrPubkey = this.keyManager.getPublicKeyHex();
3120
- this.log("Subscribing with Nostr pubkey:", nostrPubkey);
3225
+ logger.debug("Nostr", "Subscribing with Nostr pubkey:", nostrPubkey);
3121
3226
  let since;
3122
3227
  if (this.storage) {
3123
3228
  const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_WALLET_EVENT_TS}_${nostrPubkey.slice(0, 16)}`;
@@ -3126,18 +3231,18 @@ var NostrTransportProvider = class {
3126
3231
  if (stored) {
3127
3232
  since = parseInt(stored, 10);
3128
3233
  this.lastEventTs = since;
3129
- this.log("Resuming from stored event timestamp:", since);
3234
+ logger.debug("Nostr", "Resuming from stored event timestamp:", since);
3130
3235
  } else {
3131
3236
  since = Math.floor(Date.now() / 1e3);
3132
- this.log("No stored timestamp, starting from now:", since);
3237
+ logger.debug("Nostr", "No stored timestamp, starting from now:", since);
3133
3238
  }
3134
3239
  } catch (err) {
3135
- this.log("Failed to read last event timestamp, falling back to now:", err);
3240
+ logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
3136
3241
  since = Math.floor(Date.now() / 1e3);
3137
3242
  }
3138
3243
  } else {
3139
3244
  since = Math.floor(Date.now() / 1e3) - 86400;
3140
- this.log("No storage adapter, using 24h fallback");
3245
+ logger.debug("Nostr", "No storage adapter, using 24h fallback");
3141
3246
  }
3142
3247
  const walletFilter = new Filter();
3143
3248
  walletFilter.kinds = [
@@ -3150,7 +3255,7 @@ var NostrTransportProvider = class {
3150
3255
  walletFilter.since = since;
3151
3256
  this.walletSubscriptionId = this.nostrClient.subscribe(walletFilter, {
3152
3257
  onEvent: (event) => {
3153
- this.log("Received wallet event kind:", event.kind, "id:", event.id?.slice(0, 12));
3258
+ logger.debug("Nostr", "Received wallet event kind:", event.kind, "id:", event.id?.slice(0, 12));
3154
3259
  this.handleEvent({
3155
3260
  id: event.id,
3156
3261
  kind: event.kind,
@@ -3162,19 +3267,19 @@ var NostrTransportProvider = class {
3162
3267
  });
3163
3268
  },
3164
3269
  onEndOfStoredEvents: () => {
3165
- this.log("Wallet subscription ready (EOSE)");
3270
+ logger.debug("Nostr", "Wallet subscription ready (EOSE)");
3166
3271
  },
3167
3272
  onError: (_subId, error) => {
3168
- this.log("Wallet subscription error:", error);
3273
+ logger.debug("Nostr", "Wallet subscription error:", error);
3169
3274
  }
3170
3275
  });
3171
- this.log("Wallet subscription created, subId:", this.walletSubscriptionId);
3276
+ logger.debug("Nostr", "Wallet subscription created, subId:", this.walletSubscriptionId);
3172
3277
  const chatFilter = new Filter();
3173
3278
  chatFilter.kinds = [EventKinds.GIFT_WRAP];
3174
3279
  chatFilter["#p"] = [nostrPubkey];
3175
3280
  this.chatSubscriptionId = this.nostrClient.subscribe(chatFilter, {
3176
3281
  onEvent: (event) => {
3177
- this.log("Received chat event kind:", event.kind, "id:", event.id?.slice(0, 12));
3282
+ logger.debug("Nostr", "Received chat event kind:", event.kind, "id:", event.id?.slice(0, 12));
3178
3283
  this.handleEvent({
3179
3284
  id: event.id,
3180
3285
  kind: event.kind,
@@ -3186,13 +3291,13 @@ var NostrTransportProvider = class {
3186
3291
  });
3187
3292
  },
3188
3293
  onEndOfStoredEvents: () => {
3189
- this.log("Chat subscription ready (EOSE)");
3294
+ logger.debug("Nostr", "Chat subscription ready (EOSE)");
3190
3295
  },
3191
3296
  onError: (_subId, error) => {
3192
- this.log("Chat subscription error:", error);
3297
+ logger.debug("Nostr", "Chat subscription error:", error);
3193
3298
  }
3194
3299
  });
3195
- this.log("Chat subscription created, subId:", this.chatSubscriptionId);
3300
+ logger.debug("Nostr", "Chat subscription created, subId:", this.chatSubscriptionId);
3196
3301
  }
3197
3302
  subscribeToTags(tags) {
3198
3303
  if (!this.nostrClient) return;
@@ -3222,7 +3327,7 @@ var NostrTransportProvider = class {
3222
3327
  // Private: Encryption
3223
3328
  // ===========================================================================
3224
3329
  async decryptContent(content, senderPubkey) {
3225
- if (!this.keyManager) throw new Error("KeyManager not initialized");
3330
+ if (!this.keyManager) throw new SphereError("KeyManager not initialized", "NOT_INITIALIZED");
3226
3331
  const decrypted = await NIP04.decryptHex(
3227
3332
  content,
3228
3333
  this.keyManager.getPrivateKeyHex(),
@@ -3252,13 +3357,13 @@ var NostrTransportProvider = class {
3252
3357
  // ===========================================================================
3253
3358
  ensureConnected() {
3254
3359
  if (!this.isConnected()) {
3255
- throw new Error("NostrTransportProvider not connected");
3360
+ throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
3256
3361
  }
3257
3362
  }
3258
3363
  ensureReady() {
3259
3364
  this.ensureConnected();
3260
3365
  if (!this.identity) {
3261
- throw new Error("Identity not set");
3366
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
3262
3367
  }
3263
3368
  }
3264
3369
  emitEvent(event) {
@@ -3266,7 +3371,7 @@ var NostrTransportProvider = class {
3266
3371
  try {
3267
3372
  callback(event);
3268
3373
  } catch (error) {
3269
- this.log("Event callback error:", error);
3374
+ logger.debug("Nostr", "Event callback error:", error);
3270
3375
  }
3271
3376
  }
3272
3377
  }
@@ -3303,11 +3408,6 @@ var NostrTransportProvider = class {
3303
3408
  ephemeralKeys.clear();
3304
3409
  return giftWrap;
3305
3410
  }
3306
- log(...args) {
3307
- if (this.config.debug) {
3308
- console.log("[NostrTransportProvider]", ...args);
3309
- }
3310
- }
3311
3411
  };
3312
3412
 
3313
3413
  // impl/browser/transport/index.ts
@@ -3491,7 +3591,8 @@ var UnicityAggregatorProvider = class {
3491
3591
  proof: response.proof,
3492
3592
  timestamp: Date.now()
3493
3593
  };
3494
- } catch {
3594
+ } catch (error) {
3595
+ logger.warn("Aggregator", "getProof failed", error);
3495
3596
  return null;
3496
3597
  }
3497
3598
  }
@@ -3513,7 +3614,7 @@ var UnicityAggregatorProvider = class {
3513
3614
  }
3514
3615
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
3515
3616
  }
3516
- throw new Error(`Timeout waiting for proof: ${requestId}`);
3617
+ throw new SphereError(`Timeout waiting for proof: ${requestId}`, "TIMEOUT");
3517
3618
  }
3518
3619
  async validateToken(tokenData) {
3519
3620
  this.ensureConnected();
@@ -3572,7 +3673,7 @@ var UnicityAggregatorProvider = class {
3572
3673
  async waitForProofSdk(commitment, signal) {
3573
3674
  this.ensureConnected();
3574
3675
  if (!this.trustBase) {
3575
- throw new Error("Trust base not initialized");
3676
+ throw new SphereError("Trust base not initialized", "NOT_INITIALIZED");
3576
3677
  }
3577
3678
  return await waitInclusionProof(
3578
3679
  this.trustBase,
@@ -3594,7 +3695,8 @@ var UnicityAggregatorProvider = class {
3594
3695
  this.spentCache.set(stateHash, true);
3595
3696
  }
3596
3697
  return spent;
3597
- } catch {
3698
+ } catch (error) {
3699
+ logger.warn("Aggregator", "isSpent check failed, assuming unspent", error);
3598
3700
  return false;
3599
3701
  }
3600
3702
  }
@@ -3612,7 +3714,8 @@ var UnicityAggregatorProvider = class {
3612
3714
  roundNumber: response.state.roundNumber,
3613
3715
  lastUpdated: Date.now()
3614
3716
  };
3615
- } catch {
3717
+ } catch (error) {
3718
+ logger.warn("Aggregator", "getTokenState failed", error);
3616
3719
  return null;
3617
3720
  }
3618
3721
  }
@@ -3672,11 +3775,11 @@ var UnicityAggregatorProvider = class {
3672
3775
  signal: controller.signal
3673
3776
  });
3674
3777
  if (!response.ok) {
3675
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
3778
+ throw new SphereError(`HTTP ${response.status}: ${response.statusText}`, "AGGREGATOR_ERROR");
3676
3779
  }
3677
3780
  const result = await response.json();
3678
3781
  if (result.error) {
3679
- throw new Error(result.error.message ?? "RPC error");
3782
+ throw new SphereError(result.error.message ?? "RPC error", "AGGREGATOR_ERROR");
3680
3783
  }
3681
3784
  return result.result ?? {};
3682
3785
  } finally {
@@ -3688,7 +3791,7 @@ var UnicityAggregatorProvider = class {
3688
3791
  // ===========================================================================
3689
3792
  ensureConnected() {
3690
3793
  if (this.status !== "connected") {
3691
- throw new Error("UnicityAggregatorProvider not connected");
3794
+ throw new SphereError("UnicityAggregatorProvider not connected", "NOT_INITIALIZED");
3692
3795
  }
3693
3796
  }
3694
3797
  emitEvent(event) {
@@ -3700,10 +3803,8 @@ var UnicityAggregatorProvider = class {
3700
3803
  }
3701
3804
  }
3702
3805
  }
3703
- log(...args) {
3704
- if (this.config.debug) {
3705
- console.log("[UnicityAggregatorProvider]", ...args);
3706
- }
3806
+ log(message, ...args) {
3807
+ logger.debug("Aggregator", message, ...args);
3707
3808
  }
3708
3809
  };
3709
3810
  var UnicityOracleProvider = UnicityAggregatorProvider;
@@ -4292,7 +4393,10 @@ var IpfsHttpClient = class {
4292
4393
  { headers: { Accept: "application/octet-stream" } }
4293
4394
  );
4294
4395
  if (!response.ok) {
4295
- const body = await response.text().catch(() => "");
4396
+ const body = await response.text().catch((err) => {
4397
+ logger.debug("IPFS-HTTP", "Failed to read error response body", err);
4398
+ return "";
4399
+ });
4296
4400
  throw new IpfsError(
4297
4401
  `Fetch failed: HTTP ${response.status}`,
4298
4402
  classifyHttpStatus(response.status, body),
@@ -4338,7 +4442,10 @@ var IpfsHttpClient = class {
4338
4442
  { method: "POST" }
4339
4443
  );
4340
4444
  if (!response.ok) {
4341
- const body = await response.text().catch(() => "");
4445
+ const body = await response.text().catch((err) => {
4446
+ logger.debug("IPFS-HTTP", "Failed to read error response body", err);
4447
+ return "";
4448
+ });
4342
4449
  const category = classifyHttpStatus(response.status, body);
4343
4450
  if (category === "NOT_FOUND") return null;
4344
4451
  throw new IpfsError(`Routing API: HTTP ${response.status}`, category, gateway);
@@ -4384,7 +4491,8 @@ var IpfsHttpClient = class {
4384
4491
  }
4385
4492
  }
4386
4493
  return { cid: "", content };
4387
- } catch {
4494
+ } catch (err) {
4495
+ logger.debug("IPFS-HTTP", "IPNS gateway resolution failed", err);
4388
4496
  return null;
4389
4497
  }
4390
4498
  }
@@ -4449,7 +4557,10 @@ var IpfsHttpClient = class {
4449
4557
  { method: "POST", body: formData }
4450
4558
  );
4451
4559
  if (!response.ok) {
4452
- const errorText = await response.text().catch(() => "");
4560
+ const errorText = await response.text().catch((err) => {
4561
+ logger.debug("IPFS-HTTP", "Failed to read error response body", err);
4562
+ return "";
4563
+ });
4453
4564
  throw new IpfsError(
4454
4565
  `IPNS publish: HTTP ${response.status}: ${errorText.slice(0, 100)}`,
4455
4566
  classifyHttpStatus(response.status, errorText),
@@ -4526,9 +4637,7 @@ var IpfsHttpClient = class {
4526
4637
  }
4527
4638
  }
4528
4639
  log(message) {
4529
- if (this.debug) {
4530
- console.log(`[IPFS-HTTP] ${message}`);
4531
- }
4640
+ logger.debug("IPFS-HTTP", message);
4532
4641
  }
4533
4642
  };
4534
4643
 
@@ -4972,10 +5081,12 @@ var IpnsSubscriptionClient = class {
4972
5081
  startFallbackPolling() {
4973
5082
  if (this.fallbackPollInterval || !this.fallbackPollFn || this.destroyed) return;
4974
5083
  this.log(`Starting fallback polling (${this.fallbackPollIntervalMs / 1e3}s interval)`);
4975
- this.fallbackPollFn().catch(() => {
5084
+ this.fallbackPollFn().catch((err) => {
5085
+ logger.warn("IPNS-WS", "Fallback poll error:", err);
4976
5086
  });
4977
5087
  this.fallbackPollInterval = setInterval(() => {
4978
- this.fallbackPollFn?.().catch(() => {
5088
+ this.fallbackPollFn?.().catch((err) => {
5089
+ logger.warn("IPNS-WS", "Fallback poll error:", err);
4979
5090
  });
4980
5091
  }, this.fallbackPollIntervalMs);
4981
5092
  }
@@ -4989,9 +5100,7 @@ var IpnsSubscriptionClient = class {
4989
5100
  // Internal: Logging
4990
5101
  // ---------------------------------------------------------------------------
4991
5102
  log(message) {
4992
- if (this.debugEnabled) {
4993
- console.log(`[IPNS-WS] ${message}`);
4994
- }
5103
+ logger.debug("IPNS-WS", message);
4995
5104
  }
4996
5105
  };
4997
5106
 
@@ -5180,7 +5289,8 @@ var IpfsStorageProvider = class {
5180
5289
  } else {
5181
5290
  this.log("Warning: no healthy gateways found");
5182
5291
  }
5183
- }).catch(() => {
5292
+ }).catch((err) => {
5293
+ logger.warn("IPFS-Storage", "Gateway health check failed (non-fatal):", err);
5184
5294
  });
5185
5295
  this.isShuttingDown = false;
5186
5296
  this.status = "connected";
@@ -5344,7 +5454,7 @@ var IpfsStorageProvider = class {
5344
5454
  };
5345
5455
  const result = await this._doSave(baseData);
5346
5456
  if (!result.success) {
5347
- throw new Error(result.error ?? "Save failed");
5457
+ throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
5348
5458
  }
5349
5459
  this.log(`Flushed successfully: CID=${result.cid}`);
5350
5460
  } catch (error) {
@@ -5584,10 +5694,12 @@ var IpfsStorageProvider = class {
5584
5694
  if (this.flushTimer) {
5585
5695
  clearTimeout(this.flushTimer);
5586
5696
  this.flushTimer = null;
5587
- await this.flushQueue.enqueue(() => this.executeFlush()).catch(() => {
5697
+ await this.flushQueue.enqueue(() => this.executeFlush()).catch((err) => {
5698
+ logger.warn("IPFS-Storage", "Flush on shutdown failed:", err);
5588
5699
  });
5589
5700
  } else if (!this.pendingBuffer.isEmpty) {
5590
- await this.flushQueue.enqueue(() => this.executeFlush()).catch(() => {
5701
+ await this.flushQueue.enqueue(() => this.executeFlush()).catch((err) => {
5702
+ logger.warn("IPFS-Storage", "Flush on shutdown failed:", err);
5591
5703
  });
5592
5704
  } else {
5593
5705
  await this.flushQueue.enqueue(async () => {
@@ -5641,9 +5753,7 @@ var IpfsStorageProvider = class {
5641
5753
  }
5642
5754
  }
5643
5755
  log(message) {
5644
- if (this.debug) {
5645
- console.log(`[IPFS-Storage] ${message}`);
5646
- }
5756
+ logger.debug("IPFS-Storage", message);
5647
5757
  }
5648
5758
  };
5649
5759
 
@@ -5756,7 +5866,7 @@ var CoinGeckoPriceProvider = class {
5756
5866
  const allCovered = uncachedNames.every((n) => this.fetchNames.has(n));
5757
5867
  if (allCovered) {
5758
5868
  if (this.debug) {
5759
- console.log(`[CoinGecko] Deduplicating request, reusing in-flight fetch`);
5869
+ logger.debug("CoinGecko", "Deduplicating request, reusing in-flight fetch");
5760
5870
  }
5761
5871
  const fetched = await this.fetchPromise;
5762
5872
  for (const name of uncachedNames) {
@@ -5795,7 +5905,7 @@ var CoinGeckoPriceProvider = class {
5795
5905
  headers["x-cg-pro-api-key"] = this.apiKey;
5796
5906
  }
5797
5907
  if (this.debug) {
5798
- console.log(`[CoinGecko] Fetching prices for: ${uncachedNames.join(", ")}`);
5908
+ logger.debug("CoinGecko", `Fetching prices for: ${uncachedNames.join(", ")}`);
5799
5909
  }
5800
5910
  const response = await fetch(url, {
5801
5911
  headers,
@@ -5805,7 +5915,7 @@ var CoinGeckoPriceProvider = class {
5805
5915
  if (response.status === 429) {
5806
5916
  this.extendCacheOnRateLimit(uncachedNames);
5807
5917
  }
5808
- throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
5918
+ throw new SphereError(`CoinGecko API error: ${response.status} ${response.statusText}`, "NETWORK_ERROR");
5809
5919
  }
5810
5920
  const data = await response.json();
5811
5921
  for (const [name, values] of Object.entries(data)) {
@@ -5835,12 +5945,12 @@ var CoinGeckoPriceProvider = class {
5835
5945
  }
5836
5946
  }
5837
5947
  if (this.debug) {
5838
- console.log(`[CoinGecko] Fetched ${result.size} prices`);
5948
+ logger.debug("CoinGecko", `Fetched ${result.size} prices`);
5839
5949
  }
5840
5950
  this.saveToStorage();
5841
5951
  } catch (error) {
5842
5952
  if (this.debug) {
5843
- console.warn("[CoinGecko] Fetch failed, using stale cache:", error);
5953
+ logger.warn("CoinGecko", "Fetch failed, using stale cache:", error);
5844
5954
  }
5845
5955
  for (const name of uncachedNames) {
5846
5956
  const stale = this.cache.get(name);
@@ -5890,7 +6000,7 @@ var CoinGeckoPriceProvider = class {
5890
6000
  }
5891
6001
  }
5892
6002
  if (this.debug) {
5893
- console.log(`[CoinGecko] Loaded ${Object.keys(data).length} prices from persistent cache`);
6003
+ logger.debug("CoinGecko", `Loaded ${Object.keys(data).length} prices from persistent cache`);
5894
6004
  }
5895
6005
  } catch {
5896
6006
  }
@@ -5907,8 +6017,7 @@ var CoinGeckoPriceProvider = class {
5907
6017
  Promise.all([
5908
6018
  this.storage.set(STORAGE_KEYS_GLOBAL.PRICE_CACHE, JSON.stringify(data)),
5909
6019
  this.storage.set(STORAGE_KEYS_GLOBAL.PRICE_CACHE_TS, String(Date.now()))
5910
- ]).catch(() => {
5911
- });
6020
+ ]).catch((err) => logger.debug("Price", "Cache save failed (non-critical)", err));
5912
6021
  }
5913
6022
  // ===========================================================================
5914
6023
  // Rate-limit handling
@@ -5927,7 +6036,7 @@ var CoinGeckoPriceProvider = class {
5927
6036
  }
5928
6037
  }
5929
6038
  if (this.debug) {
5930
- console.warn(`[CoinGecko] Rate-limited (429), extended cache TTL by ${backoffMs / 1e3}s`);
6039
+ logger.warn("CoinGecko", `Rate-limited (429), extended cache TTL by ${backoffMs / 1e3}s`);
5931
6040
  }
5932
6041
  }
5933
6042
  async getPrice(tokenName) {
@@ -5945,7 +6054,7 @@ function createPriceProvider(config) {
5945
6054
  case "coingecko":
5946
6055
  return new CoinGeckoPriceProvider(config);
5947
6056
  default:
5948
- throw new Error(`Unsupported price platform: ${String(config.platform)}`);
6057
+ throw new SphereError(`Unsupported price platform: ${String(config.platform)}`, "INVALID_CONFIG");
5949
6058
  }
5950
6059
  }
5951
6060
 
@@ -6170,14 +6279,12 @@ var TokenRegistry = class _TokenRegistry {
6170
6279
  clearTimeout(timer);
6171
6280
  }
6172
6281
  if (!response.ok) {
6173
- console.warn(
6174
- `[TokenRegistry] Remote fetch failed: HTTP ${response.status} ${response.statusText}`
6175
- );
6282
+ logger.warn("TokenRegistry", `Remote fetch failed: HTTP ${response.status} ${response.statusText}`);
6176
6283
  return false;
6177
6284
  }
6178
6285
  const data = await response.json();
6179
6286
  if (!this.isValidDefinitionsArray(data)) {
6180
- console.warn("[TokenRegistry] Remote data is not a valid token definitions array");
6287
+ logger.warn("TokenRegistry", "Remote data is not a valid token definitions array");
6181
6288
  return false;
6182
6289
  }
6183
6290
  const definitions = data;
@@ -6187,7 +6294,7 @@ var TokenRegistry = class _TokenRegistry {
6187
6294
  return true;
6188
6295
  } catch (error) {
6189
6296
  const message = error instanceof Error ? error.message : String(error);
6190
- console.warn(`[TokenRegistry] Remote refresh failed: ${message}`);
6297
+ logger.warn("TokenRegistry", `Remote refresh failed: ${message}`);
6191
6298
  return false;
6192
6299
  }
6193
6300
  }
@@ -6493,6 +6600,12 @@ function resolveTokenSyncConfig(network, config) {
6493
6600
  }
6494
6601
  function createBrowserProviders(config) {
6495
6602
  const network = config?.network ?? "mainnet";
6603
+ if (config?.debug !== void 0) {
6604
+ logger.configure({ debug: config.debug });
6605
+ }
6606
+ if (config?.transport?.debug) logger.setTagDebug("Nostr", true);
6607
+ if (config?.oracle?.debug) logger.setTagDebug("Aggregator", true);
6608
+ if (config?.price?.debug) logger.setTagDebug("Price", true);
6496
6609
  const transportConfig = resolveTransportConfig(network, config?.transport);
6497
6610
  const oracleConfig = resolveOracleConfig(network, config?.oracle);
6498
6611
  const l1Config = resolveL1Config(network, config?.l1);